Skip to content

Commit 0b32c26

Browse files
snowpjoeyb
authored andcommitted
cache/server: implement sds (#77)
Implements SecretDiscoveryService Fixes #76 Signed-off-by: Snow Pettersen <[email protected]>
1 parent 8274eed commit 0b32c26

File tree

9 files changed

+136
-15
lines changed

9 files changed

+136
-15
lines changed

cache/src/main/java/io/envoyproxy/controlplane/cache/Resources.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import envoy.api.v2.Eds.ClusterLoadAssignment;
1818
import envoy.api.v2.Lds.Listener;
1919
import envoy.api.v2.Rds.RouteConfiguration;
20+
import envoy.api.v2.auth.Cert.Secret;
2021
import envoy.api.v2.listener.Listener.Filter;
2122
import envoy.api.v2.listener.Listener.FilterChain;
2223
import envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManagerOuterClass.HttpConnectionManager;
@@ -40,18 +41,21 @@ public class Resources {
4041
public static final String ENDPOINT_TYPE_URL = TYPE_URL_PREFIX + "ClusterLoadAssignment";
4142
public static final String LISTENER_TYPE_URL = TYPE_URL_PREFIX + "Listener";
4243
public static final String ROUTE_TYPE_URL = TYPE_URL_PREFIX + "RouteConfiguration";
44+
public static final String SECRET_TYPE_URL = TYPE_URL_PREFIX + "auth.Secret";
4345

4446
public static final List<String> TYPE_URLS = ImmutableList.of(
4547
CLUSTER_TYPE_URL,
4648
ENDPOINT_TYPE_URL,
4749
LISTENER_TYPE_URL,
48-
ROUTE_TYPE_URL);
50+
ROUTE_TYPE_URL,
51+
SECRET_TYPE_URL);
4952

5053
public static final Map<String, Class<? extends Message>> RESOURCE_TYPE_BY_URL = ImmutableMap.of(
5154
CLUSTER_TYPE_URL, Cluster.class,
5255
ENDPOINT_TYPE_URL, ClusterLoadAssignment.class,
5356
LISTENER_TYPE_URL, Listener.class,
54-
ROUTE_TYPE_URL, RouteConfiguration.class
57+
ROUTE_TYPE_URL, RouteConfiguration.class,
58+
SECRET_TYPE_URL, Secret.class
5559
);
5660

5761
/**
@@ -76,6 +80,10 @@ public static String getResourceName(Message resource) {
7680
return ((RouteConfiguration) resource).getName();
7781
}
7882

83+
if (resource instanceof Secret) {
84+
return ((Secret) resource).getName();
85+
}
86+
7987
return "";
8088
}
8189

cache/src/main/java/io/envoyproxy/controlplane/cache/Snapshot.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static io.envoyproxy.controlplane.cache.Resources.ENDPOINT_TYPE_URL;
55
import static io.envoyproxy.controlplane.cache.Resources.LISTENER_TYPE_URL;
66
import static io.envoyproxy.controlplane.cache.Resources.ROUTE_TYPE_URL;
7+
import static io.envoyproxy.controlplane.cache.Resources.SECRET_TYPE_URL;
78

89
import com.google.auto.value.AutoValue;
910
import com.google.common.base.Strings;
@@ -13,6 +14,7 @@
1314
import envoy.api.v2.Eds.ClusterLoadAssignment;
1415
import envoy.api.v2.Lds.Listener;
1516
import envoy.api.v2.Rds.RouteConfiguration;
17+
import envoy.api.v2.auth.Cert.Secret;
1618
import java.util.Map;
1719
import java.util.Set;
1820

@@ -37,13 +39,15 @@ public static Snapshot create(
3739
Iterable<ClusterLoadAssignment> endpoints,
3840
Iterable<Listener> listeners,
3941
Iterable<RouteConfiguration> routes,
42+
Iterable<Secret> secrets,
4043
String version) {
4144

4245
return new AutoValue_Snapshot(
4346
SnapshotResources.create(clusters, version),
4447
SnapshotResources.create(endpoints, version),
4548
SnapshotResources.create(listeners, version),
46-
SnapshotResources.create(routes, version));
49+
SnapshotResources.create(routes, version),
50+
SnapshotResources.create(secrets, version));
4751
}
4852

4953
/**
@@ -66,13 +70,17 @@ public static Snapshot create(
6670
Iterable<Listener> listeners,
6771
String listenersVersion,
6872
Iterable<RouteConfiguration> routes,
69-
String routesVersion) {
73+
String routesVersion,
74+
Iterable<Secret> secrets,
75+
String secretsVersion) {
7076

77+
// TODO(snowp): add a builder alternative
7178
return new AutoValue_Snapshot(
7279
SnapshotResources.create(clusters, clustersVersion),
7380
SnapshotResources.create(endpoints, endpointsVersion),
7481
SnapshotResources.create(listeners, listenersVersion),
75-
SnapshotResources.create(routes, routesVersion));
82+
SnapshotResources.create(routes, routesVersion),
83+
SnapshotResources.create(secrets, secretsVersion));
7684
}
7785

7886
/**
@@ -95,6 +103,11 @@ public static Snapshot create(
95103
*/
96104
public abstract SnapshotResources<RouteConfiguration> routes();
97105

106+
/**
107+
* Returns all secret items in the SDS payload.
108+
*/
109+
public abstract SnapshotResources<Secret> secrets();
110+
98111
/**
99112
* Asserts that all dependent resources are included in the snapshot. All EDS resources are listed by name in CDS
100113
* resources, and all RDS resources are listed by name in LDS resources.
@@ -133,6 +146,8 @@ public void ensureConsistent() throws SnapshotConsistencyException {
133146
return listeners().resources();
134147
case ROUTE_TYPE_URL:
135148
return routes().resources();
149+
case SECRET_TYPE_URL:
150+
return secrets().resources();
136151
default:
137152
return ImmutableMap.of();
138153
}
@@ -157,6 +172,8 @@ public String version(String typeUrl) {
157172
return listeners().version();
158173
case ROUTE_TYPE_URL:
159174
return routes().version();
175+
case SECRET_TYPE_URL:
176+
return secrets().version();
160177
default:
161178
return "";
162179
}

cache/src/main/java/io/envoyproxy/controlplane/cache/TestResources.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
import envoy.api.v2.Eds.ClusterLoadAssignment;
1313
import envoy.api.v2.Lds.Listener;
1414
import envoy.api.v2.Rds.RouteConfiguration;
15+
import envoy.api.v2.auth.Cert;
16+
import envoy.api.v2.auth.Cert.TlsCertificate;
1517
import envoy.api.v2.core.AddressOuterClass.Address;
1618
import envoy.api.v2.core.AddressOuterClass.SocketAddress;
1719
import envoy.api.v2.core.AddressOuterClass.SocketAddress.Protocol;
20+
import envoy.api.v2.core.Base.DataSource;
1821
import envoy.api.v2.core.ConfigSourceOuterClass.AggregatedConfigSource;
1922
import envoy.api.v2.core.ConfigSourceOuterClass.ApiConfigSource;
2023
import envoy.api.v2.core.ConfigSourceOuterClass.ApiConfigSource.ApiType;
@@ -171,6 +174,20 @@ public static RouteConfiguration createRoute(String routeName, String clusterNam
171174
.build();
172175
}
173176

177+
/**
178+
* Returns a new test secret.
179+
*
180+
* @param secretName name of the new secret
181+
*/
182+
public static Cert.Secret createSecret(String secretName) {
183+
return Cert.Secret.newBuilder()
184+
.setName(secretName)
185+
.setTlsCertificate(TlsCertificate.newBuilder()
186+
.setPrivateKey(DataSource.newBuilder()
187+
.setInlineString("secret!")))
188+
.build();
189+
}
190+
174191
private static Struct messageAsStruct(MessageOrBuilder message) {
175192
try {
176193
String json = JsonFormat.printer()

cache/src/test/java/io/envoyproxy/controlplane/cache/SimpleCacheTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import envoy.api.v2.Eds.ClusterLoadAssignment;
1010
import envoy.api.v2.Lds.Listener;
1111
import envoy.api.v2.Rds.RouteConfiguration;
12+
import envoy.api.v2.auth.Cert.Secret;
1213
import envoy.api.v2.core.Base.Node;
1314
import java.util.Collections;
1415
import java.util.LinkedList;
@@ -26,6 +27,7 @@ public class SimpleCacheTest {
2627
private static final String SECONDARY_CLUSTER_NAME = "cluster1";
2728
private static final String LISTENER_NAME = "listener0";
2829
private static final String ROUTE_NAME = "route0";
30+
private static final String SECRET_NAME = "secret0";
2931

3032
private static final String VERSION1 = UUID.randomUUID().toString();
3133
private static final String VERSION2 = UUID.randomUUID().toString();
@@ -35,13 +37,15 @@ public class SimpleCacheTest {
3537
ImmutableList.of(ClusterLoadAssignment.getDefaultInstance()),
3638
ImmutableList.of(Listener.newBuilder().setName(LISTENER_NAME).build()),
3739
ImmutableList.of(RouteConfiguration.newBuilder().setName(ROUTE_NAME).build()),
40+
ImmutableList.of(Secret.newBuilder().setName(ROUTE_NAME).build()),
3841
VERSION1);
3942

4043
private static final Snapshot SNAPSHOT2 = Snapshot.create(
4144
ImmutableList.of(Cluster.newBuilder().setName(CLUSTER_NAME).build()),
4245
ImmutableList.of(ClusterLoadAssignment.getDefaultInstance()),
4346
ImmutableList.of(Listener.newBuilder().setName(LISTENER_NAME).build()),
4447
ImmutableList.of(RouteConfiguration.newBuilder().setName(ROUTE_NAME).build()),
48+
ImmutableList.of(Secret.newBuilder().setName(ROUTE_NAME).build()),
4549
VERSION2);
4650

4751
private static final Snapshot MULTIPLE_RESOURCES_SNAPSHOT2 = Snapshot.create(
@@ -51,6 +55,7 @@ public class SimpleCacheTest {
5155
ClusterLoadAssignment.newBuilder().setClusterName(SECONDARY_CLUSTER_NAME).build()),
5256
ImmutableList.of(Listener.newBuilder().setName(LISTENER_NAME).build()),
5357
ImmutableList.of(RouteConfiguration.newBuilder().setName(ROUTE_NAME).build()),
58+
ImmutableList.of(Secret.newBuilder().setName(ROUTE_NAME).build()),
5459
VERSION2);
5560

5661
@Test

cache/src/test/java/io/envoyproxy/controlplane/cache/SnapshotTest.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import envoy.api.v2.Eds.ClusterLoadAssignment;
1515
import envoy.api.v2.Lds.Listener;
1616
import envoy.api.v2.Rds.RouteConfiguration;
17+
import envoy.api.v2.auth.Cert.Secret;
1718
import java.util.Map;
1819
import java.util.UUID;
1920
import java.util.concurrent.ThreadLocalRandom;
@@ -25,6 +26,7 @@ public class SnapshotTest {
2526
private static final String CLUSTER_NAME = "cluster0";
2627
private static final String LISTENER_NAME = "listener0";
2728
private static final String ROUTE_NAME = "route0";
29+
private static final String SECRET_NAME = "secret0";
2830

2931
private static final int ENDPOINT_PORT = ThreadLocalRandom.current().nextInt(10000, 20000);
3032
private static final int LISTENER_PORT = ThreadLocalRandom.current().nextInt(20000, 30000);
@@ -33,6 +35,7 @@ public class SnapshotTest {
3335
private static final ClusterLoadAssignment ENDPOINT = TestResources.createEndpoint(CLUSTER_NAME, ENDPOINT_PORT);
3436
private static final Listener LISTENER = TestResources.createListener(ADS, LISTENER_NAME, LISTENER_PORT, ROUTE_NAME);
3537
private static final RouteConfiguration ROUTE = TestResources.createRoute(ROUTE_NAME, CLUSTER_NAME);
38+
private static final Secret SECRET = TestResources.createSecret(SECRET_NAME);
3639

3740
@Test
3841
public void createSingleVersionSetsResourcesCorrectly() {
@@ -43,6 +46,7 @@ public void createSingleVersionSetsResourcesCorrectly() {
4346
ImmutableList.of(ENDPOINT),
4447
ImmutableList.of(LISTENER),
4548
ImmutableList.of(ROUTE),
49+
ImmutableList.of(SECRET),
4650
version);
4751

4852
assertThat(snapshot.clusters().resources())
@@ -73,12 +77,15 @@ public void createSeparateVersionsSetsResourcesCorrectly() {
7377
final String endpointsVersion = UUID.randomUUID().toString();
7478
final String listenersVersion = UUID.randomUUID().toString();
7579
final String routesVersion = UUID.randomUUID().toString();
80+
final String secretsVersion = UUID.randomUUID().toString();
7681

7782
Snapshot snapshot = Snapshot.create(
7883
ImmutableList.of(CLUSTER), clustersVersion,
7984
ImmutableList.of(ENDPOINT), endpointsVersion,
8085
ImmutableList.of(LISTENER), listenersVersion,
81-
ImmutableList.of(ROUTE), routesVersion);
86+
ImmutableList.of(ROUTE), routesVersion,
87+
ImmutableList.of(SECRET), secretsVersion
88+
);
8289

8390
assertThat(snapshot.clusters().resources())
8491
.containsEntry(CLUSTER_NAME, CLUSTER)
@@ -110,6 +117,7 @@ public void resourcesReturnsExpectedResources() {
110117
ImmutableList.of(ENDPOINT),
111118
ImmutableList.of(LISTENER),
112119
ImmutableList.of(ROUTE),
120+
ImmutableList.of(SECRET),
113121
UUID.randomUUID().toString());
114122

115123
// We have to do some lame casting to appease java's compiler, otherwise it fails to compile due to limitations with
@@ -145,6 +153,7 @@ public void versionReturnsExpectedVersion() {
145153
ImmutableList.of(ENDPOINT),
146154
ImmutableList.of(LISTENER),
147155
ImmutableList.of(ROUTE),
156+
ImmutableList.of(SECRET),
148157
version);
149158

150159
assertThat(snapshot.version(CLUSTER_TYPE_URL)).isEqualTo(version);
@@ -164,6 +173,7 @@ public void ensureConsistentReturnsWithoutExceptionForConsistentSnapshot() throw
164173
ImmutableList.of(ENDPOINT),
165174
ImmutableList.of(LISTENER),
166175
ImmutableList.of(ROUTE),
176+
ImmutableList.of(SECRET),
167177
UUID.randomUUID().toString());
168178

169179
snapshot.ensureConsistent();
@@ -176,6 +186,7 @@ public void ensureConsistentThrowsIfEndpointOrRouteRefCountMismatch() {
176186
ImmutableList.of(),
177187
ImmutableList.of(LISTENER),
178188
ImmutableList.of(ROUTE),
189+
ImmutableList.of(SECRET),
179190
UUID.randomUUID().toString());
180191

181192
assertThatThrownBy(snapshot1::ensureConsistent)
@@ -191,6 +202,7 @@ public void ensureConsistentThrowsIfEndpointOrRouteRefCountMismatch() {
191202
ImmutableList.of(ENDPOINT),
192203
ImmutableList.of(LISTENER),
193204
ImmutableList.of(),
205+
ImmutableList.of(SECRET),
194206
UUID.randomUUID().toString());
195207

196208
assertThatThrownBy(snapshot2::ensureConsistent)
@@ -212,6 +224,7 @@ public void ensureConsistentThrowsIfEndpointOrRouteNamesMismatch() {
212224
ImmutableList.of(TestResources.createEndpoint(otherClusterName, ENDPOINT_PORT)),
213225
ImmutableList.of(LISTENER),
214226
ImmutableList.of(ROUTE),
227+
ImmutableList.of(SECRET),
215228
UUID.randomUUID().toString());
216229

217230
assertThatThrownBy(snapshot1::ensureConsistent)
@@ -228,6 +241,7 @@ public void ensureConsistentThrowsIfEndpointOrRouteNamesMismatch() {
228241
ImmutableList.of(ENDPOINT),
229242
ImmutableList.of(LISTENER),
230243
ImmutableList.of(TestResources.createRoute(otherRouteName, CLUSTER_NAME)),
244+
ImmutableList.of(SECRET),
231245
UUID.randomUUID().toString());
232246

233247
assertThatThrownBy(snapshot2::ensureConsistent)

server/src/main/java/io/envoyproxy/controlplane/server/DiscoveryServer.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import envoy.api.v2.ListenerDiscoveryServiceGrpc.ListenerDiscoveryServiceImplBase;
1111
import envoy.api.v2.RouteDiscoveryServiceGrpc.RouteDiscoveryServiceImplBase;
1212
import envoy.service.discovery.v2.AggregatedDiscoveryServiceGrpc.AggregatedDiscoveryServiceImplBase;
13+
import envoy.service.discovery.v2.SecretDiscoveryServiceGrpc;
1314
import io.envoyproxy.controlplane.cache.ConfigWatcher;
1415
import io.envoyproxy.controlplane.cache.Resources;
1516
import io.envoyproxy.controlplane.cache.Response;
@@ -115,6 +116,18 @@ public StreamObserver<DiscoveryRequest> streamRoutes(
115116
};
116117
}
117118

119+
/**
120+
* Returns a SDS implementation that uses this server's {@link ConfigWatcher}.
121+
*/
122+
public SecretDiscoveryServiceGrpc.SecretDiscoveryServiceImplBase getSecretDiscoveryServiceImpl() {
123+
return new SecretDiscoveryServiceGrpc.SecretDiscoveryServiceImplBase() {
124+
@Override public StreamObserver<DiscoveryRequest> streamSecrets(
125+
StreamObserver<DiscoveryResponse> responseObserver) {
126+
return createRequestHandler(responseObserver, false, Resources.SECRET_TYPE_URL);
127+
}
128+
};
129+
}
130+
118131
private StreamObserver<DiscoveryRequest> createRequestHandler(
119132
StreamObserver<DiscoveryResponse> responseObserver,
120133
boolean ads,

0 commit comments

Comments
 (0)