From 5f12dc233f319b7effea46540421bde5deb3132c Mon Sep 17 00:00:00 2001 From: Michael Lumish Date: Wed, 19 Feb 2025 11:29:03 -0800 Subject: [PATCH] Add more trace logging --- .../interop/test-client.Dockerfile | 2 +- packages/grpc-js-xds/src/server.ts | 2 + packages/grpc-js-xds/src/xds-credentials.ts | 6 +- .../grpc-js-xds/test/test-xds-credentials.ts | 77 +++++++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/packages/grpc-js-xds/interop/test-client.Dockerfile b/packages/grpc-js-xds/interop/test-client.Dockerfile index f8bb3aaf..db608f95 100644 --- a/packages/grpc-js-xds/interop/test-client.Dockerfile +++ b/packages/grpc-js-xds/interop/test-client.Dockerfile @@ -42,7 +42,7 @@ COPY --from=build /node/src/grpc-node/packages/grpc-js ./packages/grpc-js/ COPY --from=build /node/src/grpc-node/packages/grpc-js-xds ./packages/grpc-js-xds/ ENV GRPC_VERBOSITY="DEBUG" -ENV GRPC_TRACE=xds_client,xds_resolver,xds_cluster_manager,cds_balancer,xds_cluster_resolver,xds_cluster_impl,priority,weighted_target,round_robin,resolving_load_balancer,subchannel,keepalive,dns_resolver,fault_injection,http_filter,csds,outlier_detection,server,server_call,ring_hash,transport,certificate_provider +ENV GRPC_TRACE=xds_client,xds_resolver,xds_cluster_manager,cds_balancer,xds_cluster_resolver,xds_cluster_impl,priority,weighted_target,round_robin,resolving_load_balancer,subchannel,keepalive,dns_resolver,fault_injection,http_filter,csds,outlier_detection,server,server_call,ring_hash,transport,certificate_provider,xds_channel_credentials ENV NODE_XDS_INTEROP_VERBOSITY=1 ENTRYPOINT [ "/nodejs/bin/node", "/node/src/grpc-node/packages/grpc-js-xds/build/interop/xds-interop-client" ] diff --git a/packages/grpc-js-xds/src/server.ts b/packages/grpc-js-xds/src/server.ts index 5ccbaa67..7b386ebb 100644 --- a/packages/grpc-js-xds/src/server.ts +++ b/packages/grpc-js-xds/src/server.ts @@ -159,6 +159,7 @@ class FilterChainEntry { } if (credentials instanceof XdsServerCredentials) { if (filterChain.transport_socket) { + trace('Using secure credentials'); const downstreamTlsContext = decodeSingleResource(DOWNSTREAM_TLS_CONTEXT_TYPE_URL, filterChain.transport_socket.typed_config!.value); const commonTlsContext = downstreamTlsContext.common_tls_context!; const instanceCertificateProvider = configParameters.xdsClient.getCertificateProvider(commonTlsContext.tls_certificate_provider_instance!.instance_name); @@ -185,6 +186,7 @@ class FilterChainEntry { } credentials = experimental.createCertificateProviderServerCredentials(instanceCertificateProvider, caCertificateProvider, downstreamTlsContext.require_client_certificate?.value ?? false); } else { + trace('Using fallback credentials'); credentials = credentials.getFallbackCredentials(); } } diff --git a/packages/grpc-js-xds/src/xds-credentials.ts b/packages/grpc-js-xds/src/xds-credentials.ts index 6edac916..f7d66ce4 100644 --- a/packages/grpc-js-xds/src/xds-credentials.ts +++ b/packages/grpc-js-xds/src/xds-credentials.ts @@ -15,11 +15,12 @@ * */ -import { CallCredentials, ChannelCredentials, ChannelOptions, ServerCredentials, VerifyOptions, experimental } from "@grpc/grpc-js"; +import { CallCredentials, ChannelCredentials, ChannelOptions, ServerCredentials, VerifyOptions, experimental, logVerbosity } from "@grpc/grpc-js"; import { CA_CERT_PROVIDER_KEY, IDENTITY_CERT_PROVIDER_KEY, SAN_MATCHER_KEY, SanMatcher } from "./load-balancer-cds"; import GrpcUri = experimental.GrpcUri; import SecureConnector = experimental.SecureConnector; import createCertificateProviderChannelCredentials = experimental.createCertificateProviderChannelCredentials; +import trace = experimental.trace; export class XdsChannelCredentials extends ChannelCredentials { constructor(private fallbackCredentials: ChannelCredentials) { @@ -33,6 +34,7 @@ export class XdsChannelCredentials extends ChannelCredentials { } _createSecureConnector(channelTarget: GrpcUri, options: ChannelOptions, callCredentials?: CallCredentials): SecureConnector { if (options[CA_CERT_PROVIDER_KEY]) { + trace(logVerbosity.DEBUG, 'xds_channel_credentials', 'Using secure credentials'); const verifyOptions: VerifyOptions = {}; if (options[SAN_MATCHER_KEY]) { const matcher = options[SAN_MATCHER_KEY] as SanMatcher; @@ -40,6 +42,7 @@ export class XdsChannelCredentials extends ChannelCredentials { if (cert.subjectaltname && matcher.apply(cert.subjectaltname)) { return undefined; } else { + trace(logVerbosity.DEBUG, 'xds_channel_credentials', 'No matching subject alternative name found in certificate'); return new Error('No matching subject alternative name found in certificate'); } } @@ -47,6 +50,7 @@ export class XdsChannelCredentials extends ChannelCredentials { const certProviderCreds = createCertificateProviderChannelCredentials(options[CA_CERT_PROVIDER_KEY], options[IDENTITY_CERT_PROVIDER_KEY] ?? null, verifyOptions); return certProviderCreds._createSecureConnector(channelTarget, options, callCredentials); } else { + trace(logVerbosity.DEBUG, 'xds_channel_credentials', 'Using fallback credentials'); return this.fallbackCredentials._createSecureConnector(channelTarget, options, callCredentials); } } diff --git a/packages/grpc-js-xds/test/test-xds-credentials.ts b/packages/grpc-js-xds/test/test-xds-credentials.ts index 27063d3e..0a235721 100644 --- a/packages/grpc-js-xds/test/test-xds-credentials.ts +++ b/packages/grpc-js-xds/test/test-xds-credentials.ts @@ -366,4 +366,81 @@ describe('Client xDS credentials', () => { }); } }); + describe('Client and server xDS credentials', () => { + let xdsServer: ControlPlaneServer; + let client: XdsTestClient; + beforeEach(done => { + xdsServer = new ControlPlaneServer(); + xdsServer.startServer(error => { + done(error); + }); + }); + afterEach(() => { + client?.close(); + xdsServer?.shutdownServer(); + }); + it('Should use identity and CA certificates when configured', async () => { + const [backend] = await createBackends(1, true, new XdsServerCredentials(ServerCredentials.createInsecure())); + const downstreamTlsContext: DownstreamTlsContext & AnyExtension = { + '@type': DOWNSTREAM_TLS_CONTEXT_TYPE_URL, + common_tls_context: { + tls_certificate_provider_instance: { + instance_name: 'test_certificates' + }, + validation_context: { + ca_certificate_provider_instance: { + instance_name: 'test_certificates' + } + } + }, + ocsp_staple_policy: 'LENIENT_STAPLING', + require_client_certificate: { + value: true + } + } + const baseServerListener: Listener = { + default_filter_chain: { + filter_chain_match: { + source_type: 'SAME_IP_OR_LOOPBACK' + }, + transport_socket: { + name: 'envoy.transport_sockets.tls', + typed_config: downstreamTlsContext + } + } + } + const serverRoute = new FakeServerRoute(backend.getPort(), 'serverRoute', baseServerListener); + xdsServer.setRdsResource(serverRoute.getRouteConfiguration()); + xdsServer.setLdsResource(serverRoute.getListener()); + xdsServer.addResponseListener((typeUrl, responseState) => { + if (responseState.state === 'NACKED') { + client?.stopCalls(); + assert.fail(`Client NACKED ${typeUrl} resource with message ${responseState.errorMessage}`); + } + }); + const upstreamTlsContext: UpstreamTlsContext = { + common_tls_context: { + tls_certificate_provider_instance: { + instance_name: 'test_certificates' + }, + validation_context: { + ca_certificate_provider_instance: { + instance_name: 'test_certificates' + } + } + } + }; + const cluster = new FakeEdsCluster('cluster1', 'endpoint1', [{backends: [backend], locality:{region: 'region1'}}], undefined, upstreamTlsContext); + const routeGroup = new FakeRouteGroup('listener1', 'route1', [{cluster: cluster}]); + await routeGroup.startAllBackends(xdsServer); + xdsServer.setEdsResource(cluster.getEndpointConfig()); + xdsServer.setCdsResource(cluster.getClusterConfig()); + xdsServer.setRdsResource(routeGroup.getRouteConfiguration()); + xdsServer.setLdsResource(routeGroup.getListener()); + client = XdsTestClient.createFromServer('listener1', xdsServer, new XdsChannelCredentials(credentials.createInsecure())); + const error = await client.sendOneCallAsync(); + assert.strictEqual(error, null); + }); + + }); });