xds: add all validations related to security as described in A29 gRFC (#8331)

This commit is contained in:
sanjaypujare 2021-07-25 22:51:50 -07:00 committed by GitHub
parent f3642422b4
commit 38cba5c8dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 931 additions and 106 deletions

View File

@ -51,6 +51,8 @@ import io.envoyproxy.envoy.config.route.v3.RetryPolicy.RetryBackOff;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration; import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager; import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds; import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CertificateValidationContext;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext; import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext;
import io.envoyproxy.envoy.type.v3.FractionalPercent; import io.envoyproxy.envoy.type.v3.FractionalPercent;
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType; import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
@ -363,7 +365,11 @@ final class ClientXdsClient extends AbstractXdsClient {
} }
EnvoyServerProtoData.DownstreamTlsContext downstreamTlsContext = null; EnvoyServerProtoData.DownstreamTlsContext downstreamTlsContext = null;
if (TRANSPORT_SOCKET_NAME_TLS.equals(proto.getTransportSocket().getName())) { if (proto.hasTransportSocket()) {
if (!TRANSPORT_SOCKET_NAME_TLS.equals(proto.getTransportSocket().getName())) {
throw new ResourceInvalidException("transport-socket with name "
+ proto.getTransportSocket().getName() + " not supported.");
}
DownstreamTlsContext downstreamTlsContextProto; DownstreamTlsContext downstreamTlsContextProto;
try { try {
downstreamTlsContextProto = downstreamTlsContextProto =
@ -374,7 +380,7 @@ final class ClientXdsClient extends AbstractXdsClient {
} }
downstreamTlsContext = downstreamTlsContext =
EnvoyServerProtoData.DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext( EnvoyServerProtoData.DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext(
downstreamTlsContextProto); validateDownstreamTlsContext(downstreamTlsContextProto));
} }
String name = proto.getName(); String name = proto.getName();
@ -392,6 +398,182 @@ final class ClientXdsClient extends AbstractXdsClient {
); );
} }
@VisibleForTesting
static io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
validateDownstreamTlsContext(
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
downstreamTlsContext)
throws ResourceInvalidException {
if (downstreamTlsContext.hasCommonTlsContext()) {
validateCommonTlsContext(downstreamTlsContext.getCommonTlsContext(), true);
} else {
throw new ResourceInvalidException(
"common-tls-context is required in downstream-tls-context");
}
if (downstreamTlsContext.hasRequireSni()) {
throw new ResourceInvalidException(
"downstream-tls-context with require-sni is not supported");
}
if (downstreamTlsContext.hasSessionTicketKeys()) {
throw new ResourceInvalidException(
"downstream-tls-context with session_ticket_keys is not supported");
}
if (downstreamTlsContext.hasSessionTicketKeysSdsSecretConfig()) {
throw new ResourceInvalidException(
"downstream-tls-context with session_ticket_keys_sds_secret_config is not supported");
}
if (downstreamTlsContext.hasDisableStatelessSessionResumption()) {
throw new ResourceInvalidException(
"downstream-tls-context with disable_stateless_session_resumption is not supported");
}
if (downstreamTlsContext.hasSessionTimeout()) {
throw new ResourceInvalidException(
"downstream-tls-context with session_timeout is not supported");
}
DownstreamTlsContext.OcspStaplePolicy ocspStaplePolicy = downstreamTlsContext
.getOcspStaplePolicy();
if (ocspStaplePolicy != null
&& ocspStaplePolicy != DownstreamTlsContext.OcspStaplePolicy.UNRECOGNIZED
&& ocspStaplePolicy != DownstreamTlsContext.OcspStaplePolicy.LENIENT_STAPLING) {
throw new ResourceInvalidException(
"downstream-tls-context with ocsp_staple_policy value " + ocspStaplePolicy.name()
+ " is not supported");
}
return downstreamTlsContext;
}
@VisibleForTesting
static io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
validateUpstreamTlsContext(
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext upstreamTlsContext)
throws ResourceInvalidException {
if (upstreamTlsContext.hasCommonTlsContext()) {
validateCommonTlsContext(upstreamTlsContext.getCommonTlsContext(), false);
} else {
throw new ResourceInvalidException("common-tls-context is required in upstream-tls-context");
}
if (!Strings.isNullOrEmpty(upstreamTlsContext.getSni())) {
throw new ResourceInvalidException("upstream-tls-context with sni is not supported");
}
if (upstreamTlsContext.getAllowRenegotiation()) {
throw new ResourceInvalidException(
"upstream-tls-context with allow_renegotiation is not supported");
}
if (upstreamTlsContext.hasMaxSessionKeys()) {
throw new ResourceInvalidException(
"upstream-tls-context with max_session_keys is not supported");
}
return upstreamTlsContext;
}
@VisibleForTesting
static void validateCommonTlsContext(
CommonTlsContext commonTlsContext, boolean server) throws ResourceInvalidException {
if (commonTlsContext.hasCustomHandshaker()) {
throw new ResourceInvalidException(
"common-tls-context with custom_handshaker is not supported");
}
if (commonTlsContext.hasTlsParams()) {
throw new ResourceInvalidException("common-tls-context with tls_params is not supported");
}
if (commonTlsContext.hasValidationContext()) {
throw new ResourceInvalidException(
"common-tls-context with validation_context is not supported");
}
if (commonTlsContext.hasValidationContextSdsSecretConfig()) {
throw new ResourceInvalidException(
"common-tls-context with validation_context_sds_secret_config is not supported");
}
if (commonTlsContext.hasValidationContextCertificateProvider()) {
throw new ResourceInvalidException(
"common-tls-context with validation_context_certificate_provider is not supported");
}
if (commonTlsContext.hasValidationContextCertificateProviderInstance()) {
throw new ResourceInvalidException(
"common-tls-context with validation_context_certificate_provider_instance is not"
+ " supported");
}
if (!commonTlsContext.hasTlsCertificateCertificateProviderInstance()) {
if (server) {
throw new ResourceInvalidException(
"tls_certificate_certificate_provider_instance is required in downstream-tls-context");
}
if (commonTlsContext.getTlsCertificatesCount() > 0) {
throw new ResourceInvalidException(
"common-tls-context with tls_certificates is not supported");
}
if (commonTlsContext.getTlsCertificateSdsSecretConfigsCount() > 0) {
throw new ResourceInvalidException(
"common-tls-context with tls_certificate_sds_secret_configs is not supported");
}
if (commonTlsContext.hasTlsCertificateCertificateProvider()) {
throw new ResourceInvalidException(
"common-tls-context with tls_certificate_certificate_provider is not supported");
}
}
if (!commonTlsContext.hasCombinedValidationContext()) {
if (!server) {
throw new ResourceInvalidException(
"combined_validation_context is required in upstream-tls-context");
}
} else {
CommonTlsContext.CombinedCertificateValidationContext combinedCertificateValidationContext
= commonTlsContext.getCombinedValidationContext();
if (!combinedCertificateValidationContext.hasValidationContextCertificateProviderInstance()) {
throw new ResourceInvalidException(
"validation_context_certificate_provider_instance is required in"
+ " combined_validation_context");
}
if (combinedCertificateValidationContext.hasDefaultValidationContext()) {
if (server) {
throw new ResourceInvalidException(
"default_validation_context only allowed in upstream_tls_context");
}
CertificateValidationContext certificateValidationContext
= combinedCertificateValidationContext.getDefaultValidationContext();
if (certificateValidationContext.hasTrustedCa()) {
throw new ResourceInvalidException(
"trusted_ca in default_validation_context is not supported");
}
if (certificateValidationContext.hasWatchedDirectory()) {
throw new ResourceInvalidException(
"watched_directory in default_validation_context is not supported");
}
if (certificateValidationContext.getVerifyCertificateSpkiCount() > 0) {
throw new ResourceInvalidException(
"verify_certificate_spki in default_validation_context is not supported");
}
if (certificateValidationContext.getVerifyCertificateHashCount() > 0) {
throw new ResourceInvalidException(
"verify_certificate_hash in default_validation_context is not supported");
}
if (certificateValidationContext.hasRequireSignedCertificateTimestamp()) {
throw new ResourceInvalidException(
"require_signed_certificate_timestamp in default_validation_context is not "
+ "supported");
}
if (certificateValidationContext.hasCrl()) {
throw new ResourceInvalidException("crl in default_validation_context is not supported");
}
if (certificateValidationContext.getAllowExpiredCertificate()) {
throw new ResourceInvalidException(
"allow_expired_certificate in default_validation_context is not supported");
}
CertificateValidationContext.TrustChainVerification trustChainVerification
= certificateValidationContext.getTrustChainVerification();
if (trustChainVerification != null && trustChainVerification
!= CertificateValidationContext.TrustChainVerification.VERIFY_TRUST_CHAIN) {
throw new ResourceInvalidException(
"Only VERIFY_TRUST_CHAIN for trust_chain_verification supported");
}
if (certificateValidationContext.hasCustomValidatorConfig()) {
throw new ResourceInvalidException(
"custom_validator_config in default_validation_context is not supported");
}
}
}
}
private static void checkForUniqueness(Set<FilterChainMatch> uniqueSet, private static void checkForUniqueness(Set<FilterChainMatch> uniqueSet,
FilterChainMatch filterChainMatch) throws ResourceInvalidException { FilterChainMatch filterChainMatch) throws ResourceInvalidException {
if (uniqueSet != null) { if (uniqueSet != null) {
@ -1336,14 +1518,18 @@ final class ClientXdsClient extends AbstractXdsClient {
} }
} }
} }
if (cluster.hasTransportSocket() if (cluster.hasTransportSocket()) {
&& TRANSPORT_SOCKET_NAME_TLS.equals(cluster.getTransportSocket().getName())) { if (!TRANSPORT_SOCKET_NAME_TLS.equals(cluster.getTransportSocket().getName())) {
return StructOrError.fromError("transport-socket with name "
+ cluster.getTransportSocket().getName() + " not supported.");
}
try { try {
upstreamTlsContext = UpstreamTlsContext.fromEnvoyProtoUpstreamTlsContext( upstreamTlsContext = UpstreamTlsContext.fromEnvoyProtoUpstreamTlsContext(
validateUpstreamTlsContext(
unpackCompatibleType(cluster.getTransportSocket().getTypedConfig(), unpackCompatibleType(cluster.getTransportSocket().getTypedConfig(),
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext.class, io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext.class,
TYPE_URL_UPSTREAM_TLS_CONTEXT, TYPE_URL_UPSTREAM_TLS_CONTEXT_V2)); TYPE_URL_UPSTREAM_TLS_CONTEXT, TYPE_URL_UPSTREAM_TLS_CONTEXT_V2)));
} catch (InvalidProtocolBufferException e) { } catch (InvalidProtocolBufferException | ResourceInvalidException e) {
return StructOrError.fromError( return StructOrError.fromError(
"Cluster " + clusterName + ": malformed UpstreamTlsContext: " + e); "Cluster " + clusterName + ": malformed UpstreamTlsContext: " + e);
} }

View File

@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.protobuf.Any; import com.google.protobuf.Any;
import com.google.protobuf.BoolValue; import com.google.protobuf.BoolValue;
import com.google.protobuf.Duration;
import com.google.protobuf.StringValue; import com.google.protobuf.StringValue;
import com.google.protobuf.UInt32Value; import com.google.protobuf.UInt32Value;
import com.google.protobuf.UInt64Value; import com.google.protobuf.UInt64Value;
@ -36,12 +37,15 @@ import io.envoyproxy.envoy.config.core.v3.Address;
import io.envoyproxy.envoy.config.core.v3.AggregatedConfigSource; import io.envoyproxy.envoy.config.core.v3.AggregatedConfigSource;
import io.envoyproxy.envoy.config.core.v3.CidrRange; import io.envoyproxy.envoy.config.core.v3.CidrRange;
import io.envoyproxy.envoy.config.core.v3.ConfigSource; import io.envoyproxy.envoy.config.core.v3.ConfigSource;
import io.envoyproxy.envoy.config.core.v3.DataSource;
import io.envoyproxy.envoy.config.core.v3.HttpProtocolOptions; import io.envoyproxy.envoy.config.core.v3.HttpProtocolOptions;
import io.envoyproxy.envoy.config.core.v3.Locality; import io.envoyproxy.envoy.config.core.v3.Locality;
import io.envoyproxy.envoy.config.core.v3.RuntimeFractionalPercent; import io.envoyproxy.envoy.config.core.v3.RuntimeFractionalPercent;
import io.envoyproxy.envoy.config.core.v3.SocketAddress; import io.envoyproxy.envoy.config.core.v3.SocketAddress;
import io.envoyproxy.envoy.config.core.v3.TrafficDirection; import io.envoyproxy.envoy.config.core.v3.TrafficDirection;
import io.envoyproxy.envoy.config.core.v3.TransportSocket; import io.envoyproxy.envoy.config.core.v3.TransportSocket;
import io.envoyproxy.envoy.config.core.v3.TypedExtensionConfig;
import io.envoyproxy.envoy.config.core.v3.WatchedDirectory;
import io.envoyproxy.envoy.config.endpoint.v3.Endpoint; import io.envoyproxy.envoy.config.endpoint.v3.Endpoint;
import io.envoyproxy.envoy.config.listener.v3.Filter; import io.envoyproxy.envoy.config.listener.v3.Filter;
import io.envoyproxy.envoy.config.listener.v3.FilterChain; import io.envoyproxy.envoy.config.listener.v3.FilterChain;
@ -73,6 +77,14 @@ import io.envoyproxy.envoy.extensions.filters.http.router.v3.Router;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager; import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter; import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds; import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CertificateValidationContext;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.TlsCertificate;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.TlsParameters;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.TlsSessionTicketKeys;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext;
import io.envoyproxy.envoy.type.matcher.v3.RegexMatchAndSubstitute; import io.envoyproxy.envoy.type.matcher.v3.RegexMatchAndSubstitute;
import io.envoyproxy.envoy.type.matcher.v3.RegexMatcher; import io.envoyproxy.envoy.type.matcher.v3.RegexMatcher;
import io.envoyproxy.envoy.type.matcher.v3.RegexMatcher.GoogleRE2; import io.envoyproxy.envoy.type.matcher.v3.RegexMatcher.GoogleRE2;
@ -1233,7 +1245,6 @@ public class ClientXdsClientDataTest {
FilterChain.newBuilder() FilterChain.newBuilder()
.setName("filter-chain-1") .setName("filter-chain-1")
.setFilterChainMatch(filterChainMatch1) .setFilterChainMatch(filterChainMatch1)
.setTransportSocket(TransportSocket.getDefaultInstance())
.addFilters(filter1) .addFilters(filter1)
.build(); .build();
Filter filter2 = buildHttpConnectionManagerFilter( Filter filter2 = buildHttpConnectionManagerFilter(
@ -1251,7 +1262,6 @@ public class ClientXdsClientDataTest {
FilterChain.newBuilder() FilterChain.newBuilder()
.setName("filter-chain-2") .setName("filter-chain-2")
.setFilterChainMatch(filterChainMatch2) .setFilterChainMatch(filterChainMatch2)
.setTransportSocket(TransportSocket.getDefaultInstance())
.addFilters(filter2) .addFilters(filter2)
.build(); .build();
Listener listener = Listener listener =
@ -1282,7 +1292,6 @@ public class ClientXdsClientDataTest {
FilterChain.newBuilder() FilterChain.newBuilder()
.setName("filter-chain-1") .setName("filter-chain-1")
.setFilterChainMatch(filterChainMatch1) .setFilterChainMatch(filterChainMatch1)
.setTransportSocket(TransportSocket.getDefaultInstance())
.addFilters(filter1) .addFilters(filter1)
.build(); .build();
Filter filter2 = buildHttpConnectionManagerFilter( Filter filter2 = buildHttpConnectionManagerFilter(
@ -1300,7 +1309,6 @@ public class ClientXdsClientDataTest {
FilterChain.newBuilder() FilterChain.newBuilder()
.setName("filter-chain-2") .setName("filter-chain-2")
.setFilterChainMatch(filterChainMatch2) .setFilterChainMatch(filterChainMatch2)
.setTransportSocket(TransportSocket.getDefaultInstance())
.addFilters(filter2) .addFilters(filter2)
.build(); .build();
Listener listener = Listener listener =
@ -1332,7 +1340,6 @@ public class ClientXdsClientDataTest {
FilterChain.newBuilder() FilterChain.newBuilder()
.setName("filter-chain-1") .setName("filter-chain-1")
.setFilterChainMatch(filterChainMatch1) .setFilterChainMatch(filterChainMatch1)
.setTransportSocket(TransportSocket.getDefaultInstance())
.addFilters(filter1) .addFilters(filter1)
.build(); .build();
Filter filter2 = buildHttpConnectionManagerFilter( Filter filter2 = buildHttpConnectionManagerFilter(
@ -1351,7 +1358,6 @@ public class ClientXdsClientDataTest {
FilterChain.newBuilder() FilterChain.newBuilder()
.setName("filter-chain-2") .setName("filter-chain-2")
.setFilterChainMatch(filterChainMatch2) .setFilterChainMatch(filterChainMatch2)
.setTransportSocket(TransportSocket.getDefaultInstance())
.addFilters(filter2) .addFilters(filter2)
.build(); .build();
Listener listener = Listener listener =
@ -1467,6 +1473,519 @@ public class ClientXdsClientDataTest {
assertThat(parsedFilterChain1.getName()).isNotEqualTo(parsedFilterChain2.getName()); assertThat(parsedFilterChain1.getName()).isNotEqualTo(parsedFilterChain2.getName());
} }
@Test
public void validateCommonTlsContext_tlsParams() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setTlsParams(TlsParameters.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context with tls_params is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_customHandshaker() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCustomHandshaker(TypedExtensionConfig.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context with custom_handshaker is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_validationContext() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setValidationContext(CertificateValidationContext.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context with validation_context is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_validationContextSdsSecretConfig()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setValidationContextSdsSecretConfig(SdsSecretConfig.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"common-tls-context with validation_context_sds_secret_config is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_validationContextCertificateProvider()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setValidationContextCertificateProvider(
CommonTlsContext.CertificateProvider.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"common-tls-context with validation_context_certificate_provider is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_validationContextCertificateProviderInstance()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"common-tls-context with validation_context_certificate_provider_instance is not "
+ "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_tlsCertificateProviderInstance_isRequiredForServer()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"tls_certificate_certificate_provider_instance is required in downstream-tls-context");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, true);
}
@Test
public void validateCommonTlsContext_tlsCertificatesCount() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.addTlsCertificates(TlsCertificate.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context with tls_certificates is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_tlsCertificateSdsSecretConfigsCount()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.addTlsCertificateSdsSecretConfigs(SdsSecretConfig.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"common-tls-context with tls_certificate_sds_secret_configs is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_tlsCertificateCertificateProvider()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setTlsCertificateCertificateProvider(
CommonTlsContext.CertificateProvider.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"common-tls-context with tls_certificate_certificate_provider is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValidationContext_isRequiredForClient()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("combined_validation_context is required in upstream-tls-context");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValidationContextWithoutCertProviderInstance()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"validation_context_certificate_provider_instance is required in "
+ "combined_validation_context");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValContextWithDefaultValContextForServer()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(CertificateValidationContext.getDefaultInstance()))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("default_validation_context only allowed in upstream_tls_context");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, true);
}
@Test
public void validateCommonTlsContext_combinedValContextWithDefaultValidationContextTrustedCa()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(CertificateValidationContext.newBuilder()
.setTrustedCa(DataSource.getDefaultInstance())))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("trusted_ca in default_validation_context is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValContextWithDefaultValContextWatchedDirectory()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(CertificateValidationContext.newBuilder()
.setWatchedDirectory(WatchedDirectory.getDefaultInstance())))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("watched_directory in default_validation_context is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValContextWithDefaultValContextVerifyCertSpki()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(
CertificateValidationContext.newBuilder().addVerifyCertificateSpki("foo")))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("verify_certificate_spki in default_validation_context is not "
+ "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValContextWithDefaultValContextVerifyCertHash()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(
CertificateValidationContext.newBuilder().addVerifyCertificateHash("foo")))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("verify_certificate_hash in default_validation_context is not "
+ "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValContextDfltValContextRequireSignedCertTimestamp()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(CertificateValidationContext.newBuilder()
.setRequireSignedCertificateTimestamp(BoolValue.of(true))))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"require_signed_certificate_timestamp in default_validation_context is not "
+ "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValidationContextWithDefaultValidationContextCrl()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(CertificateValidationContext.newBuilder()
.setCrl(DataSource.getDefaultInstance())))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("crl in default_validation_context is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValContextWithDefaultValContextAllowExpiredCert()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(
CertificateValidationContext.newBuilder().setAllowExpiredCertificate(true)))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown
.expectMessage("allow_expired_certificate in default_validation_context is not "
+ "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValContextWithDfltValContextTrustChainVerification()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(CertificateValidationContext.newBuilder()
.setTrustChainVerification(
CertificateValidationContext.TrustChainVerification.ACCEPT_UNTRUSTED)))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("Only VERIFY_TRUST_CHAIN for trust_chain_verification supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateCommonTlsContext_combinedValContextWithDfltValContextCustomValidatorConfig()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.setDefaultValidationContext(CertificateValidationContext.newBuilder()
.setCustomValidatorConfig(TypedExtensionConfig.getDefaultInstance())))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("custom_validator_config in default_validation_context is not "
+ "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false);
}
@Test
public void validateDownstreamTlsContext_noCommonTlsContext() throws ResourceInvalidException {
DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.getDefaultInstance();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context is required in downstream-tls-context");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext);
}
@Test
public void validateDownstreamTlsContext_hasRequireSni() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance()))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext)
.setRequireSni(BoolValue.of(true))
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("downstream-tls-context with require-sni is not supported");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext);
}
@Test
public void validateDownstreamTlsContext_hasSessionTikcetKeys() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance()))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext)
.setSessionTicketKeys(TlsSessionTicketKeys.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("downstream-tls-context with session_ticket_keys is not supported");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext);
}
@Test
public void validateDownstreamTlsContext_hasSessionTikcetKeysSdsSecretConfig()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance()))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext)
.setSessionTicketKeysSdsSecretConfig(SdsSecretConfig.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"downstream-tls-context with session_ticket_keys_sds_secret_config is not supported");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext);
}
@Test
public void validateDownstreamTlsContext_hasDisableStatelessSessionResumption()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance()))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext)
.setDisableStatelessSessionResumption(true)
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"downstream-tls-context with disable_stateless_session_resumption is not supported");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext);
}
@Test
public void validateDownstreamTlsContext_hasSessionTimeout() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance()))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext)
.setSessionTimeout(Duration.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("downstream-tls-context with session_timeout is not supported");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext);
}
@Test
public void validateDownstreamTlsContext_hasOcspStaplePolicy() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance()))
.setTlsCertificateCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance())
.build();
DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext)
.setOcspStaplePolicy(DownstreamTlsContext.OcspStaplePolicy.STRICT_STAPLING)
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"downstream-tls-context with ocsp_staple_policy value STRICT_STAPLING is not supported");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext);
}
@Test
public void validateUpstreamTlsContext_noCommonTlsContext() throws ResourceInvalidException {
UpstreamTlsContext upstreamTlsContext = UpstreamTlsContext.getDefaultInstance();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context is required in upstream-tls-context");
ClientXdsClient.validateUpstreamTlsContext(upstreamTlsContext);
}
@Test
public void validateUpstreamTlsContext_sni() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance()))
.build();
UpstreamTlsContext upstreamTlsContext = UpstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext)
.setSni("foo")
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("upstream-tls-context with sni is not supported");
ClientXdsClient.validateUpstreamTlsContext(upstreamTlsContext);
}
@Test
public void validateUpstreamTlsContext_allowRenegotiation() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance()))
.build();
UpstreamTlsContext upstreamTlsContext = UpstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext)
.setAllowRenegotiation(true)
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("upstream-tls-context with allow_renegotiation is not supported");
ClientXdsClient.validateUpstreamTlsContext(upstreamTlsContext);
}
@Test
public void validateUpstreamTlsContext_maxSessionKeys() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CommonTlsContext.CertificateProviderInstance.getDefaultInstance()))
.build();
UpstreamTlsContext upstreamTlsContext = UpstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext)
.setMaxSessionKeys(UInt32Value.getDefaultInstance())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("upstream-tls-context with max_session_keys is not supported");
ClientXdsClient.validateUpstreamTlsContext(upstreamTlsContext);
}
private static Filter buildHttpConnectionManagerFilter(HttpFilter... httpFilters) { private static Filter buildHttpConnectionManagerFilter(HttpFilter... httpFilters) {
return Filter.newBuilder() return Filter.newBuilder()
.setName("envoy.http_connection_manager") .setName("envoy.http_connection_manager")

View File

@ -39,7 +39,7 @@ import com.google.protobuf.Any;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import io.envoyproxy.envoy.config.route.v3.FilterConfig; import io.envoyproxy.envoy.config.route.v3.FilterConfig;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig; import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
import io.grpc.BindableService; import io.grpc.BindableService;
import io.grpc.Context; import io.grpc.Context;
import io.grpc.Context.CancellableContext; import io.grpc.Context.CancellableContext;
@ -193,7 +193,9 @@ public abstract class ClientXdsClientTestBase {
// CDS test resources. // CDS test resources.
private final Any testClusterRoundRobin = private final Any testClusterRoundRobin =
Any.pack(mf.buildEdsCluster(CDS_RESOURCE, null, "round_robin", null, false, null, null)); Any.pack(mf.buildEdsCluster(CDS_RESOURCE, null, "round_robin", null, false, null,
"envoy.transport_sockets.tls", null
));
// EDS test resources. // EDS test resources.
private final Message lbEndpointHealthy = private final Message lbEndpointHealthy =
@ -990,9 +992,10 @@ public abstract class ClientXdsClientTestBase {
Message hcmFilter = mf.buildHttpConnectionManagerFilter( Message hcmFilter = mf.buildHttpConnectionManagerFilter(
RDS_RESOURCE, null, Collections.<Message>emptyList()); RDS_RESOURCE, null, Collections.<Message>emptyList());
Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext( Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
"google-sds-config-default", "ROOTCA"); "google-sds-config-default", "ROOTCA", false);
Message filterChain = mf.buildFilterChain( Message filterChain = mf.buildFilterChain(
Collections.<String>emptyList(), downstreamTlsContext, hcmFilter); Collections.<String>emptyList(), downstreamTlsContext, "envoy.transport_sockets.tls",
hcmFilter);
Any packedListener = Any packedListener =
Any.pack(mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain)); Any.pack(mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain));
@ -1024,7 +1027,8 @@ public abstract class ClientXdsClientTestBase {
"route-bar.googleapis.com", mf.buildOpaqueVirtualHosts(VHOST_SIZE)), "route-bar.googleapis.com", mf.buildOpaqueVirtualHosts(VHOST_SIZE)),
Collections.<Message>emptyList()); Collections.<Message>emptyList());
filterChain = mf.buildFilterChain( filterChain = mf.buildFilterChain(
Collections.<String>emptyList(), downstreamTlsContext, hcmFilter); Collections.<String>emptyList(), downstreamTlsContext, "envoy.transport_sockets.tls",
hcmFilter);
packedListener = packedListener =
Any.pack(mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain)); Any.pack(mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain));
call.sendResponse(LDS, packedListener, VERSION_2, "0001"); call.sendResponse(LDS, packedListener, VERSION_2, "0001");
@ -1090,9 +1094,9 @@ public abstract class ClientXdsClientTestBase {
List<Any> clusters = ImmutableList.of( List<Any> clusters = ImmutableList.of(
Any.pack(mf.buildEdsCluster("cluster-bar.googleapis.com", null, "round_robin", null, Any.pack(mf.buildEdsCluster("cluster-bar.googleapis.com", null, "round_robin", null,
false, null, null)), false, null, "envoy.transport_sockets.tls", null)),
Any.pack(mf.buildEdsCluster("cluster-baz.googleapis.com", null, "round_robin", null, Any.pack(mf.buildEdsCluster("cluster-baz.googleapis.com", null, "round_robin", null,
false, null, null))); false, null, "envoy.transport_sockets.tls", null)));
call.sendResponse(CDS, clusters, VERSION_1, "0000"); call.sendResponse(CDS, clusters, VERSION_1, "0000");
// Client sent an ACK CDS request. // Client sent an ACK CDS request.
@ -1165,9 +1169,15 @@ public abstract class ClientXdsClientTestBase {
// CDS -> {A, B, C}, version 1 // CDS -> {A, B, C}, version 1
ImmutableMap<String, Any> resourcesV1 = ImmutableMap.of( ImmutableMap<String, Any> resourcesV1 = ImmutableMap.of(
"A", Any.pack(mf.buildEdsCluster("A", "A.1", "round_robin", null, false, null, null)), "A", Any.pack(mf.buildEdsCluster("A", "A.1", "round_robin", null, false, null,
"B", Any.pack(mf.buildEdsCluster("B", "B.1", "round_robin", null, false, null, null)), "envoy.transport_sockets.tls", null
"C", Any.pack(mf.buildEdsCluster("C", "C.1", "round_robin", null, false, null, null))); )),
"B", Any.pack(mf.buildEdsCluster("B", "B.1", "round_robin", null, false, null,
"envoy.transport_sockets.tls", null
)),
"C", Any.pack(mf.buildEdsCluster("C", "C.1", "round_robin", null, false, null,
"envoy.transport_sockets.tls", null
)));
call.sendResponse(CDS, resourcesV1.values().asList(), VERSION_1, "0000"); call.sendResponse(CDS, resourcesV1.values().asList(), VERSION_1, "0000");
// {A, B, C} -> ACK, version 1 // {A, B, C} -> ACK, version 1
verifyResourceMetadataAcked(CDS, "A", resourcesV1.get("A"), VERSION_1, TIME_INCREMENT); verifyResourceMetadataAcked(CDS, "A", resourcesV1.get("A"), VERSION_1, TIME_INCREMENT);
@ -1178,7 +1188,9 @@ public abstract class ClientXdsClientTestBase {
// CDS -> {A, B}, version 2 // CDS -> {A, B}, version 2
// Failed to parse endpoint B // Failed to parse endpoint B
ImmutableMap<String, Any> resourcesV2 = ImmutableMap.of( ImmutableMap<String, Any> resourcesV2 = ImmutableMap.of(
"A", Any.pack(mf.buildEdsCluster("A", "A.2", "round_robin", null, false, null, null)), "A", Any.pack(mf.buildEdsCluster("A", "A.2", "round_robin", null, false, null,
"envoy.transport_sockets.tls", null
)),
"B", Any.pack(mf.buildClusterInvalid("B"))); "B", Any.pack(mf.buildClusterInvalid("B")));
call.sendResponse(CDS, resourcesV2.values().asList(), VERSION_2, "0001"); call.sendResponse(CDS, resourcesV2.values().asList(), VERSION_2, "0001");
// {A, B} -> NACK, version 1, rejected version 2, rejected reason: Failed to parse B // {A, B} -> NACK, version 1, rejected version 2, rejected reason: Failed to parse B
@ -1193,8 +1205,12 @@ public abstract class ClientXdsClientTestBase {
// CDS -> {B, C} version 3 // CDS -> {B, C} version 3
ImmutableMap<String, Any> resourcesV3 = ImmutableMap.of( ImmutableMap<String, Any> resourcesV3 = ImmutableMap.of(
"B", Any.pack(mf.buildEdsCluster("B", "B.3", "round_robin", null, false, null, null)), "B", Any.pack(mf.buildEdsCluster("B", "B.3", "round_robin", null, false, null,
"C", Any.pack(mf.buildEdsCluster("C", "C.3", "round_robin", null, false, null, null))); "envoy.transport_sockets.tls", null
)),
"C", Any.pack(mf.buildEdsCluster("C", "C.3", "round_robin", null, false, null,
"envoy.transport_sockets.tls", null
)));
call.sendResponse(CDS, resourcesV3.values().asList(), VERSION_3, "0002"); call.sendResponse(CDS, resourcesV3.values().asList(), VERSION_3, "0002");
// {A} -> NACK, version 1, rejected version 2, rejected reason: Failed to parse B // {A} -> NACK, version 1, rejected version 2, rejected reason: Failed to parse B
// {B, C} -> ACK, version 3 // {B, C} -> ACK, version 3
@ -1231,7 +1247,9 @@ public abstract class ClientXdsClientTestBase {
DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher); DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher);
Message ringHashConfig = mf.buildRingHashLbConfig("xx_hash", 10L, 100L); Message ringHashConfig = mf.buildRingHashLbConfig("xx_hash", 10L, 100L);
Any clusterRingHash = Any.pack( Any clusterRingHash = Any.pack(
mf.buildEdsCluster(CDS_RESOURCE, null, "ring_hash", ringHashConfig, false, null, null)); mf.buildEdsCluster(CDS_RESOURCE, null, "ring_hash", ringHashConfig, false, null,
"envoy.transport_sockets.tls", null
));
call.sendResponse(ResourceType.CDS, clusterRingHash, VERSION_1, "0000"); call.sendResponse(ResourceType.CDS, clusterRingHash, VERSION_1, "0000");
// Client sent an ACK CDS request. // Client sent an ACK CDS request.
@ -1278,7 +1296,7 @@ public abstract class ClientXdsClientTestBase {
DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher); DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher);
Any clusterCircuitBreakers = Any.pack( Any clusterCircuitBreakers = Any.pack(
mf.buildEdsCluster(CDS_RESOURCE, null, "round_robin", null, false, null, mf.buildEdsCluster(CDS_RESOURCE, null, "round_robin", null, false, null,
mf.buildCircuitBreakers(50, 200))); "envoy.transport_sockets.tls", mf.buildCircuitBreakers(50, 200)));
call.sendResponse(CDS, clusterCircuitBreakers, VERSION_1, "0000"); call.sendResponse(CDS, clusterCircuitBreakers, VERSION_1, "0000");
// Client sent an ACK CDS request. // Client sent an ACK CDS request.
@ -1302,41 +1320,81 @@ public abstract class ClientXdsClientTestBase {
*/ */
@Test @Test
public void cdsResponseWithUpstreamTlsContext() { public void cdsResponseWithUpstreamTlsContext() {
Assume.assumeTrue(useProtocolV3());
DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher); DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher);
// Management server sends back CDS response with UpstreamTlsContext. // Management server sends back CDS response with UpstreamTlsContext.
Any clusterEds = Any clusterEds =
Any.pack(mf.buildEdsCluster(CDS_RESOURCE, "eds-cluster-foo.googleapis.com", "round_robin", Any.pack(mf.buildEdsCluster(CDS_RESOURCE, "eds-cluster-foo.googleapis.com", "round_robin",
null, true, null, true,
mf.buildUpstreamTlsContext("secret1", "unix:/var/uds2"), null)); mf.buildUpstreamTlsContext("secret1", "cert1"), "envoy.transport_sockets.tls", null));
List<Any> clusters = ImmutableList.of( List<Any> clusters = ImmutableList.of(
Any.pack(mf.buildLogicalDnsCluster("cluster-bar.googleapis.com", Any.pack(mf.buildLogicalDnsCluster("cluster-bar.googleapis.com",
"dns-service-bar.googleapis.com", 443, "round_robin", null, false, null, null)), "dns-service-bar.googleapis.com", 443, "round_robin", null, false, null, null)),
clusterEds, clusterEds,
Any.pack(mf.buildEdsCluster("cluster-baz.googleapis.com", null, "round_robin", null, false, Any.pack(mf.buildEdsCluster("cluster-baz.googleapis.com", null, "round_robin", null, false,
null, null))); null, "envoy.transport_sockets.tls", null)));
call.sendResponse(CDS, clusters, VERSION_1, "0000"); call.sendResponse(CDS, clusters, VERSION_1, "0000");
// Client sent an ACK CDS request. // Client sent an ACK CDS request.
call.verifyRequest(CDS, CDS_RESOURCE, VERSION_1, "0000", NODE); call.verifyRequest(CDS, CDS_RESOURCE, VERSION_1, "0000", NODE);
verify(cdsResourceWatcher, times(1)).onChanged(cdsUpdateCaptor.capture()); verify(cdsResourceWatcher, times(1)).onChanged(cdsUpdateCaptor.capture());
CdsUpdate cdsUpdate = cdsUpdateCaptor.getValue(); CdsUpdate cdsUpdate = cdsUpdateCaptor.getValue();
SdsSecretConfig validationContextSdsSecretConfig = CommonTlsContext.CertificateProviderInstance certificateProviderInstance =
cdsUpdate.upstreamTlsContext().getCommonTlsContext().getValidationContextSdsSecretConfig(); cdsUpdate.upstreamTlsContext().getCommonTlsContext().getCombinedValidationContext()
assertThat(validationContextSdsSecretConfig.getName()).isEqualTo("secret1"); .getValidationContextCertificateProviderInstance();
assertThat( assertThat(certificateProviderInstance.getInstanceName()).isEqualTo("secret1");
Iterables.getOnlyElement( assertThat(certificateProviderInstance.getCertificateName()).isEqualTo("cert1");
validationContextSdsSecretConfig
.getSdsConfig()
.getApiConfigSource()
.getGrpcServicesList())
.getGoogleGrpc()
.getTargetUri())
.isEqualTo("unix:/var/uds2");
verifyResourceMetadataAcked(CDS, CDS_RESOURCE, clusterEds, VERSION_1, TIME_INCREMENT); verifyResourceMetadataAcked(CDS, CDS_RESOURCE, clusterEds, VERSION_1, TIME_INCREMENT);
verifySubscribedResourcesMetadataSizes(0, 1, 0, 0); verifySubscribedResourcesMetadataSizes(0, 1, 0, 0);
} }
/**
* CDS response containing bad UpstreamTlsContext for a cluster.
*/
@Test
public void cdsResponseErrorHandling_badUpstreamTlsContext() {
Assume.assumeTrue(useProtocolV3());
DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher);
// Management server sends back CDS response with UpstreamTlsContext.
List<Any> clusters = ImmutableList.of(Any
.pack(mf.buildEdsCluster(CDS_RESOURCE, "eds-cluster-foo.googleapis.com", "round_robin",
null, true,
mf.buildUpstreamTlsContext(null, null), "envoy.transport_sockets.tls", null)));
call.sendResponse(CDS, clusters, VERSION_1, "0000");
// The response NACKed with errors indicating indices of the failed resources.
call.verifyRequestNack(CDS, CDS_RESOURCE, "", "0000", NODE, ImmutableList.of(
"CDS response Cluster 'cluster.googleapis.com' validation error: "
+ "Cluster cluster.googleapis.com: malformed UpstreamTlsContext: "
+ "io.grpc.xds.ClientXdsClient$ResourceInvalidException: "
+ "combined_validation_context is required in upstream-tls-context"));
verifyNoInteractions(cdsResourceWatcher);
}
/**
* CDS response containing UpstreamTlsContext with bad transportSocketName for a cluster.
*/
@Test
public void cdsResponseErrorHandling_badTransportSocketName() {
Assume.assumeTrue(useProtocolV3());
DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher);
// Management server sends back CDS response with UpstreamTlsContext.
List<Any> clusters = ImmutableList.of(Any
.pack(mf.buildEdsCluster(CDS_RESOURCE, "eds-cluster-foo.googleapis.com", "round_robin",
null, true,
mf.buildUpstreamTlsContext("secret1", "cert1"), "envoy.transport_sockets.bad", null)));
call.sendResponse(CDS, clusters, VERSION_1, "0000");
// The response NACKed with errors indicating indices of the failed resources.
call.verifyRequestNack(CDS, CDS_RESOURCE, "", "0000", NODE, ImmutableList.of(
"CDS response Cluster 'cluster.googleapis.com' validation error: "
+ "transport-socket with name envoy.transport_sockets.bad not supported."));
verifyNoInteractions(cdsResourceWatcher);
}
@Test @Test
public void cachedCdsResource_data() { public void cachedCdsResource_data() {
DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher); DiscoveryRpcCall call = startResourceWatcher(CDS, CDS_RESOURCE, cdsResourceWatcher);
@ -1403,7 +1461,9 @@ public abstract class ClientXdsClientTestBase {
// Updated CDS response. // Updated CDS response.
String edsService = "eds-service-bar.googleapis.com"; String edsService = "eds-service-bar.googleapis.com";
Any clusterEds = Any.pack( Any clusterEds = Any.pack(
mf.buildEdsCluster(CDS_RESOURCE, edsService, "round_robin", null, true, null, null)); mf.buildEdsCluster(CDS_RESOURCE, edsService, "round_robin", null, true, null,
"envoy.transport_sockets.tls", null
));
call.sendResponse(CDS, clusterEds, VERSION_2, "0001"); call.sendResponse(CDS, clusterEds, VERSION_2, "0001");
call.verifyRequest(CDS, CDS_RESOURCE, VERSION_2, "0001", NODE); call.verifyRequest(CDS, CDS_RESOURCE, VERSION_2, "0001", NODE);
verify(cdsResourceWatcher, times(2)).onChanged(cdsUpdateCaptor.capture()); verify(cdsResourceWatcher, times(2)).onChanged(cdsUpdateCaptor.capture());
@ -1477,7 +1537,7 @@ public abstract class ClientXdsClientTestBase {
Any.pack(mf.buildLogicalDnsCluster(CDS_RESOURCE, dnsHostAddr, dnsHostPort, "round_robin", Any.pack(mf.buildLogicalDnsCluster(CDS_RESOURCE, dnsHostAddr, dnsHostPort, "round_robin",
null, false, null, null)), null, false, null, null)),
Any.pack(mf.buildEdsCluster(cdsResourceTwo, edsService, "round_robin", null, true, null, Any.pack(mf.buildEdsCluster(cdsResourceTwo, edsService, "round_robin", null, true, null,
null))); "envoy.transport_sockets.tls", null)));
call.sendResponse(CDS, clusters, VERSION_1, "0000"); call.sendResponse(CDS, clusters, VERSION_1, "0000");
verify(cdsResourceWatcher).onChanged(cdsUpdateCaptor.capture()); verify(cdsResourceWatcher).onChanged(cdsUpdateCaptor.capture());
CdsUpdate cdsUpdate = cdsUpdateCaptor.getValue(); CdsUpdate cdsUpdate = cdsUpdateCaptor.getValue();
@ -1736,9 +1796,11 @@ public abstract class ClientXdsClientTestBase {
DiscoveryRpcCall call = resourceDiscoveryCalls.poll(); DiscoveryRpcCall call = resourceDiscoveryCalls.poll();
List<Any> clusters = ImmutableList.of( List<Any> clusters = ImmutableList.of(
Any.pack(mf.buildEdsCluster(resource, null, "round_robin", null, true, null, null)), Any.pack(mf.buildEdsCluster(resource, null, "round_robin", null, true, null,
"envoy.transport_sockets.tls", null
)),
Any.pack(mf.buildEdsCluster(CDS_RESOURCE, EDS_RESOURCE, "round_robin", null, false, null, Any.pack(mf.buildEdsCluster(CDS_RESOURCE, EDS_RESOURCE, "round_robin", null, false, null,
null))); "envoy.transport_sockets.tls", null)));
call.sendResponse(CDS, clusters, VERSION_1, "0000"); call.sendResponse(CDS, clusters, VERSION_1, "0000");
verify(cdsWatcher).onChanged(cdsUpdateCaptor.capture()); verify(cdsWatcher).onChanged(cdsUpdateCaptor.capture());
CdsUpdate cdsUpdate = cdsUpdateCaptor.getValue(); CdsUpdate cdsUpdate = cdsUpdateCaptor.getValue();
@ -1784,8 +1846,10 @@ public abstract class ClientXdsClientTestBase {
clusters = ImmutableList.of( clusters = ImmutableList.of(
Any.pack(mf.buildEdsCluster(resource, null, "round_robin", null, true, null, Any.pack(mf.buildEdsCluster(resource, null, "round_robin", null, true, null,
null)), // no change "envoy.transport_sockets.tls", null)), // no change
Any.pack(mf.buildEdsCluster(CDS_RESOURCE, null, "round_robin", null, false, null, null))); Any.pack(mf.buildEdsCluster(CDS_RESOURCE, null, "round_robin", null, false, null,
"envoy.transport_sockets.tls", null
)));
call.sendResponse(CDS, clusters, VERSION_2, "0001"); call.sendResponse(CDS, clusters, VERSION_2, "0001");
verify(cdsResourceWatcher, times(2)).onChanged(cdsUpdateCaptor.capture()); verify(cdsResourceWatcher, times(2)).onChanged(cdsUpdateCaptor.capture());
assertThat(cdsUpdateCaptor.getValue().edsServiceName()).isNull(); assertThat(cdsUpdateCaptor.getValue().edsServiceName()).isNull();
@ -2100,9 +2164,10 @@ public abstract class ClientXdsClientTestBase {
Message hcmFilter = mf.buildHttpConnectionManagerFilter( Message hcmFilter = mf.buildHttpConnectionManagerFilter(
"route-foo.googleapis.com", null, Collections.<Message>emptyList()); "route-foo.googleapis.com", null, Collections.<Message>emptyList());
Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext( Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
"google-sds-config-default", "ROOTCA"); "google-sds-config-default", "ROOTCA", false);
Message filterChain = mf.buildFilterChain( Message filterChain = mf.buildFilterChain(
Collections.<String>emptyList(), downstreamTlsContext, hcmFilter); Collections.<String>emptyList(), downstreamTlsContext, "envoy.transport_sockets.tls",
hcmFilter);
Message listener = Message listener =
mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain); mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain);
List<Any> listeners = ImmutableList.of(Any.pack(listener)); List<Any> listeners = ImmutableList.of(Any.pack(listener));
@ -2133,9 +2198,10 @@ public abstract class ClientXdsClientTestBase {
Message hcmFilter = mf.buildHttpConnectionManagerFilter( Message hcmFilter = mf.buildHttpConnectionManagerFilter(
"route-foo.googleapis.com", null, Collections.<Message>emptyList()); "route-foo.googleapis.com", null, Collections.<Message>emptyList());
Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext( Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
"google-sds-config-default", "ROOTCA"); "google-sds-config-default", "ROOTCA", false);
Message filterChain = mf.buildFilterChain( Message filterChain = mf.buildFilterChain(
Collections.singletonList("managed-mtls"), downstreamTlsContext, hcmFilter); Collections.singletonList("managed-mtls"), downstreamTlsContext,
"envoy.transport_sockets.tls", hcmFilter);
Message listener = mf.buildListenerWithFilterChain( Message listener = mf.buildListenerWithFilterChain(
"grpc/server?xds.resource.listening_address=0.0.0.0:8000", 7000, "0.0.0.0", filterChain); "grpc/server?xds.resource.listening_address=0.0.0.0:8000", 7000, "0.0.0.0", filterChain);
List<Any> listeners = ImmutableList.of(Any.pack(listener)); List<Any> listeners = ImmutableList.of(Any.pack(listener));
@ -2150,6 +2216,53 @@ public abstract class ClientXdsClientTestBase {
assertThat(fakeClock.getPendingTasks(LDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty(); assertThat(fakeClock.getPendingTasks(LDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty();
} }
@Test
public void serverSideListenerResponseErrorHandling_badDownstreamTlsContext() {
Assume.assumeTrue(useProtocolV3());
ClientXdsClientTestBase.DiscoveryRpcCall call =
startResourceWatcher(LDS, LISTENER_RESOURCE, ldsResourceWatcher);
Message hcmFilter = mf.buildHttpConnectionManagerFilter(
"route-foo.googleapis.com", null, Collections.<Message>emptyList());
Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
null, null,false);
Message filterChain = mf.buildFilterChain(
Collections.<String>emptyList(), downstreamTlsContext, "envoy.transport_sockets.tls",
hcmFilter);
Message listener =
mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain);
List<Any> listeners = ImmutableList.of(Any.pack(listener));
call.sendResponse(ResourceType.LDS, listeners, "0", "0000");
// The response NACKed with errors indicating indices of the failed resources.
call.verifyRequestNack(LDS, LISTENER_RESOURCE, "", "0000", NODE, ImmutableList.of(
"LDS response Listener \'grpc/server?xds.resource.listening_address=0.0.0.0:7000\' "
+ "validation error: common-tls-context is required in downstream-tls-context"));
verifyNoInteractions(ldsResourceWatcher);
}
@Test
public void serverSideListenerResponseErrorHandling_badTransportSocketName() {
Assume.assumeTrue(useProtocolV3());
ClientXdsClientTestBase.DiscoveryRpcCall call =
startResourceWatcher(LDS, LISTENER_RESOURCE, ldsResourceWatcher);
Message hcmFilter = mf.buildHttpConnectionManagerFilter(
"route-foo.googleapis.com", null, Collections.<Message>emptyList());
Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
"cert1", "cert2",false);
Message filterChain = mf.buildFilterChain(
Collections.<String>emptyList(), downstreamTlsContext, "envoy.transport_sockets.bad1",
hcmFilter);
Message listener =
mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain);
List<Any> listeners = ImmutableList.of(Any.pack(listener));
call.sendResponse(ResourceType.LDS, listeners, "0", "0000");
// The response NACKed with errors indicating indices of the failed resources.
call.verifyRequestNack(LDS, LISTENER_RESOURCE, "", "0000", NODE, ImmutableList.of(
"LDS response Listener \'grpc/server?xds.resource.listening_address=0.0.0.0:7000\' "
+ "validation error: "
+ "transport-socket with name envoy.transport_sockets.bad1 not supported."));
verifyNoInteractions(ldsResourceWatcher);
}
private DiscoveryRpcCall startResourceWatcher( private DiscoveryRpcCall startResourceWatcher(
ResourceType type, String name, ResourceWatcher watcher) { ResourceType type, String name, ResourceWatcher watcher) {
FakeClock.TaskFilter timeoutTaskFilter; FakeClock.TaskFilter timeoutTaskFilter;
@ -2268,7 +2381,8 @@ public abstract class ClientXdsClientTestBase {
protected abstract Message buildEdsCluster(String clusterName, @Nullable String edsServiceName, protected abstract Message buildEdsCluster(String clusterName, @Nullable String edsServiceName,
String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs, String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs,
@Nullable Message upstreamTlsContext, @Nullable Message circuitBreakers); @Nullable Message upstreamTlsContext, String transportSocketName,
@Nullable Message circuitBreakers);
protected abstract Message buildLogicalDnsCluster(String clusterName, String dnsHostAddr, protected abstract Message buildLogicalDnsCluster(String clusterName, String dnsHostAddr,
int dnsHostPort, String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs, int dnsHostPort, String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs,
@ -2280,7 +2394,7 @@ public abstract class ClientXdsClientTestBase {
protected abstract Message buildRingHashLbConfig(String hashFunction, long minRingSize, protected abstract Message buildRingHashLbConfig(String hashFunction, long minRingSize,
long maxRingSize); long maxRingSize);
protected abstract Message buildUpstreamTlsContext(String secretName, String targetUri); protected abstract Message buildUpstreamTlsContext(String instanceName, String certName);
protected abstract Message buildCircuitBreakers(int highPriorityMaxRequests, protected abstract Message buildCircuitBreakers(int highPriorityMaxRequests,
int defaultPriorityMaxRequests); int defaultPriorityMaxRequests);
@ -2305,7 +2419,8 @@ public abstract class ClientXdsClientTestBase {
protected abstract Message buildDropOverload(String category, int dropPerMillion); protected abstract Message buildDropOverload(String category, int dropPerMillion);
protected abstract Message buildFilterChain( protected abstract Message buildFilterChain(
List<String> alpn, Message tlsContext, Message... filters); List<String> alpn, Message tlsContext, String transportSocketName,
Message... filters);
protected abstract Message buildListenerWithFilterChain( protected abstract Message buildListenerWithFilterChain(
String name, int portValue, String address, Message... filterChains); String name, int portValue, String address, Message... filterChains);

View File

@ -393,7 +393,8 @@ public class ClientXdsClientV2Test extends ClientXdsClientTestBase {
@Override @Override
protected Message buildEdsCluster(String clusterName, @Nullable String edsServiceName, protected Message buildEdsCluster(String clusterName, @Nullable String edsServiceName,
String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs, String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs,
@Nullable Message upstreamTlsContext, @Nullable Message circuitBreakers) { @Nullable Message upstreamTlsContext, String transportSocketName,
@Nullable Message circuitBreakers) {
Cluster.Builder builder = initClusterBuilder(clusterName, lbPolicy, ringHashLbConfig, Cluster.Builder builder = initClusterBuilder(clusterName, lbPolicy, ringHashLbConfig,
enableLrs, upstreamTlsContext, circuitBreakers); enableLrs, upstreamTlsContext, circuitBreakers);
builder.setType(DiscoveryType.EDS); builder.setType(DiscoveryType.EDS);
@ -493,10 +494,10 @@ public class ClientXdsClientV2Test extends ClientXdsClientTestBase {
} }
@Override @Override
protected Message buildUpstreamTlsContext(String secretName, String targetUri) { protected Message buildUpstreamTlsContext(String instanceName, String certName) {
GrpcService grpcService = GrpcService grpcService =
GrpcService.newBuilder() GrpcService.newBuilder()
.setGoogleGrpc(GoogleGrpc.newBuilder().setTargetUri(targetUri)) .setGoogleGrpc(GoogleGrpc.newBuilder().setTargetUri(certName))
.build(); .build();
ConfigSource sdsConfig = ConfigSource sdsConfig =
ConfigSource.newBuilder() ConfigSource.newBuilder()
@ -504,7 +505,7 @@ public class ClientXdsClientV2Test extends ClientXdsClientTestBase {
.build(); .build();
SdsSecretConfig validationContextSdsSecretConfig = SdsSecretConfig validationContextSdsSecretConfig =
SdsSecretConfig.newBuilder() SdsSecretConfig.newBuilder()
.setName(secretName) .setName(instanceName)
.setSdsConfig(sdsConfig) .setSdsConfig(sdsConfig)
.build(); .build();
return UpstreamTlsContext.newBuilder() return UpstreamTlsContext.newBuilder()
@ -618,7 +619,8 @@ public class ClientXdsClientV2Test extends ClientXdsClientTestBase {
} }
@Override @Override
protected Message buildFilterChain(List<String> alpn, Message tlsContext, Message... filters) { protected Message buildFilterChain(List<String> alpn, Message tlsContext,
String transportSocketName, Message... filters) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -42,10 +42,7 @@ import io.envoyproxy.envoy.config.cluster.v3.Cluster.RingHashLbConfig;
import io.envoyproxy.envoy.config.cluster.v3.Cluster.RingHashLbConfig.HashFunction; import io.envoyproxy.envoy.config.cluster.v3.Cluster.RingHashLbConfig.HashFunction;
import io.envoyproxy.envoy.config.core.v3.Address; import io.envoyproxy.envoy.config.core.v3.Address;
import io.envoyproxy.envoy.config.core.v3.AggregatedConfigSource; import io.envoyproxy.envoy.config.core.v3.AggregatedConfigSource;
import io.envoyproxy.envoy.config.core.v3.ApiConfigSource;
import io.envoyproxy.envoy.config.core.v3.ConfigSource; import io.envoyproxy.envoy.config.core.v3.ConfigSource;
import io.envoyproxy.envoy.config.core.v3.GrpcService;
import io.envoyproxy.envoy.config.core.v3.GrpcService.GoogleGrpc;
import io.envoyproxy.envoy.config.core.v3.HealthStatus; import io.envoyproxy.envoy.config.core.v3.HealthStatus;
import io.envoyproxy.envoy.config.core.v3.Locality; import io.envoyproxy.envoy.config.core.v3.Locality;
import io.envoyproxy.envoy.config.core.v3.Node; import io.envoyproxy.envoy.config.core.v3.Node;
@ -81,7 +78,6 @@ import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter; import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds; import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext; import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext; import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext;
import io.envoyproxy.envoy.service.discovery.v3.AggregatedDiscoveryServiceGrpc.AggregatedDiscoveryServiceImplBase; import io.envoyproxy.envoy.service.discovery.v3.AggregatedDiscoveryServiceGrpc.AggregatedDiscoveryServiceImplBase;
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryRequest; import io.envoyproxy.envoy.service.discovery.v3.DiscoveryRequest;
@ -437,9 +433,10 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
@Override @Override
protected Message buildEdsCluster(String clusterName, @Nullable String edsServiceName, protected Message buildEdsCluster(String clusterName, @Nullable String edsServiceName,
String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs, String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs,
@Nullable Message upstreamTlsContext, @Nullable Message circuitBreakers) { @Nullable Message upstreamTlsContext, String transportSocketName,
@Nullable Message circuitBreakers) {
Cluster.Builder builder = initClusterBuilder(clusterName, lbPolicy, ringHashLbConfig, Cluster.Builder builder = initClusterBuilder(clusterName, lbPolicy, ringHashLbConfig,
enableLrs, upstreamTlsContext, circuitBreakers); enableLrs, upstreamTlsContext, transportSocketName, circuitBreakers);
builder.setType(DiscoveryType.EDS); builder.setType(DiscoveryType.EDS);
EdsClusterConfig.Builder edsClusterConfigBuilder = EdsClusterConfig.newBuilder(); EdsClusterConfig.Builder edsClusterConfigBuilder = EdsClusterConfig.newBuilder();
edsClusterConfigBuilder.setEdsConfig( edsClusterConfigBuilder.setEdsConfig(
@ -456,7 +453,7 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
int dnsHostPort, String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs, int dnsHostPort, String lbPolicy, @Nullable Message ringHashLbConfig, boolean enableLrs,
@Nullable Message upstreamTlsContext, @Nullable Message circuitBreakers) { @Nullable Message upstreamTlsContext, @Nullable Message circuitBreakers) {
Cluster.Builder builder = initClusterBuilder(clusterName, lbPolicy, ringHashLbConfig, Cluster.Builder builder = initClusterBuilder(clusterName, lbPolicy, ringHashLbConfig,
enableLrs, upstreamTlsContext, circuitBreakers); enableLrs, upstreamTlsContext, "envoy.transport_sockets.tls", circuitBreakers);
builder.setType(DiscoveryType.LOGICAL_DNS); builder.setType(DiscoveryType.LOGICAL_DNS);
builder.setLoadAssignment( builder.setLoadAssignment(
ClusterLoadAssignment.newBuilder().addEndpoints( ClusterLoadAssignment.newBuilder().addEndpoints(
@ -492,7 +489,8 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
private Cluster.Builder initClusterBuilder(String clusterName, String lbPolicy, private Cluster.Builder initClusterBuilder(String clusterName, String lbPolicy,
@Nullable Message ringHashLbConfig, boolean enableLrs, @Nullable Message ringHashLbConfig, boolean enableLrs,
@Nullable Message upstreamTlsContext, @Nullable Message circuitBreakers) { @Nullable Message upstreamTlsContext, String transportSocketName,
@Nullable Message circuitBreakers) {
Cluster.Builder builder = Cluster.newBuilder(); Cluster.Builder builder = Cluster.newBuilder();
builder.setName(clusterName); builder.setName(clusterName);
if (lbPolicy.equals("round_robin")) { if (lbPolicy.equals("round_robin")) {
@ -511,7 +509,7 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
if (upstreamTlsContext != null) { if (upstreamTlsContext != null) {
builder.setTransportSocket( builder.setTransportSocket(
TransportSocket.newBuilder() TransportSocket.newBuilder()
.setName("envoy.transport_sockets.tls") .setName(transportSocketName)
.setTypedConfig(Any.pack(upstreamTlsContext))); .setTypedConfig(Any.pack(upstreamTlsContext)));
} }
if (circuitBreakers != null) { if (circuitBreakers != null) {
@ -537,24 +535,22 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
} }
@Override @Override
protected Message buildUpstreamTlsContext(String secretName, String targetUri) { protected Message buildUpstreamTlsContext(String instanceName, String certName) {
GrpcService grpcService = CommonTlsContext.Builder commonTlsContextBuilder = CommonTlsContext.newBuilder();
GrpcService.newBuilder() if (instanceName != null && certName != null) {
.setGoogleGrpc(GoogleGrpc.newBuilder().setTargetUri(targetUri)) CommonTlsContext.CertificateProviderInstance providerInstance =
.build(); CommonTlsContext.CertificateProviderInstance.newBuilder()
ConfigSource sdsConfig = .setInstanceName(instanceName)
ConfigSource.newBuilder() .setCertificateName(certName)
.setApiConfigSource(ApiConfigSource.newBuilder().addGrpcServices(grpcService)) .build();
.build(); CommonTlsContext.CombinedCertificateValidationContext combined =
SdsSecretConfig validationContextSdsSecretConfig = CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
SdsSecretConfig.newBuilder() .setValidationContextCertificateProviderInstance(providerInstance)
.setName(secretName) .build();
.setSdsConfig(sdsConfig) commonTlsContextBuilder.setCombinedValidationContext(combined);
.build(); }
return UpstreamTlsContext.newBuilder() return UpstreamTlsContext.newBuilder()
.setCommonTlsContext( .setCommonTlsContext(commonTlsContextBuilder)
CommonTlsContext.newBuilder()
.setValidationContextSdsSecretConfig(validationContextSdsSecretConfig))
.build(); .build();
} }
@ -664,7 +660,8 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override @Override
protected FilterChain buildFilterChain( protected FilterChain buildFilterChain(
List<String> alpn, Message tlsContext, Message... filters) { List<String> alpn, Message tlsContext, String transportSocketName,
Message... filters) {
FilterChainMatch filterChainMatch = FilterChainMatch filterChainMatch =
FilterChainMatch.newBuilder().addAllApplicationProtocols(alpn).build(); FilterChainMatch.newBuilder().addAllApplicationProtocols(alpn).build();
Filter[] filterArray = new Filter[filters.length]; Filter[] filterArray = new Filter[filters.length];
@ -677,7 +674,7 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
tlsContext == null tlsContext == null
? TransportSocket.getDefaultInstance() ? TransportSocket.getDefaultInstance()
: TransportSocket.newBuilder() : TransportSocket.newBuilder()
.setName("envoy.transport_sockets.tls") .setName(transportSocketName)
.setTypedConfig(Any.pack(tlsContext)) .setTypedConfig(Any.pack(tlsContext))
.build()) .build())
.addAllFilters(Arrays.asList(filterArray)) .addAllFilters(Arrays.asList(filterArray))

View File

@ -84,12 +84,14 @@ public class CommonTlsContextTestsUtil {
: CertificateValidationContext.newBuilder() : CertificateValidationContext.newBuilder()
.addAllMatchSubjectAltNames(matchSubjectAltNames) .addAllMatchSubjectAltNames(matchSubjectAltNames)
.build(); .build();
if (validationCertificateProviderInstance != null && certValidationContext != null) { if (validationCertificateProviderInstance != null) {
CombinedCertificateValidationContext.Builder combinedBuilder = CombinedCertificateValidationContext.Builder combinedBuilder =
CombinedCertificateValidationContext.newBuilder() CombinedCertificateValidationContext.newBuilder()
.setDefaultValidationContext(certValidationContext)
.setValidationContextCertificateProviderInstance( .setValidationContextCertificateProviderInstance(
validationCertificateProviderInstance); validationCertificateProviderInstance);
if (certValidationContext != null) {
combinedBuilder = combinedBuilder.setDefaultValidationContext(certValidationContext);
}
builder.setCombinedValidationContext(combinedBuilder); builder.setCombinedValidationContext(combinedBuilder);
} else if (validationCertificateProviderInstance != null) { } else if (validationCertificateProviderInstance != null) {
builder builder
@ -106,12 +108,14 @@ public class CommonTlsContextTestsUtil {
/** Helper method to build DownstreamTlsContext for multiple test classes. */ /** Helper method to build DownstreamTlsContext for multiple test classes. */
static DownstreamTlsContext buildDownstreamTlsContext( static DownstreamTlsContext buildDownstreamTlsContext(
CommonTlsContext commonTlsContext, boolean requireClientCert) { CommonTlsContext commonTlsContext, boolean requireClientCert) {
DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.Builder downstreamTlsContextBuilder =
DownstreamTlsContext.newBuilder() DownstreamTlsContext.newBuilder()
.setCommonTlsContext(commonTlsContext) .setRequireClientCertificate(BoolValue.of(requireClientCert));
.setRequireClientCertificate(BoolValue.of(requireClientCert)) if (commonTlsContext != null) {
.build(); downstreamTlsContextBuilder = downstreamTlsContextBuilder
return downstreamTlsContext; .setCommonTlsContext(commonTlsContext);
}
return downstreamTlsContextBuilder.build();
} }
/** Helper method to build DownstreamTlsContext for multiple test classes. */ /** Helper method to build DownstreamTlsContext for multiple test classes. */
@ -137,23 +141,25 @@ public class CommonTlsContextTestsUtil {
/** Helper method for creating DownstreamTlsContext values with names. */ /** Helper method for creating DownstreamTlsContext values with names. */
public static DownstreamTlsContext buildTestDownstreamTlsContext( public static DownstreamTlsContext buildTestDownstreamTlsContext(
String certName, String validationContextCertName) { String certName, String validationContextCertName, boolean useSans) {
return buildDownstreamTlsContext( CommonTlsContext commonTlsContext = null;
buildCommonTlsContextWithAdditionalValues( if (certName != null || validationContextCertName != null || useSans) {
"cert-instance-name", certName, commonTlsContext = buildCommonTlsContextWithAdditionalValues(
"val-cert-instance-name", validationContextCertName, "cert-instance-name", certName,
Arrays.asList( "val-cert-instance-name", validationContextCertName,
StringMatcher.newBuilder() useSans ? Arrays.asList(
.setExact("spiffe://grpc-sds-testing.svc.id.goog/ns/default/sa/bob") StringMatcher.newBuilder()
.build()), .setExact("spiffe://grpc-sds-testing.svc.id.goog/ns/default/sa/bob")
Arrays.asList("managed-tls")), .build()) : null,
/* requireClientCert= */ false); Arrays.asList("managed-tls"));
}
return buildDownstreamTlsContext(commonTlsContext, /* requireClientCert= */ false);
} }
public static EnvoyServerProtoData.DownstreamTlsContext buildTestInternalDownstreamTlsContext( public static EnvoyServerProtoData.DownstreamTlsContext buildTestInternalDownstreamTlsContext(
String certName, String validationContextName) { String certName, String validationContextName) {
return EnvoyServerProtoData.DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext( return EnvoyServerProtoData.DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext(
buildTestDownstreamTlsContext(certName, validationContextName)); buildTestDownstreamTlsContext(certName, validationContextName, true));
} }
public static String getTempFileNameForResourcesFile(String resFile) throws IOException { public static String getTempFileNameForResourcesFile(String resFile) throws IOException {