Skip to content

Commit 1a1024a

Browse files
committed
Add tests and fix bugs
1 parent c87767e commit 1a1024a

File tree

6 files changed

+88
-10
lines changed

6 files changed

+88
-10
lines changed

packages/grpc-js-xds/src/xds-bootstrap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ function validateFileWatcherPluginConfig(obj: any, instanceName: string): FileWa
345345
return {
346346
certificateFile: obj.certificate_file,
347347
privateKeyFile: obj.private_key_file,
348-
caCertificateFile: obj.caCertificateFile,
348+
caCertificateFile: obj.ca_certificate_file,
349349
refreshIntervalMs: durationToMs(refreshDuration)
350350
};
351351
}

packages/grpc-js-xds/src/xds-resource-type/listener-resource-type.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,34 +143,46 @@ function validateFilterChain(context: XdsDecodeContext, filterChain: FilterChain
143143
if (filterChain.transport_socket) {
144144
const transportSocket = filterChain.transport_socket;
145145
if (transportSocket.name !== 'envoy.transport_sockets.tls') {
146+
trace('Wrong transportSocket.name');
147+
return false;
148+
}
149+
if (!transportSocket.typed_config) {
150+
trace('No typed_config');
146151
return false;
147152
}
148153
if (transportSocket.typed_config?.type_url !== DOWNSTREAM_TLS_CONTEXT_TYPE_URL) {
154+
trace(`Wrong typed_config type_url: ${transportSocket.typed_config?.type_url}`);
149155
return false;
150156
}
151157
const downstreamTlsContext = decodeSingleResource(DOWNSTREAM_TLS_CONTEXT_TYPE_URL, transportSocket.typed_config.value);
152158
if (!downstreamTlsContext.common_tls_context) {
159+
trace('No common_tls_context');
153160
return false;
154161
}
155162
const commonTlsContext = downstreamTlsContext.common_tls_context;
156163
if (!commonTlsContext.tls_certificate_provider_instance) {
164+
trace('No tls_certificate_provider_instance');
157165
return false;
158166
}
159167
if (!(commonTlsContext.tls_certificate_provider_instance.instance_name in context.bootstrap.certificateProviders)) {
168+
trace('Unmatched tls_certificate_provider_instance instance_name');
160169
return false;
161170
}
162171
let validationContext: CertificateValidationContext__Output | null;
163172
switch (commonTlsContext.validation_context_type) {
164173
case 'validation_context_sds_secret_config':
174+
trace('Unexpected validation_context_sds_secret_config')
165175
return false;
166176
case 'validation_context':
167177
if (!commonTlsContext.validation_context) {
178+
trace('Missing validation_context');
168179
return false;
169180
}
170181
validationContext = commonTlsContext.validation_context;
171182
break;
172183
case 'combined_validation_context':
173184
if (!commonTlsContext.combined_validation_context) {
185+
trace('Missing combined_validation_context')
174186
return false;
175187
}
176188
validationContext = commonTlsContext.combined_validation_context.default_validation_context;
@@ -179,21 +191,27 @@ function validateFilterChain(context: XdsDecodeContext, filterChain: FilterChain
179191
return false;
180192
}
181193
if (validationContext?.ca_certificate_provider_instance && !(validationContext.ca_certificate_provider_instance.instance_name in context.bootstrap.certificateProviders)) {
194+
trace('Unmatched validationContext instance_name');
182195
return false;
183196
}
184197
if (downstreamTlsContext.require_client_certificate && !validationContext) {
198+
trace('require_client_certificate set without validationContext');
185199
return false;
186200
}
187201
if (commonTlsContext.tls_params) {
202+
trace('tls_params set');
188203
return false;
189204
}
190205
if (commonTlsContext.custom_handshaker) {
206+
trace('custom_handshaker set');
191207
return false;
192208
}
193209
if (downstreamTlsContext.require_sni?.value) {
210+
trace('require_sni set');
194211
return false;
195212
}
196213
if (downstreamTlsContext.ocsp_staple_policy !== 'LENIENT_STAPLING') {
214+
trace('Unexpected ocsp_staple_policy');
197215
return false;
198216
}
199217
}

packages/grpc-js-xds/test/test-xds-credentials.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,64 @@ describe('Server xDS Credentials', () => {
7575
common_tls_context: {
7676
tls_certificate_provider_instance: {
7777
instance_name: 'test_certificates'
78+
},
79+
validation_context: {}
80+
},
81+
ocsp_staple_policy: 'LENIENT_STAPLING'
82+
}
83+
const baseServerListener: Listener = {
84+
default_filter_chain: {
85+
filter_chain_match: {
86+
source_type: 'SAME_IP_OR_LOOPBACK'
87+
},
88+
transport_socket: {
89+
name: 'envoy.transport_sockets.tls',
90+
typed_config: downstreamTlsContext
7891
}
7992
}
8093
}
94+
const serverRoute = new FakeServerRoute(backend.getPort(), 'serverRoute', baseServerListener);
95+
xdsServer.setRdsResource(serverRoute.getRouteConfiguration());
96+
xdsServer.setLdsResource(serverRoute.getListener());
97+
xdsServer.addResponseListener((typeUrl, responseState) => {
98+
if (responseState.state === 'NACKED') {
99+
client?.stopCalls();
100+
assert.fail(`Client NACKED ${typeUrl} resource with message ${responseState.errorMessage}`);
101+
}
102+
});
103+
const cluster = new FakeEdsCluster('cluster1', 'endpoint1', [{backends: [backend], locality:{region: 'region1'}}]);
104+
const routeGroup = new FakeRouteGroup('listener1', 'route1', [{cluster: cluster}]);
105+
await routeGroup.startAllBackends(xdsServer);
106+
xdsServer.setEdsResource(cluster.getEndpointConfig());
107+
xdsServer.setCdsResource(cluster.getClusterConfig());
108+
xdsServer.setRdsResource(routeGroup.getRouteConfiguration());
109+
xdsServer.setLdsResource(routeGroup.getListener());
110+
client = XdsTestClient.createFromServer('listener1', xdsServer, credentials.createSsl(ca), {
111+
'grpc.ssl_target_name_override': 'foo.test.google.fr',
112+
'grpc.default_authority': 'foo.test.google.fr',
113+
});
114+
const error = await client.sendOneCallAsync();
115+
assert.strictEqual(error, null);
116+
});
117+
it('Should use identity and CA certificates when configured', async () => {
118+
const [backend] = await createBackends(1, true, new XdsServerCredentials(ServerCredentials.createInsecure()));
119+
const downstreamTlsContext: DownstreamTlsContext & AnyExtension = {
120+
'@type': DOWNSTREAM_TLS_CONTEXT_TYPE_URL,
121+
common_tls_context: {
122+
tls_certificate_provider_instance: {
123+
instance_name: 'test_certificates'
124+
},
125+
validation_context: {
126+
ca_certificate_provider_instance: {
127+
instance_name: 'test_certificates'
128+
}
129+
}
130+
},
131+
ocsp_staple_policy: 'LENIENT_STAPLING',
132+
require_client_certificate: {
133+
value: true
134+
}
135+
}
81136
const baseServerListener: Listener = {
82137
default_filter_chain: {
83138
filter_chain_match: {
@@ -105,7 +160,10 @@ describe('Server xDS Credentials', () => {
105160
xdsServer.setCdsResource(cluster.getClusterConfig());
106161
xdsServer.setRdsResource(routeGroup.getRouteConfiguration());
107162
xdsServer.setLdsResource(routeGroup.getListener());
108-
client = XdsTestClient.createFromServer('listener1', xdsServer, credentials.createSsl(ca));
163+
client = XdsTestClient.createFromServer('listener1', xdsServer, credentials.createSsl(ca, key, cert), {
164+
'grpc.ssl_target_name_override': 'foo.test.google.fr',
165+
'grpc.default_authority': 'foo.test.google.fr',
166+
});
109167
const error = await client.sendOneCallAsync();
110168
assert.strictEqual(error, null);
111169
});

packages/grpc-js-xds/test/xds-server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const loadedProtos = loadPackageDefinition(loadSync(
5353
'envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.proto',
5454
'envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.proto',
5555
'envoy/extensions/load_balancing_policies/pick_first/v3/pick_first.proto',
56+
'envoy/extensions/transport_sockets/tls/v3/tls.proto',
5657
'xds/type/v3/typed_struct.proto'
5758
],
5859
{

packages/grpc-js/src/certificate-provider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export class FileWatcherCertificateProvider implements CertificateProvider {
9090
if (!this.refreshTimer) {
9191
return;
9292
}
93-
trace('File watcher read certificates certificate' + (certificateResult ? '!=' : '==') + 'null, privateKey' + (privateKeyResult ? '!=' : '==') + 'null, CA certificate' + (caCertificateResult ? '!=' : '==') + 'null');
93+
trace('File watcher read certificates certificate ' + certificateResult.status + ', privateKey ' + privateKeyResult.status + ', CA certificate ' + caCertificateResult.status);
9494
this.lastUpdateTime = new Date();
9595
this.fileResultPromise = null;
9696
if (certificateResult.status === 'fulfilled' && privateKeyResult.status === 'fulfilled') {

packages/grpc-js/src/server-credentials.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -225,24 +225,24 @@ class CertificateProviderServerCredentials extends ServerCredentials {
225225
private caCertificateUpdateListener: CaCertificateUpdateListener = this.handleCaCertificateUpdate.bind(this);
226226
private identityCertificateUpdateListener: IdentityCertificateUpdateListener = this.handleIdentityCertitificateUpdate.bind(this);
227227
constructor(
228-
private caCertificateProvider: CertificateProvider,
229-
private identityCertificateProvider: CertificateProvider | null,
228+
private identityCertificateProvider: CertificateProvider,
229+
private caCertificateProvider: CertificateProvider | null,
230230
private requireClientCertificate: boolean
231231
) {
232232
super();
233233
}
234234
_addWatcher(watcher: SecureContextWatcher): void {
235235
if (this.getWatcherCount() === 0) {
236-
this.caCertificateProvider.addCaCertificateListener(this.caCertificateUpdateListener);
237-
this.identityCertificateProvider?.addIdentityCertificateListener(this.identityCertificateUpdateListener);
236+
this.caCertificateProvider?.addCaCertificateListener(this.caCertificateUpdateListener);
237+
this.identityCertificateProvider.addIdentityCertificateListener(this.identityCertificateUpdateListener);
238238
}
239239
super._addWatcher(watcher);
240240
}
241241
_removeWatcher(watcher: SecureContextWatcher): void {
242242
super._removeWatcher(watcher);
243243
if (this.getWatcherCount() === 0) {
244-
this.caCertificateProvider.removeCaCertificateListener(this.caCertificateUpdateListener);
245-
this.identityCertificateProvider?.removeIdentityCertificateListener(this.identityCertificateUpdateListener);
244+
this.caCertificateProvider?.removeCaCertificateListener(this.caCertificateUpdateListener);
245+
this.identityCertificateProvider.removeIdentityCertificateListener(this.identityCertificateUpdateListener);
246246
}
247247
}
248248
_isSecure(): boolean {
@@ -279,7 +279,8 @@ class CertificateProviderServerCredentials extends ServerCredentials {
279279
}
280280

281281
private finalizeUpdate() {
282-
this.updateSecureContextOptions(this.calculateSecureContextOptions());
282+
const secureContextOptions = this.calculateSecureContextOptions();
283+
this.updateSecureContextOptions(secureContextOptions);
283284
}
284285

285286
private handleCaCertificateUpdate(update: CaCertificateUpdate | null) {

0 commit comments

Comments
 (0)