From 05a2380f9fe440eebb0e19a30709f6d4edd82466 Mon Sep 17 00:00:00 2001 From: "data-plane-api(Azure Pipelines)" Date: Wed, 4 Aug 2021 01:45:31 +0000 Subject: [PATCH] xds: restructure CertificateProvider fields (#17201) When these fields were originally added, we didn't fully understand how the `CertificateValidationContext` configuration worked. A `CertificateProvider` cannot provide a full `CertificateValidationContext` proto; it provides only the CA certs (i.e., the `trusted_ca` field within the `CertificateValidationContext` proto). So this PR makes the following changes: - Duplicates the `CertificateProvider` and `CertificateProviderInstance` messages from `CommonTlsContext` as `CertificateProviderPlugin` and `CertificateProviderPluginInstance` outside of `CommonTlsContext` (in common.proto instead of tls.proto). (Note that this also paves the way for reusing these messages for SPIFFE validation in the future.) - Adds new `CertificateProviderPlugin` and `CertificateProviderPluginInstance` fields to `CertificateValidationContext`, as an alternative to the existing `trusted_ca` field. (Added annotations to make this a `oneof` in the future.) - In `CommonTlsContext`, I have deprecated the `validation_context_certificate_provider` and `validation_context_certificate_provider_instance` fields both in the `validation_context_type` oneof and in `CombinedValidationContext`. - In `CommonTlsContext`, I have replaced the `tls_certificate_certificate_provider` and `tls_certificate_certificate_provider_instance` fields with new fields that use the new messages outside of `CommonTlsContext`. Risk Level: Low Testing: N/A Docs Changes: Included in PR Release Notes: N/A Platform Specific Features: N/A Signed-off-by: Mark D. Roth Mirrored from https://github.com/envoyproxy/envoy @ b29d6543e7568a8a3e772c7909a1daa182acc670 --- .../extensions/transport_sockets/tls/v3/BUILD | 1 + .../transport_sockets/tls/v3/common.proto | 38 +++++++- .../transport_sockets/tls/v3/tls.proto | 69 +++++++++----- .../tls/v4alpha/common.proto | 94 +++++++++++++------ .../transport_sockets/tls/v4alpha/tls.proto | 79 ++++++++-------- 5 files changed, 190 insertions(+), 91 deletions(-) diff --git a/envoy/extensions/transport_sockets/tls/v3/BUILD b/envoy/extensions/transport_sockets/tls/v3/BUILD index 4485559a..47b9b9ae 100644 --- a/envoy/extensions/transport_sockets/tls/v3/BUILD +++ b/envoy/extensions/transport_sockets/tls/v3/BUILD @@ -6,6 +6,7 @@ licenses(["notice"]) # Apache 2 api_proto_package( deps = [ + "//envoy/annotations:pkg", "//envoy/api/v2/auth:pkg", "//envoy/config/core/v3:pkg", "//envoy/type/matcher/v3:pkg", diff --git a/envoy/extensions/transport_sockets/tls/v3/common.proto b/envoy/extensions/transport_sockets/tls/v3/common.proto index aa05a31f..82dcb37c 100644 --- a/envoy/extensions/transport_sockets/tls/v3/common.proto +++ b/envoy/extensions/transport_sockets/tls/v3/common.proto @@ -9,6 +9,7 @@ import "envoy/type/matcher/v3/string.proto"; import "google/protobuf/any.proto"; import "google/protobuf/wrappers.proto"; +import "udpa/annotations/migrate.proto"; import "udpa/annotations/sensitive.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; @@ -232,7 +233,27 @@ message TlsSessionTicketKeys { [(validate.rules).repeated = {min_items: 1}, (udpa.annotations.sensitive) = true]; } -// [#next-free-field: 13] +// Indicates a certificate to be obtained from a named CertificateProvider plugin instance. +// The plugin instances are defined in the client's bootstrap file. +// The plugin allows certificates to be fetched/refreshed over the network asynchronously with +// respect to the TLS handshake. +// [#not-implemented-hide:] +message CertificateProviderPluginInstance { + // Provider instance name. If not present, defaults to "default". + // + // Instance names should generally be defined not in terms of the underlying provider + // implementation (e.g., "file_watcher") but rather in terms of the function of the + // certificates (e.g., "foo_deployment_identity"). + string instance_name = 1; + + // Opaque name used to specify certificate instances or types. For example, "ROOTCA" to specify + // a root-certificate (validation context) or "example.com" to specify a certificate for a + // particular domain. Not all provider instances will actually use this field, so the value + // defaults to the empty string. + string certificate_name = 2; +} + +// [#next-free-field: 14] message CertificateValidationContext { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.auth.CertificateValidationContext"; @@ -279,7 +300,20 @@ message CertificateValidationContext { // directory for any file moves to support rotation. This currently only // applies to dynamic secrets, when the *CertificateValidationContext* is // delivered via SDS. - config.core.v3.DataSource trusted_ca = 1; + // + // Only one of *trusted_ca* and *ca_certificate_provider_instance* may be specified. + // + // [#next-major-version: This field and watched_directory below should ideally be moved into a + // separate sub-message, since there's no point in specifying the latter field without this one.] + config.core.v3.DataSource trusted_ca = 1 + [(udpa.annotations.field_migrate).oneof_promotion = "ca_cert_source"]; + + // Certificate provider instance for fetching TLS certificates. + // + // Only one of *trusted_ca* and *ca_certificate_provider_instance* may be specified. + // [#not-implemented-hide:] + CertificateProviderPluginInstance ca_certificate_provider_instance = 13 + [(udpa.annotations.field_migrate).oneof_promotion = "ca_cert_source"]; // If specified, updates of a file-based *trusted_ca* source will be triggered // by this watch. This allows explicit control over the path watched, by diff --git a/envoy/extensions/transport_sockets/tls/v3/tls.proto b/envoy/extensions/transport_sockets/tls/v3/tls.proto index 02287de5..f6802079 100644 --- a/envoy/extensions/transport_sockets/tls/v3/tls.proto +++ b/envoy/extensions/transport_sockets/tls/v3/tls.proto @@ -9,7 +9,7 @@ import "envoy/extensions/transport_sockets/tls/v3/secret.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/wrappers.proto"; -import "udpa/annotations/migrate.proto"; +import "envoy/annotations/deprecation.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; import "validate/validate.proto"; @@ -125,12 +125,18 @@ message DownstreamTlsContext { } // TLS context shared by both client and server TLS contexts. -// [#next-free-field: 14] +// [#next-free-field: 15] message CommonTlsContext { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.auth.CommonTlsContext"; // Config for Certificate provider to get certificates. This provider should allow certificates to be // fetched/refreshed over the network asynchronously with respect to the TLS handshake. + // + // DEPRECATED: This message is not currently used, but if we ever do need it, we will want to + // move it out of CommonTlsContext and into common.proto, similar to the existing + // CertificateProviderPluginInstance message. + // + // [#not-implemented-hide:] message CertificateProvider { // opaque name used to specify certificate instances or types. For example, "ROOTCA" to specify // a root-certificate (validation context) or "TLS" to specify a new tls-certificate. @@ -151,6 +157,11 @@ message CommonTlsContext { // Similar to CertificateProvider above, but allows the provider instances to be configured on // the client side instead of being sent from the control plane. + // + // DEPRECATED: This message was moved outside of CommonTlsContext + // and now lives in common.proto. + // + // [#not-implemented-hide:] message CertificateProviderInstance { // Provider instance name. This name must be defined in the client's configuration (e.g., a // bootstrap file) to correspond to a provider instance (i.e., the same data in the typed_config @@ -179,26 +190,20 @@ message CommonTlsContext { // Config for fetching validation context via SDS API. Note SDS API allows certificates to be // fetched/refreshed over the network asynchronously with respect to the TLS handshake. - // Only one of validation_context_sds_secret_config, validation_context_certificate_provider, - // or validation_context_certificate_provider_instance may be used. - SdsSecretConfig validation_context_sds_secret_config = 2 [ - (validate.rules).message = {required: true}, - (udpa.annotations.field_migrate).oneof_promotion = "dynamic_validation_context" - ]; + SdsSecretConfig validation_context_sds_secret_config = 2 + [(validate.rules).message = {required: true}]; - // Certificate provider for fetching validation context. - // Only one of validation_context_sds_secret_config, validation_context_certificate_provider, - // or validation_context_certificate_provider_instance may be used. + // Certificate provider for fetching CA certs. This will populate the + // *default_validation_context.trusted_ca* field. // [#not-implemented-hide:] CertificateProvider validation_context_certificate_provider = 3 - [(udpa.annotations.field_migrate).oneof_promotion = "dynamic_validation_context"]; + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; - // Certificate provider instance for fetching validation context. - // Only one of validation_context_sds_secret_config, validation_context_certificate_provider, - // or validation_context_certificate_provider_instance may be used. + // Certificate provider instance for fetching CA certs. This will populate the + // *default_validation_context.trusted_ca* field. // [#not-implemented-hide:] CertificateProviderInstance validation_context_certificate_provider_instance = 4 - [(udpa.annotations.field_migrate).oneof_promotion = "dynamic_validation_context"]; + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; } reserved 5; @@ -212,6 +217,12 @@ message CommonTlsContext { // Only a single TLS certificate is supported in client contexts. In server contexts, the first // RSA certificate is used for clients that only support RSA and the first ECDSA certificate is // used for clients that support ECDSA. + // + // Only one of *tls_certificates*, *tls_certificate_sds_secret_configs*, + // and *tls_certificate_provider_instance* may be used. + // [#next-major-version: These mutually exclusive fields should ideally be in a oneof, but it's + // not legal to put a repeated field in a oneof. In the next major version, we should rework + // this to avoid this problem.] repeated TlsCertificate tls_certificates = 2; // Configs for fetching TLS certificates via SDS API. Note SDS API allows certificates to be @@ -220,18 +231,30 @@ message CommonTlsContext { // The same number and types of certificates as :ref:`tls_certificates ` // are valid in the the certificates fetched through this setting. // - // If :ref:`tls_certificates ` - // is non-empty, this field is ignored. + // Only one of *tls_certificates*, *tls_certificate_sds_secret_configs*, + // and *tls_certificate_provider_instance* may be used. + // [#next-major-version: These mutually exclusive fields should ideally be in a oneof, but it's + // not legal to put a repeated field in a oneof. In the next major version, we should rework + // this to avoid this problem.] repeated SdsSecretConfig tls_certificate_sds_secret_configs = 6 [(validate.rules).repeated = {max_items: 2}]; + // Certificate provider instance for fetching TLS certs. + // + // Only one of *tls_certificates*, *tls_certificate_sds_secret_configs*, + // and *tls_certificate_provider_instance* may be used. + // [#not-implemented-hide:] + CertificateProviderPluginInstance tls_certificate_provider_instance = 14; + // Certificate provider for fetching TLS certificates. // [#not-implemented-hide:] - CertificateProvider tls_certificate_certificate_provider = 9; + CertificateProvider tls_certificate_certificate_provider = 9 + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; // Certificate provider instance for fetching TLS certificates. // [#not-implemented-hide:] - CertificateProviderInstance tls_certificate_certificate_provider_instance = 11; + CertificateProviderInstance tls_certificate_certificate_provider_instance = 11 + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; oneof validation_context_type { // How to validate peer certificates. @@ -252,11 +275,13 @@ message CommonTlsContext { // Certificate provider for fetching validation context. // [#not-implemented-hide:] - CertificateProvider validation_context_certificate_provider = 10; + CertificateProvider validation_context_certificate_provider = 10 + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; // Certificate provider instance for fetching validation context. // [#not-implemented-hide:] - CertificateProviderInstance validation_context_certificate_provider_instance = 12; + CertificateProviderInstance validation_context_certificate_provider_instance = 12 + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; } // Supplies the list of ALPN protocols that the listener should expose. In diff --git a/envoy/extensions/transport_sockets/tls/v4alpha/common.proto b/envoy/extensions/transport_sockets/tls/v4alpha/common.proto index e696fffc..4e4488c7 100644 --- a/envoy/extensions/transport_sockets/tls/v4alpha/common.proto +++ b/envoy/extensions/transport_sockets/tls/v4alpha/common.proto @@ -234,7 +234,30 @@ message TlsSessionTicketKeys { [(validate.rules).repeated = {min_items: 1}, (udpa.annotations.sensitive) = true]; } -// [#next-free-field: 13] +// Indicates a certificate to be obtained from a named CertificateProvider plugin instance. +// The plugin instances are defined in the client's bootstrap file. +// The plugin allows certificates to be fetched/refreshed over the network asynchronously with +// respect to the TLS handshake. +// [#not-implemented-hide:] +message CertificateProviderPluginInstance { + option (udpa.annotations.versioning).previous_message_type = + "envoy.extensions.transport_sockets.tls.v3.CertificateProviderPluginInstance"; + + // Provider instance name. If not present, defaults to "default". + // + // Instance names should generally be defined not in terms of the underlying provider + // implementation (e.g., "file_watcher") but rather in terms of the function of the + // certificates (e.g., "foo_deployment_identity"). + string instance_name = 1; + + // Opaque name used to specify certificate instances or types. For example, "ROOTCA" to specify + // a root-certificate (validation context) or "example.com" to specify a certificate for a + // particular domain. Not all provider instances will actually use this field, so the value + // defaults to the empty string. + string certificate_name = 2; +} + +// [#next-free-field: 14] message CertificateValidationContext { option (udpa.annotations.versioning).previous_message_type = "envoy.extensions.transport_sockets.tls.v3.CertificateValidationContext"; @@ -254,34 +277,47 @@ message CertificateValidationContext { reserved "verify_subject_alt_name"; - // TLS certificate data containing certificate authority certificates to use in verifying - // a presented peer certificate (e.g. server certificate for clusters or client certificate - // for listeners). If not specified and a peer certificate is presented it will not be - // verified. By default, a client certificate is optional, unless one of the additional - // options (:ref:`require_client_certificate - // `, - // :ref:`verify_certificate_spki - // `, - // :ref:`verify_certificate_hash - // `, or - // :ref:`match_subject_alt_names - // `) is also - // specified. - // - // It can optionally contain certificate revocation lists, in which case Envoy will verify - // that the presented peer certificate has not been revoked by one of the included CRLs. Note - // that if a CRL is provided for any certificate authority in a trust chain, a CRL must be - // provided for all certificate authorities in that chain. Failure to do so will result in - // verification failure for both revoked and unrevoked certificates from that chain. - // - // See :ref:`the TLS overview ` for a list of common - // system CA locations. - // - // If *trusted_ca* is a filesystem path, a watch will be added to the parent - // directory for any file moves to support rotation. This currently only - // applies to dynamic secrets, when the *CertificateValidationContext* is - // delivered via SDS. - config.core.v4alpha.DataSource trusted_ca = 1; + oneof ca_cert_source { + // TLS certificate data containing certificate authority certificates to use in verifying + // a presented peer certificate (e.g. server certificate for clusters or client certificate + // for listeners). If not specified and a peer certificate is presented it will not be + // verified. By default, a client certificate is optional, unless one of the additional + // options (:ref:`require_client_certificate + // `, + // :ref:`verify_certificate_spki + // `, + // :ref:`verify_certificate_hash + // `, or + // :ref:`match_subject_alt_names + // `) is also + // specified. + // + // It can optionally contain certificate revocation lists, in which case Envoy will verify + // that the presented peer certificate has not been revoked by one of the included CRLs. Note + // that if a CRL is provided for any certificate authority in a trust chain, a CRL must be + // provided for all certificate authorities in that chain. Failure to do so will result in + // verification failure for both revoked and unrevoked certificates from that chain. + // + // See :ref:`the TLS overview ` for a list of common + // system CA locations. + // + // If *trusted_ca* is a filesystem path, a watch will be added to the parent + // directory for any file moves to support rotation. This currently only + // applies to dynamic secrets, when the *CertificateValidationContext* is + // delivered via SDS. + // + // Only one of *trusted_ca* and *ca_certificate_provider_instance* may be specified. + // + // [#next-major-version: This field and watched_directory below should ideally be moved into a + // separate sub-message, since there's no point in specifying the latter field without this one.] + config.core.v4alpha.DataSource trusted_ca = 1; + + // Certificate provider instance for fetching TLS certificates. + // + // Only one of *trusted_ca* and *ca_certificate_provider_instance* may be specified. + // [#not-implemented-hide:] + CertificateProviderPluginInstance ca_certificate_provider_instance = 13; + } // If specified, updates of a file-based *trusted_ca* source will be triggered // by this watch. This allows explicit control over the path watched, by diff --git a/envoy/extensions/transport_sockets/tls/v4alpha/tls.proto b/envoy/extensions/transport_sockets/tls/v4alpha/tls.proto index b92cae61..0a7d9267 100644 --- a/envoy/extensions/transport_sockets/tls/v4alpha/tls.proto +++ b/envoy/extensions/transport_sockets/tls/v4alpha/tls.proto @@ -124,13 +124,19 @@ message DownstreamTlsContext { } // TLS context shared by both client and server TLS contexts. -// [#next-free-field: 14] +// [#next-free-field: 15] message CommonTlsContext { option (udpa.annotations.versioning).previous_message_type = "envoy.extensions.transport_sockets.tls.v3.CommonTlsContext"; // Config for Certificate provider to get certificates. This provider should allow certificates to be // fetched/refreshed over the network asynchronously with respect to the TLS handshake. + // + // DEPRECATED: This message is not currently used, but if we ever do need it, we will want to + // move it out of CommonTlsContext and into common.proto, similar to the existing + // CertificateProviderPluginInstance message. + // + // [#not-implemented-hide:] message CertificateProvider { option (udpa.annotations.versioning).previous_message_type = "envoy.extensions.transport_sockets.tls.v3.CommonTlsContext.CertificateProvider"; @@ -154,6 +160,11 @@ message CommonTlsContext { // Similar to CertificateProvider above, but allows the provider instances to be configured on // the client side instead of being sent from the control plane. + // + // DEPRECATED: This message was moved outside of CommonTlsContext + // and now lives in common.proto. + // + // [#not-implemented-hide:] message CertificateProviderInstance { option (udpa.annotations.versioning).previous_message_type = "envoy.extensions.transport_sockets.tls.v3.CommonTlsContext.CertificateProviderInstance"; @@ -180,33 +191,25 @@ message CommonTlsContext { "envoy.extensions.transport_sockets.tls.v3.CommonTlsContext." "CombinedCertificateValidationContext"; + reserved 3, 4; + + reserved "validation_context_certificate_provider", + "validation_context_certificate_provider_instance"; + // How to validate peer certificates. CertificateValidationContext default_validation_context = 1 [(validate.rules).message = {required: true}]; - oneof dynamic_validation_context { - // Config for fetching validation context via SDS API. Note SDS API allows certificates to be - // fetched/refreshed over the network asynchronously with respect to the TLS handshake. - // Only one of validation_context_sds_secret_config, validation_context_certificate_provider, - // or validation_context_certificate_provider_instance may be used. - SdsSecretConfig validation_context_sds_secret_config = 2 - [(validate.rules).message = {required: true}]; - - // Certificate provider for fetching validation context. - // Only one of validation_context_sds_secret_config, validation_context_certificate_provider, - // or validation_context_certificate_provider_instance may be used. - // [#not-implemented-hide:] - CertificateProvider validation_context_certificate_provider = 3; - - // Certificate provider instance for fetching validation context. - // Only one of validation_context_sds_secret_config, validation_context_certificate_provider, - // or validation_context_certificate_provider_instance may be used. - // [#not-implemented-hide:] - CertificateProviderInstance validation_context_certificate_provider_instance = 4; - } + // Config for fetching validation context via SDS API. Note SDS API allows certificates to be + // fetched/refreshed over the network asynchronously with respect to the TLS handshake. + SdsSecretConfig validation_context_sds_secret_config = 2 + [(validate.rules).message = {required: true}]; } - reserved 5; + reserved 5, 9, 11, 10, 12; + + reserved "tls_certificate_certificate_provider", "tls_certificate_certificate_provider_instance", + "validation_context_certificate_provider", "validation_context_certificate_provider_instance"; // TLS protocol versions, cipher suites etc. TlsParameters tls_params = 1; @@ -217,6 +220,12 @@ message CommonTlsContext { // Only a single TLS certificate is supported in client contexts. In server contexts, the first // RSA certificate is used for clients that only support RSA and the first ECDSA certificate is // used for clients that support ECDSA. + // + // Only one of *tls_certificates*, *tls_certificate_sds_secret_configs*, + // and *tls_certificate_provider_instance* may be used. + // [#next-major-version: These mutually exclusive fields should ideally be in a oneof, but it's + // not legal to put a repeated field in a oneof. In the next major version, we should rework + // this to avoid this problem.] repeated TlsCertificate tls_certificates = 2; // Configs for fetching TLS certificates via SDS API. Note SDS API allows certificates to be @@ -225,18 +234,20 @@ message CommonTlsContext { // The same number and types of certificates as :ref:`tls_certificates ` // are valid in the the certificates fetched through this setting. // - // If :ref:`tls_certificates ` - // is non-empty, this field is ignored. + // Only one of *tls_certificates*, *tls_certificate_sds_secret_configs*, + // and *tls_certificate_provider_instance* may be used. + // [#next-major-version: These mutually exclusive fields should ideally be in a oneof, but it's + // not legal to put a repeated field in a oneof. In the next major version, we should rework + // this to avoid this problem.] repeated SdsSecretConfig tls_certificate_sds_secret_configs = 6 [(validate.rules).repeated = {max_items: 2}]; - // Certificate provider for fetching TLS certificates. - // [#not-implemented-hide:] - CertificateProvider tls_certificate_certificate_provider = 9; - - // Certificate provider instance for fetching TLS certificates. + // Certificate provider instance for fetching TLS certs. + // + // Only one of *tls_certificates*, *tls_certificate_sds_secret_configs*, + // and *tls_certificate_provider_instance* may be used. // [#not-implemented-hide:] - CertificateProviderInstance tls_certificate_certificate_provider_instance = 11; + CertificateProviderPluginInstance tls_certificate_provider_instance = 14; oneof validation_context_type { // How to validate peer certificates. @@ -254,14 +265,6 @@ message CommonTlsContext { // CertificateValidationContext, and concatenates repeated fields to default // CertificateValidationContext, and logical OR is applied to boolean fields. CombinedCertificateValidationContext combined_validation_context = 8; - - // Certificate provider for fetching validation context. - // [#not-implemented-hide:] - CertificateProvider validation_context_certificate_provider = 10; - - // Certificate provider instance for fetching validation context. - // [#not-implemented-hide:] - CertificateProviderInstance validation_context_certificate_provider_instance = 12; } // Supplies the list of ALPN protocols that the listener should expose. In