xds: fix implementation to comply with gRFC for security (#8468)

This commit is contained in:
sanjaypujare 2021-09-01 10:49:33 -07:00 committed by GitHub
parent 7cde473efa
commit b0b250024f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 204 additions and 328 deletions

View File

@ -84,7 +84,8 @@ public abstract class Bootstrapper {
private final String pluginName; private final String pluginName;
private final Map<String, ?> config; private final Map<String, ?> config;
CertificateProviderInfo(String pluginName, Map<String, ?> config) { @VisibleForTesting
public CertificateProviderInfo(String pluginName, Map<String, ?> config) {
this.pluginName = checkNotNull(pluginName, "pluginName"); this.pluginName = checkNotNull(pluginName, "pluginName");
this.config = checkNotNull(config, "config"); this.config = checkNotNull(config, "config");
} }
@ -135,8 +136,9 @@ public abstract class Bootstrapper {
} }
/** Returns the cert-providers config map. */ /** Returns the cert-providers config map. */
@Nullable
public Map<String, CertificateProviderInfo> getCertProviders() { public Map<String, CertificateProviderInfo> getCertProviders() {
return Collections.unmodifiableMap(certProviders); return certProviders == null ? null : Collections.unmodifiableMap(certProviders);
} }
@Nullable @Nullable

View File

@ -266,14 +266,20 @@ final class ClientXdsClient extends AbstractXdsClient {
private LdsUpdate processServerSideListener( private LdsUpdate processServerSideListener(
Listener proto, Set<String> rdsResources, boolean parseHttpFilter) Listener proto, Set<String> rdsResources, boolean parseHttpFilter)
throws ResourceInvalidException { throws ResourceInvalidException {
Set<String> certProviderInstances = null;
if (getBootstrapInfo() != null && getBootstrapInfo().getCertProviders() != null) {
certProviderInstances = getBootstrapInfo().getCertProviders().keySet();
}
return LdsUpdate.forTcpListener(parseServerSideListener( return LdsUpdate.forTcpListener(parseServerSideListener(
proto, rdsResources, tlsContextManager, filterRegistry, parseHttpFilter)); proto, rdsResources, tlsContextManager, filterRegistry, certProviderInstances,
parseHttpFilter));
} }
@VisibleForTesting @VisibleForTesting
static EnvoyServerProtoData.Listener parseServerSideListener( static EnvoyServerProtoData.Listener parseServerSideListener(
Listener proto, Set<String> rdsResources, TlsContextManager tlsContextManager, Listener proto, Set<String> rdsResources, TlsContextManager tlsContextManager,
FilterRegistry filterRegistry, boolean parseHttpFilter) throws ResourceInvalidException { FilterRegistry filterRegistry, Set<String> certProviderInstances, boolean parseHttpFilter)
throws ResourceInvalidException {
if (!proto.getTrafficDirection().equals(TrafficDirection.INBOUND)) { if (!proto.getTrafficDirection().equals(TrafficDirection.INBOUND)) {
throw new ResourceInvalidException( throw new ResourceInvalidException(
"Listener " + proto.getName() + " with invalid traffic direction: " "Listener " + proto.getName() + " with invalid traffic direction: "
@ -309,13 +315,13 @@ final class ClientXdsClient extends AbstractXdsClient {
for (io.envoyproxy.envoy.config.listener.v3.FilterChain fc : proto.getFilterChainsList()) { for (io.envoyproxy.envoy.config.listener.v3.FilterChain fc : proto.getFilterChainsList()) {
filterChains.add( filterChains.add(
parseFilterChain(fc, rdsResources, tlsContextManager, filterRegistry, uniqueSet, parseFilterChain(fc, rdsResources, tlsContextManager, filterRegistry, uniqueSet,
parseHttpFilter)); certProviderInstances, parseHttpFilter));
} }
FilterChain defaultFilterChain = null; FilterChain defaultFilterChain = null;
if (proto.hasDefaultFilterChain()) { if (proto.hasDefaultFilterChain()) {
defaultFilterChain = parseFilterChain( defaultFilterChain = parseFilterChain(
proto.getDefaultFilterChain(), rdsResources, tlsContextManager, filterRegistry, proto.getDefaultFilterChain(), rdsResources, tlsContextManager, filterRegistry,
null, parseHttpFilter); null, certProviderInstances, parseHttpFilter);
} }
return new EnvoyServerProtoData.Listener( return new EnvoyServerProtoData.Listener(
@ -326,7 +332,7 @@ final class ClientXdsClient extends AbstractXdsClient {
static FilterChain parseFilterChain( static FilterChain parseFilterChain(
io.envoyproxy.envoy.config.listener.v3.FilterChain proto, Set<String> rdsResources, io.envoyproxy.envoy.config.listener.v3.FilterChain proto, Set<String> rdsResources,
TlsContextManager tlsContextManager, FilterRegistry filterRegistry, TlsContextManager tlsContextManager, FilterRegistry filterRegistry,
Set<FilterChainMatch> uniqueSet, boolean parseHttpFilters) Set<FilterChainMatch> uniqueSet, Set<String> certProviderInstances, boolean parseHttpFilters)
throws ResourceInvalidException { throws ResourceInvalidException {
io.grpc.xds.HttpConnectionManager httpConnectionManager = null; io.grpc.xds.HttpConnectionManager httpConnectionManager = null;
HashSet<String> uniqueNames = new HashSet<>(); HashSet<String> uniqueNames = new HashSet<>();
@ -380,7 +386,7 @@ final class ClientXdsClient extends AbstractXdsClient {
} }
downstreamTlsContext = downstreamTlsContext =
EnvoyServerProtoData.DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext( EnvoyServerProtoData.DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext(
validateDownstreamTlsContext(downstreamTlsContextProto)); validateDownstreamTlsContext(downstreamTlsContextProto, certProviderInstances));
} }
String name = proto.getName(); String name = proto.getName();
@ -399,13 +405,12 @@ final class ClientXdsClient extends AbstractXdsClient {
} }
@VisibleForTesting @VisibleForTesting
static io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext static DownstreamTlsContext validateDownstreamTlsContext(
validateDownstreamTlsContext( DownstreamTlsContext downstreamTlsContext, Set<String> certProviderInstances)
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
downstreamTlsContext)
throws ResourceInvalidException { throws ResourceInvalidException {
if (downstreamTlsContext.hasCommonTlsContext()) { if (downstreamTlsContext.hasCommonTlsContext()) {
validateCommonTlsContext(downstreamTlsContext.getCommonTlsContext(), true); validateCommonTlsContext(downstreamTlsContext.getCommonTlsContext(), certProviderInstances,
true);
} else { } else {
throw new ResourceInvalidException( throw new ResourceInvalidException(
"common-tls-context is required in downstream-tls-context"); "common-tls-context is required in downstream-tls-context");
@ -414,22 +419,6 @@ final class ClientXdsClient extends AbstractXdsClient {
throw new ResourceInvalidException( throw new ResourceInvalidException(
"downstream-tls-context with require-sni is not supported"); "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 DownstreamTlsContext.OcspStaplePolicy ocspStaplePolicy = downstreamTlsContext
.getOcspStaplePolicy(); .getOcspStaplePolicy();
if (ocspStaplePolicy != DownstreamTlsContext.OcspStaplePolicy.UNRECOGNIZED if (ocspStaplePolicy != DownstreamTlsContext.OcspStaplePolicy.UNRECOGNIZED
@ -444,30 +433,22 @@ final class ClientXdsClient extends AbstractXdsClient {
@VisibleForTesting @VisibleForTesting
static io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext static io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
validateUpstreamTlsContext( validateUpstreamTlsContext(
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext upstreamTlsContext) io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext upstreamTlsContext,
Set<String> certProviderInstances)
throws ResourceInvalidException { throws ResourceInvalidException {
if (upstreamTlsContext.hasCommonTlsContext()) { if (upstreamTlsContext.hasCommonTlsContext()) {
validateCommonTlsContext(upstreamTlsContext.getCommonTlsContext(), false); validateCommonTlsContext(upstreamTlsContext.getCommonTlsContext(), certProviderInstances,
false);
} else { } else {
throw new ResourceInvalidException("common-tls-context is required in upstream-tls-context"); 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; return upstreamTlsContext;
} }
@VisibleForTesting @VisibleForTesting
static void validateCommonTlsContext( static void validateCommonTlsContext(
CommonTlsContext commonTlsContext, boolean server) throws ResourceInvalidException { CommonTlsContext commonTlsContext, Set<String> certProviderInstances, boolean server)
throws ResourceInvalidException {
if (commonTlsContext.hasCustomHandshaker()) { if (commonTlsContext.hasCustomHandshaker()) {
throw new ResourceInvalidException( throw new ResourceInvalidException(
"common-tls-context with custom_handshaker is not supported"); "common-tls-context with custom_handshaker is not supported");
@ -492,6 +473,7 @@ final class ClientXdsClient extends AbstractXdsClient {
"common-tls-context with validation_context_certificate_provider_instance is not" "common-tls-context with validation_context_certificate_provider_instance is not"
+ " supported"); + " supported");
} }
String certInstanceName = null;
if (!commonTlsContext.hasTlsCertificateCertificateProviderInstance()) { if (!commonTlsContext.hasTlsCertificateCertificateProviderInstance()) {
if (server) { if (server) {
throw new ResourceInvalidException( throw new ResourceInvalidException(
@ -509,7 +491,18 @@ final class ClientXdsClient extends AbstractXdsClient {
throw new ResourceInvalidException( throw new ResourceInvalidException(
"common-tls-context with tls_certificate_certificate_provider is not supported"); "common-tls-context with tls_certificate_certificate_provider is not supported");
} }
} else {
certInstanceName = commonTlsContext.getTlsCertificateCertificateProviderInstance()
.getInstanceName();
} }
if (certInstanceName != null) {
if (certProviderInstances == null || !certProviderInstances.contains(certInstanceName)) {
throw new ResourceInvalidException(
"CertificateProvider instance name '" + certInstanceName
+ "' not defined in the bootstrap file.");
}
}
String rootCaInstanceName = null;
if (!commonTlsContext.hasCombinedValidationContext()) { if (!commonTlsContext.hasCombinedValidationContext()) {
if (!server) { if (!server) {
throw new ResourceInvalidException( throw new ResourceInvalidException(
@ -523,6 +516,8 @@ final class ClientXdsClient extends AbstractXdsClient {
"validation_context_certificate_provider_instance is required in" "validation_context_certificate_provider_instance is required in"
+ " combined_validation_context"); + " combined_validation_context");
} }
rootCaInstanceName = combinedCertificateValidationContext
.getValidationContextCertificateProviderInstance().getInstanceName();
if (combinedCertificateValidationContext.hasDefaultValidationContext()) { if (combinedCertificateValidationContext.hasDefaultValidationContext()) {
CertificateValidationContext certificateValidationContext CertificateValidationContext certificateValidationContext
= combinedCertificateValidationContext.getDefaultValidationContext(); = combinedCertificateValidationContext.getDefaultValidationContext();
@ -530,14 +525,6 @@ final class ClientXdsClient extends AbstractXdsClient {
throw new ResourceInvalidException( throw new ResourceInvalidException(
"match_subject_alt_names only allowed in upstream_tls_context"); "match_subject_alt_names only allowed in upstream_tls_context");
} }
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) { if (certificateValidationContext.getVerifyCertificateSpkiCount() > 0) {
throw new ResourceInvalidException( throw new ResourceInvalidException(
"verify_certificate_spki in default_validation_context is not supported"); "verify_certificate_spki in default_validation_context is not supported");
@ -554,23 +541,19 @@ final class ClientXdsClient extends AbstractXdsClient {
if (certificateValidationContext.hasCrl()) { if (certificateValidationContext.hasCrl()) {
throw new ResourceInvalidException("crl in default_validation_context is not supported"); 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
!= CertificateValidationContext.TrustChainVerification.VERIFY_TRUST_CHAIN) {
throw new ResourceInvalidException(
"Only VERIFY_TRUST_CHAIN for trust_chain_verification supported");
}
if (certificateValidationContext.hasCustomValidatorConfig()) { if (certificateValidationContext.hasCustomValidatorConfig()) {
throw new ResourceInvalidException( throw new ResourceInvalidException(
"custom_validator_config in default_validation_context is not supported"); "custom_validator_config in default_validation_context is not supported");
} }
} }
} }
if (rootCaInstanceName != null) {
if (certProviderInstances == null || !certProviderInstances.contains(rootCaInstanceName)) {
throw new ResourceInvalidException(
"ValidationContextProvider instance name '" + rootCaInstanceName
+ "' not defined in the bootstrap file.");
}
}
} }
private static void checkForUniqueness(Set<FilterChainMatch> uniqueSet, private static void checkForUniqueness(Set<FilterChainMatch> uniqueSet,
@ -1397,7 +1380,11 @@ final class ClientXdsClient extends AbstractXdsClient {
// Process Cluster into CdsUpdate. // Process Cluster into CdsUpdate.
CdsUpdate cdsUpdate; CdsUpdate cdsUpdate;
try { try {
cdsUpdate = parseCluster(cluster, retainedEdsResources); Set<String> certProviderInstances = null;
if (getBootstrapInfo() != null && getBootstrapInfo().getCertProviders() != null) {
certProviderInstances = getBootstrapInfo().getCertProviders().keySet();
}
cdsUpdate = parseCluster(cluster, retainedEdsResources, certProviderInstances);
} catch (ResourceInvalidException e) { } catch (ResourceInvalidException e) {
errors.add( errors.add(
"CDS response Cluster '" + clusterName + "' validation error: " + e.getMessage()); "CDS response Cluster '" + clusterName + "' validation error: " + e.getMessage());
@ -1426,12 +1413,14 @@ final class ClientXdsClient extends AbstractXdsClient {
} }
@VisibleForTesting @VisibleForTesting
static CdsUpdate parseCluster(Cluster cluster, Set<String> retainedEdsResources) static CdsUpdate parseCluster(Cluster cluster, Set<String> retainedEdsResources,
Set<String> certProviderInstances)
throws ResourceInvalidException { throws ResourceInvalidException {
StructOrError<CdsUpdate.Builder> structOrError; StructOrError<CdsUpdate.Builder> structOrError;
switch (cluster.getClusterDiscoveryTypeCase()) { switch (cluster.getClusterDiscoveryTypeCase()) {
case TYPE: case TYPE:
structOrError = parseNonAggregateCluster(cluster, retainedEdsResources); structOrError = parseNonAggregateCluster(cluster, retainedEdsResources,
certProviderInstances);
break; break;
case CLUSTER_TYPE: case CLUSTER_TYPE:
structOrError = parseAggregateCluster(cluster); structOrError = parseAggregateCluster(cluster);
@ -1494,7 +1483,7 @@ final class ClientXdsClient extends AbstractXdsClient {
} }
private static StructOrError<CdsUpdate.Builder> parseNonAggregateCluster( private static StructOrError<CdsUpdate.Builder> parseNonAggregateCluster(
Cluster cluster, Set<String> edsResources) { Cluster cluster, Set<String> edsResources, Set<String> certProviderInstances) {
String clusterName = cluster.getName(); String clusterName = cluster.getName();
String lrsServerName = null; String lrsServerName = null;
Long maxConcurrentRequests = null; Long maxConcurrentRequests = null;
@ -1517,6 +1506,10 @@ final class ClientXdsClient extends AbstractXdsClient {
} }
} }
} }
if (cluster.getTransportSocketMatchesCount() > 0) {
return StructOrError.fromError("Cluster " + clusterName
+ ": transport-socket-matches not supported.");
}
if (cluster.hasTransportSocket()) { if (cluster.hasTransportSocket()) {
if (!TRANSPORT_SOCKET_NAME_TLS.equals(cluster.getTransportSocket().getName())) { if (!TRANSPORT_SOCKET_NAME_TLS.equals(cluster.getTransportSocket().getName())) {
return StructOrError.fromError("transport-socket with name " return StructOrError.fromError("transport-socket with name "
@ -1527,7 +1520,8 @@ final class ClientXdsClient extends AbstractXdsClient {
validateUpstreamTlsContext( 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),
certProviderInstances));
} catch (InvalidProtocolBufferException | ResourceInvalidException e) { } catch (InvalidProtocolBufferException | ResourceInvalidException e) {
return StructOrError.fromError( return StructOrError.fromError(
"Cluster " + clusterName + ": malformed UpstreamTlsContext: " + e); "Cluster " + clusterName + ": malformed UpstreamTlsContext: " + e);

View File

@ -32,6 +32,7 @@ import io.netty.handler.ssl.SslContextBuilder;
import java.security.cert.CertStoreException; import java.security.cert.CertStoreException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
/** A client SslContext provider using CertificateProviderInstance to fetch secrets. */ /** A client SslContext provider using CertificateProviderInstance to fetch secrets. */
@Internal @Internal
@ -39,7 +40,7 @@ public final class CertProviderClientSslContextProvider extends CertProviderSslC
private CertProviderClientSslContextProvider( private CertProviderClientSslContextProvider(
Node node, Node node,
Map<String, CertificateProviderInfo> certProviders, @Nullable Map<String, CertificateProviderInfo> certProviders,
CommonTlsContext.CertificateProviderInstance certInstance, CommonTlsContext.CertificateProviderInstance certInstance,
CommonTlsContext.CertificateProviderInstance rootCertInstance, CommonTlsContext.CertificateProviderInstance rootCertInstance,
CertificateValidationContext staticCertValidationContext, CertificateValidationContext staticCertValidationContext,
@ -90,7 +91,7 @@ public final class CertProviderClientSslContextProvider extends CertProviderSslC
public CertProviderClientSslContextProvider getProvider( public CertProviderClientSslContextProvider getProvider(
UpstreamTlsContext upstreamTlsContext, UpstreamTlsContext upstreamTlsContext,
Node node, Node node,
Map<String, CertificateProviderInfo> certProviders) { @Nullable Map<String, CertificateProviderInfo> certProviders) {
checkNotNull(upstreamTlsContext, "upstreamTlsContext"); checkNotNull(upstreamTlsContext, "upstreamTlsContext");
CommonTlsContext commonTlsContext = upstreamTlsContext.getCommonTlsContext(); CommonTlsContext commonTlsContext = upstreamTlsContext.getCommonTlsContext();
CommonTlsContext.CertificateProviderInstance rootCertInstance = null; CommonTlsContext.CertificateProviderInstance rootCertInstance = null;

View File

@ -35,6 +35,7 @@ import java.security.cert.CertStoreException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
/** A server SslContext provider using CertificateProviderInstance to fetch secrets. */ /** A server SslContext provider using CertificateProviderInstance to fetch secrets. */
@Internal @Internal
@ -42,7 +43,7 @@ public final class CertProviderServerSslContextProvider extends CertProviderSslC
private CertProviderServerSslContextProvider( private CertProviderServerSslContextProvider(
Node node, Node node,
Map<String, CertificateProviderInfo> certProviders, @Nullable Map<String, CertificateProviderInfo> certProviders,
CommonTlsContext.CertificateProviderInstance certInstance, CommonTlsContext.CertificateProviderInstance certInstance,
CommonTlsContext.CertificateProviderInstance rootCertInstance, CommonTlsContext.CertificateProviderInstance rootCertInstance,
CertificateValidationContext staticCertValidationContext, CertificateValidationContext staticCertValidationContext,
@ -93,7 +94,7 @@ public final class CertProviderServerSslContextProvider extends CertProviderSslC
public CertProviderServerSslContextProvider getProvider( public CertProviderServerSslContextProvider getProvider(
DownstreamTlsContext downstreamTlsContext, DownstreamTlsContext downstreamTlsContext,
Node node, Node node,
Map<String, CertificateProviderInfo> certProviders) { @Nullable Map<String, CertificateProviderInfo> certProviders) {
checkNotNull(downstreamTlsContext, "downstreamTlsContext"); checkNotNull(downstreamTlsContext, "downstreamTlsContext");
CommonTlsContext commonTlsContext = downstreamTlsContext.getCommonTlsContext(); CommonTlsContext commonTlsContext = downstreamTlsContext.getCommonTlsContext();
CommonTlsContext.CertificateProviderInstance rootCertInstance = null; CommonTlsContext.CertificateProviderInstance rootCertInstance = null;

View File

@ -42,7 +42,7 @@ abstract class CertProviderSslContextProvider extends DynamicSslContextProvider
protected CertProviderSslContextProvider( protected CertProviderSslContextProvider(
Node node, Node node,
Map<String, CertificateProviderInfo> certProviders, @Nullable Map<String, CertificateProviderInfo> certProviders,
CertificateProviderInstance certInstance, CertificateProviderInstance certInstance,
CertificateProviderInstance rootCertInstance, CertificateProviderInstance rootCertInstance,
CertificateValidationContext staticCertValidationContext, CertificateValidationContext staticCertValidationContext,
@ -56,8 +56,8 @@ abstract class CertProviderSslContextProvider extends DynamicSslContextProvider
certInstanceName = certInstance.getInstanceName(); certInstanceName = certInstance.getInstanceName();
CertificateProviderInfo certProviderInstanceConfig = CertificateProviderInfo certProviderInstanceConfig =
getCertProviderConfig(certProviders, certInstanceName); getCertProviderConfig(certProviders, certInstanceName);
certHandle = certHandle = certProviderInstanceConfig == null ? null
certificateProviderStore.createOrGetProvider( : certificateProviderStore.createOrGetProvider(
certInstance.getCertificateName(), certInstance.getCertificateName(),
certProviderInstanceConfig.getPluginName(), certProviderInstanceConfig.getPluginName(),
certProviderInstanceConfig.getConfig(), certProviderInstanceConfig.getConfig(),
@ -71,8 +71,8 @@ abstract class CertProviderSslContextProvider extends DynamicSslContextProvider
&& !rootCertInstance.getInstanceName().equals(certInstanceName)) { && !rootCertInstance.getInstanceName().equals(certInstanceName)) {
CertificateProviderInfo certProviderInstanceConfig = CertificateProviderInfo certProviderInstanceConfig =
getCertProviderConfig(certProviders, rootCertInstance.getInstanceName()); getCertProviderConfig(certProviders, rootCertInstance.getInstanceName());
rootCertHandle = rootCertHandle = certProviderInstanceConfig == null ? null
certificateProviderStore.createOrGetProvider( : certificateProviderStore.createOrGetProvider(
rootCertInstance.getCertificateName(), rootCertInstance.getCertificateName(),
certProviderInstanceConfig.getPluginName(), certProviderInstanceConfig.getPluginName(),
certProviderInstanceConfig.getConfig(), certProviderInstanceConfig.getConfig(),
@ -84,8 +84,8 @@ abstract class CertProviderSslContextProvider extends DynamicSslContextProvider
} }
private static CertificateProviderInfo getCertProviderConfig( private static CertificateProviderInfo getCertProviderConfig(
Map<String, CertificateProviderInfo> certProviders, String pluginInstanceName) { @Nullable Map<String, CertificateProviderInfo> certProviders, String pluginInstanceName) {
return certProviders.get(pluginInstanceName); return certProviders != null ? certProviders.get(pluginInstanceName) : null;
} }
@Override @Override

View File

@ -19,9 +19,9 @@ package io.grpc.xds;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
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.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.StringValue; import com.google.protobuf.StringValue;
import com.google.protobuf.UInt32Value; import com.google.protobuf.UInt32Value;
@ -46,7 +46,6 @@ 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.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;
@ -86,7 +85,6 @@ import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsCont
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig; 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.TlsCertificate;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.TlsParameters; 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.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;
@ -1130,7 +1128,7 @@ public class ClientXdsClientDataTest {
.setLbPolicy(LbPolicy.RING_HASH) .setLbPolicy(LbPolicy.RING_HASH)
.build(); .build();
CdsUpdate update = ClientXdsClient.parseCluster(cluster, new HashSet<String>()); CdsUpdate update = ClientXdsClient.parseCluster(cluster, new HashSet<String>(), null);
assertThat(update.lbPolicy()).isEqualTo(CdsUpdate.LbPolicy.RING_HASH); assertThat(update.lbPolicy()).isEqualTo(CdsUpdate.LbPolicy.RING_HASH);
assertThat(update.minRingSize()) assertThat(update.minRingSize())
.isEqualTo(ClientXdsClient.DEFAULT_RING_HASH_LB_POLICY_MIN_RING_SIZE); .isEqualTo(ClientXdsClient.DEFAULT_RING_HASH_LB_POLICY_MIN_RING_SIZE);
@ -1138,6 +1136,28 @@ public class ClientXdsClientDataTest {
.isEqualTo(ClientXdsClient.DEFAULT_RING_HASH_LB_POLICY_MAX_RING_SIZE); .isEqualTo(ClientXdsClient.DEFAULT_RING_HASH_LB_POLICY_MAX_RING_SIZE);
} }
@Test
public void parseCluster_transportSocketMatches_exception() throws ResourceInvalidException {
Cluster cluster = Cluster.newBuilder()
.setName("cluster-foo.googleapis.com")
.setType(DiscoveryType.EDS)
.setEdsClusterConfig(
EdsClusterConfig.newBuilder()
.setEdsConfig(
ConfigSource.newBuilder()
.setAds(AggregatedConfigSource.getDefaultInstance()))
.setServiceName("service-foo.googleapis.com"))
.setLbPolicy(LbPolicy.ROUND_ROBIN)
.addTransportSocketMatches(
Cluster.TransportSocketMatch.newBuilder().setName("match1").build())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"Cluster cluster-foo.googleapis.com: transport-socket-matches not supported.");
ClientXdsClient.parseCluster(cluster, new HashSet<String>(), null);
}
@Test @Test
public void parseCluster_ringHashLbPolicy_invalidRingSizeConfig_minGreaterThanMax() public void parseCluster_ringHashLbPolicy_invalidRingSizeConfig_minGreaterThanMax()
throws ResourceInvalidException { throws ResourceInvalidException {
@ -1160,7 +1180,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("Cluster cluster-foo.googleapis.com: invalid ring_hash_lb_config"); thrown.expectMessage("Cluster cluster-foo.googleapis.com: invalid ring_hash_lb_config");
ClientXdsClient.parseCluster(cluster, new HashSet<String>()); ClientXdsClient.parseCluster(cluster, new HashSet<String>(), null);
} }
@Test @Test
@ -1187,7 +1207,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("Cluster cluster-foo.googleapis.com: invalid ring_hash_lb_config"); thrown.expectMessage("Cluster cluster-foo.googleapis.com: invalid ring_hash_lb_config");
ClientXdsClient.parseCluster(cluster, new HashSet<String>()); ClientXdsClient.parseCluster(cluster, new HashSet<String>(), null);
} }
@Test @Test
@ -1200,7 +1220,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("Listener listener1 with invalid traffic direction: OUTBOUND"); thrown.expectMessage("Listener listener1 with invalid traffic direction: OUTBOUND");
ClientXdsClient.parseServerSideListener( ClientXdsClient.parseServerSideListener(
listener, new HashSet<String>(), null, filterRegistry, true /* does not matter */); listener, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */);
} }
@Test @Test
@ -1214,7 +1234,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("Listener listener1 cannot have listener_filters"); thrown.expectMessage("Listener listener1 cannot have listener_filters");
ClientXdsClient.parseServerSideListener( ClientXdsClient.parseServerSideListener(
listener, new HashSet<String>(), null, filterRegistry, true /* does not matter */); listener, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */);
} }
@Test @Test
@ -1228,7 +1248,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("Listener listener1 cannot have use_original_dst set to true"); thrown.expectMessage("Listener listener1 cannot have use_original_dst set to true");
ClientXdsClient.parseServerSideListener( ClientXdsClient.parseServerSideListener(
listener, new HashSet<String>(), null, filterRegistry, true /* does not matter */); listener, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */);
} }
@Test @Test
@ -1275,7 +1295,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("Found duplicate matcher:"); thrown.expectMessage("Found duplicate matcher:");
ClientXdsClient.parseServerSideListener( ClientXdsClient.parseServerSideListener(
listener, new HashSet<String>(), null, filterRegistry, true /* does not matter */); listener, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */);
} }
@Test @Test
@ -1322,7 +1342,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("Found duplicate matcher:"); thrown.expectMessage("Found duplicate matcher:");
ClientXdsClient.parseServerSideListener( ClientXdsClient.parseServerSideListener(
listener, new HashSet<String>(), null, filterRegistry, true /* does not matter */); listener, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */);
} }
@Test @Test
@ -1369,7 +1389,7 @@ public class ClientXdsClientDataTest {
.addAllFilterChains(Arrays.asList(filterChain1, filterChain2)) .addAllFilterChains(Arrays.asList(filterChain1, filterChain2))
.build(); .build();
ClientXdsClient.parseServerSideListener( ClientXdsClient.parseServerSideListener(
listener, new HashSet<String>(), null, filterRegistry, true /* does not matter */); listener, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */);
} }
@Test @Test
@ -1384,7 +1404,8 @@ public class ClientXdsClientDataTest {
thrown.expectMessage( thrown.expectMessage(
"FilterChain filter-chain-foo missing required HttpConnectionManager filter"); "FilterChain filter-chain-foo missing required HttpConnectionManager filter");
ClientXdsClient.parseFilterChain( ClientXdsClient.parseFilterChain(
filterChain, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */); filterChain, new HashSet<String>(), null, filterRegistry, null, null,
true /* does not matter */);
} }
@Test @Test
@ -1402,7 +1423,8 @@ public class ClientXdsClientDataTest {
thrown.expectMessage( thrown.expectMessage(
"FilterChain filter-chain-foo with duplicated filter: envoy.http_connection_manager"); "FilterChain filter-chain-foo with duplicated filter: envoy.http_connection_manager");
ClientXdsClient.parseFilterChain( ClientXdsClient.parseFilterChain(
filterChain, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */); filterChain, new HashSet<String>(), null, filterRegistry, null, null,
true /* does not matter */);
} }
@Test @Test
@ -1420,7 +1442,8 @@ public class ClientXdsClientDataTest {
"FilterChain filter-chain-foo contains filter envoy.http_connection_manager " "FilterChain filter-chain-foo contains filter envoy.http_connection_manager "
+ "without typed_config"); + "without typed_config");
ClientXdsClient.parseFilterChain( ClientXdsClient.parseFilterChain(
filterChain, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */); filterChain, new HashSet<String>(), null, filterRegistry, null, null,
true /* does not matter */);
} }
@Test @Test
@ -1442,7 +1465,8 @@ public class ClientXdsClientDataTest {
"FilterChain filter-chain-foo contains filter unsupported with unsupported " "FilterChain filter-chain-foo contains filter unsupported with unsupported "
+ "typed_config type unsupported-type-url"); + "typed_config type unsupported-type-url");
ClientXdsClient.parseFilterChain( ClientXdsClient.parseFilterChain(
filterChain, new HashSet<String>(), null, filterRegistry, null, true /* does not matter */); filterChain, new HashSet<String>(), null, filterRegistry, null, null,
true /* does not matter */);
} }
@Test @Test
@ -1468,10 +1492,10 @@ public class ClientXdsClientDataTest {
EnvoyServerProtoData.FilterChain parsedFilterChain1 = ClientXdsClient.parseFilterChain( EnvoyServerProtoData.FilterChain parsedFilterChain1 = ClientXdsClient.parseFilterChain(
filterChain1, new HashSet<String>(), null, filterRegistry, null, filterChain1, new HashSet<String>(), null, filterRegistry, null,
true /* does not matter */); null, true /* does not matter */);
EnvoyServerProtoData.FilterChain parsedFilterChain2 = ClientXdsClient.parseFilterChain( EnvoyServerProtoData.FilterChain parsedFilterChain2 = ClientXdsClient.parseFilterChain(
filterChain2, new HashSet<String>(), null, filterRegistry, null, filterChain2, new HashSet<String>(), null, filterRegistry, null,
true /* does not matter */); null, true /* does not matter */);
assertThat(parsedFilterChain1.getName()).isNotEqualTo(parsedFilterChain2.getName()); assertThat(parsedFilterChain1.getName()).isNotEqualTo(parsedFilterChain2.getName());
} }
@ -1483,7 +1507,7 @@ public class ClientXdsClientDataTest {
.build(); .build();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context with tls_params is not supported"); thrown.expectMessage("common-tls-context with tls_params is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1493,7 +1517,7 @@ public class ClientXdsClientDataTest {
.build(); .build();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context with custom_handshaker is not supported"); thrown.expectMessage("common-tls-context with custom_handshaker is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1503,7 +1527,7 @@ public class ClientXdsClientDataTest {
.build(); .build();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context with validation_context is not supported"); thrown.expectMessage("common-tls-context with validation_context is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1515,7 +1539,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage( thrown.expectMessage(
"common-tls-context with validation_context_sds_secret_config is not supported"); "common-tls-context with validation_context_sds_secret_config is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1528,7 +1552,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage( thrown.expectMessage(
"common-tls-context with validation_context_certificate_provider is not supported"); "common-tls-context with validation_context_certificate_provider is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1542,7 +1566,7 @@ public class ClientXdsClientDataTest {
thrown.expectMessage( thrown.expectMessage(
"common-tls-context with validation_context_certificate_provider_instance is not " "common-tls-context with validation_context_certificate_provider_instance is not "
+ "supported"); + "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1553,9 +1577,66 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage( thrown.expectMessage(
"tls_certificate_certificate_provider_instance is required in downstream-tls-context"); "tls_certificate_certificate_provider_instance is required in downstream-tls-context");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, true); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, true);
} }
@Test
public void validateCommonTlsContext_tlsCertificateProviderInstance()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setTlsCertificateCertificateProviderInstance(
CertificateProviderInstance.newBuilder().setInstanceName("name1").build())
.build();
ClientXdsClient
.validateCommonTlsContext(commonTlsContext, ImmutableSet.of("name1", "name2"), true);
}
@Test
public void validateCommonTlsContext_tlsCertificateProviderInstance_absentInBootstrapFile()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setTlsCertificateCertificateProviderInstance(
CertificateProviderInstance.newBuilder().setInstanceName("bad-name").build())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"CertificateProvider instance name 'bad-name' not defined in the bootstrap file.");
ClientXdsClient
.validateCommonTlsContext(commonTlsContext, ImmutableSet.of("name1", "name2"), true);
}
@Test
public void validateCommonTlsContext_validationContextProviderInstance()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CertificateProviderInstance.newBuilder().setInstanceName("name1").build())
.build())
.build();
ClientXdsClient
.validateCommonTlsContext(commonTlsContext, ImmutableSet.of("name1", "name2"), false);
}
@Test
public void validateCommonTlsContext_validationContextProviderInstance_absentInBootstrapFile()
throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
.setCombinedValidationContext(
CommonTlsContext.CombinedCertificateValidationContext.newBuilder()
.setValidationContextCertificateProviderInstance(
CertificateProviderInstance.newBuilder().setInstanceName("bad-name").build())
.build())
.build();
thrown.expect(ResourceInvalidException.class);
thrown.expectMessage(
"ValidationContextProvider instance name 'bad-name' not defined in the bootstrap file.");
ClientXdsClient
.validateCommonTlsContext(commonTlsContext, ImmutableSet.of("name1", "name2"), false);
}
@Test @Test
public void validateCommonTlsContext_tlsCertificatesCount() throws ResourceInvalidException { public void validateCommonTlsContext_tlsCertificatesCount() throws ResourceInvalidException {
CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder() CommonTlsContext commonTlsContext = CommonTlsContext.newBuilder()
@ -1563,7 +1644,7 @@ public class ClientXdsClientDataTest {
.build(); .build();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context with tls_certificates is not supported"); thrown.expectMessage("common-tls-context with tls_certificates is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1575,7 +1656,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage( thrown.expectMessage(
"common-tls-context with tls_certificate_sds_secret_configs is not supported"); "common-tls-context with tls_certificate_sds_secret_configs is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1588,7 +1669,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage( thrown.expectMessage(
"common-tls-context with tls_certificate_certificate_provider is not supported"); "common-tls-context with tls_certificate_certificate_provider is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1598,7 +1679,7 @@ public class ClientXdsClientDataTest {
.build(); .build();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("combined_validation_context is required in upstream-tls-context"); thrown.expectMessage("combined_validation_context is required in upstream-tls-context");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1612,7 +1693,7 @@ public class ClientXdsClientDataTest {
thrown.expectMessage( thrown.expectMessage(
"validation_context_certificate_provider_instance is required in " "validation_context_certificate_provider_instance is required in "
+ "combined_validation_context"); + "combined_validation_context");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, null, false);
} }
@Test @Test
@ -1631,43 +1712,7 @@ public class ClientXdsClientDataTest {
.build(); .build();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("match_subject_alt_names only allowed in upstream_tls_context"); thrown.expectMessage("match_subject_alt_names only allowed in upstream_tls_context");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, true); ClientXdsClient.validateCommonTlsContext(commonTlsContext, ImmutableSet.of(""), 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 @Test
@ -1686,7 +1731,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("verify_certificate_spki in default_validation_context is not " thrown.expectMessage("verify_certificate_spki in default_validation_context is not "
+ "supported"); + "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, ImmutableSet.of(""), false);
} }
@Test @Test
@ -1705,7 +1750,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("verify_certificate_hash in default_validation_context is not " thrown.expectMessage("verify_certificate_hash in default_validation_context is not "
+ "supported"); + "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, ImmutableSet.of(""), false);
} }
@Test @Test
@ -1725,7 +1770,7 @@ public class ClientXdsClientDataTest {
thrown.expectMessage( thrown.expectMessage(
"require_signed_certificate_timestamp in default_validation_context is not " "require_signed_certificate_timestamp in default_validation_context is not "
+ "supported"); + "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, ImmutableSet.of(""), false);
} }
@Test @Test
@ -1743,46 +1788,7 @@ public class ClientXdsClientDataTest {
.build(); .build();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("crl in default_validation_context is not supported"); thrown.expectMessage("crl in default_validation_context is not supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, ImmutableSet.of(""), 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 @Test
@ -1801,7 +1807,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("custom_validator_config in default_validation_context is not " thrown.expectMessage("custom_validator_config in default_validation_context is not "
+ "supported"); + "supported");
ClientXdsClient.validateCommonTlsContext(commonTlsContext, false); ClientXdsClient.validateCommonTlsContext(commonTlsContext, ImmutableSet.of(""), false);
} }
@Test @Test
@ -1809,7 +1815,7 @@ public class ClientXdsClientDataTest {
DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.getDefaultInstance(); DownstreamTlsContext downstreamTlsContext = DownstreamTlsContext.getDefaultInstance();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context is required in downstream-tls-context"); thrown.expectMessage("common-tls-context is required in downstream-tls-context");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext); ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext, null);
} }
@Test @Test
@ -1828,87 +1834,7 @@ public class ClientXdsClientDataTest {
.build(); .build();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("downstream-tls-context with require-sni is not supported"); thrown.expectMessage("downstream-tls-context with require-sni is not supported");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext); ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext, ImmutableSet.of(""));
}
@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 @Test
@ -1928,7 +1854,7 @@ public class ClientXdsClientDataTest {
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage( thrown.expectMessage(
"downstream-tls-context with ocsp_staple_policy value STRICT_STAPLING is not supported"); "downstream-tls-context with ocsp_staple_policy value STRICT_STAPLING is not supported");
ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext); ClientXdsClient.validateDownstreamTlsContext(downstreamTlsContext, ImmutableSet.of(""));
} }
@Test @Test
@ -1936,58 +1862,7 @@ public class ClientXdsClientDataTest {
UpstreamTlsContext upstreamTlsContext = UpstreamTlsContext.getDefaultInstance(); UpstreamTlsContext upstreamTlsContext = UpstreamTlsContext.getDefaultInstance();
thrown.expect(ResourceInvalidException.class); thrown.expect(ResourceInvalidException.class);
thrown.expectMessage("common-tls-context is required in upstream-tls-context"); thrown.expectMessage("common-tls-context is required in upstream-tls-context");
ClientXdsClient.validateUpstreamTlsContext(upstreamTlsContext); ClientXdsClient.validateUpstreamTlsContext(upstreamTlsContext, null);
}
@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) {

View File

@ -56,6 +56,7 @@ import io.grpc.internal.FakeClock.TaskFilter;
import io.grpc.internal.TimeProvider; import io.grpc.internal.TimeProvider;
import io.grpc.testing.GrpcCleanupRule; import io.grpc.testing.GrpcCleanupRule;
import io.grpc.xds.AbstractXdsClient.ResourceType; import io.grpc.xds.AbstractXdsClient.ResourceType;
import io.grpc.xds.Bootstrapper.CertificateProviderInfo;
import io.grpc.xds.Endpoints.DropOverload; import io.grpc.xds.Endpoints.DropOverload;
import io.grpc.xds.Endpoints.LbEndpoint; import io.grpc.xds.Endpoints.LbEndpoint;
import io.grpc.xds.Endpoints.LocalityLbEndpoints; import io.grpc.xds.Endpoints.LocalityLbEndpoints;
@ -273,7 +274,8 @@ public abstract class ClientXdsClientTestBase {
new Bootstrapper.ServerInfo( new Bootstrapper.ServerInfo(
SERVER_URI, InsecureChannelCredentials.create(), useProtocolV3())), SERVER_URI, InsecureChannelCredentials.create(), useProtocolV3())),
EnvoyProtoData.Node.newBuilder().build(), EnvoyProtoData.Node.newBuilder().build(),
null, ImmutableMap.of("cert-instance-name",
new CertificateProviderInfo("file-watcher", ImmutableMap.<String, Object>of())),
null); null);
xdsClient = xdsClient =
new ClientXdsClient( new ClientXdsClient(
@ -1327,7 +1329,8 @@ public abstract class ClientXdsClientTestBase {
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", "cert1"), "envoy.transport_sockets.tls", null)); mf.buildUpstreamTlsContext("cert-instance-name", "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)),
@ -1343,7 +1346,7 @@ public abstract class ClientXdsClientTestBase {
CommonTlsContext.CertificateProviderInstance certificateProviderInstance = CommonTlsContext.CertificateProviderInstance certificateProviderInstance =
cdsUpdate.upstreamTlsContext().getCommonTlsContext().getCombinedValidationContext() cdsUpdate.upstreamTlsContext().getCommonTlsContext().getCombinedValidationContext()
.getValidationContextCertificateProviderInstance(); .getValidationContextCertificateProviderInstance();
assertThat(certificateProviderInstance.getInstanceName()).isEqualTo("secret1"); assertThat(certificateProviderInstance.getInstanceName()).isEqualTo("cert-instance-name");
assertThat(certificateProviderInstance.getCertificateName()).isEqualTo("cert1"); assertThat(certificateProviderInstance.getCertificateName()).isEqualTo("cert1");
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);

View File

@ -146,7 +146,7 @@ public class CommonTlsContextTestsUtil {
if (certName != null || validationContextCertName != null || useSans) { if (certName != null || validationContextCertName != null || useSans) {
commonTlsContext = buildCommonTlsContextWithAdditionalValues( commonTlsContext = buildCommonTlsContextWithAdditionalValues(
"cert-instance-name", certName, "cert-instance-name", certName,
"val-cert-instance-name", validationContextCertName, "cert-instance-name", validationContextCertName,
useSans ? Arrays.asList( useSans ? Arrays.asList(
StringMatcher.newBuilder() StringMatcher.newBuilder()
.setExact("spiffe://grpc-sds-testing.svc.id.goog/ns/default/sa/bob") .setExact("spiffe://grpc-sds-testing.svc.id.goog/ns/default/sa/bob")