From f0e341c7c89c151cae06bff22f41e52f5fa76f78 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Fri, 29 May 2020 10:01:38 -0700 Subject: [PATCH 01/26] A29: xDS-Based Security for gRPC Clients and Servers --- A29-xds-tls-security.md | 411 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 A29-xds-tls-security.md diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md new file mode 100644 index 000000000..2fc665e50 --- /dev/null +++ b/A29-xds-tls-security.md @@ -0,0 +1,411 @@ +A29: xDS-Based Security for gRPC Clients and Servers +---- +* Author(s): [Sanjay M. Pujare](https://github.com/sanjaypujare), [Easwar Swaminathan](https://github.com/easwars), [Yash Tibrewal](https://github.com/yashykt) +* Approver: markdroth +* Status: Draft +* Implemented in: C-core, Java, and Go +* Last updated: 2021-06-08 +* Discussion at: + +## Abstract + +This proposal seeks to add transport security (i.e. TLS or mTLS) to xDS-managed +gRPC connections. (m)TLS adds encryption and authentication capabilities to the +connections. RBAC or client authorization is not part of this proposal but is covered in +[A41:xDS RBAC Support](https://github.com/grpc/proposal/pull/237/files). + +The proposal describes what is already implemented in the 3 core gRPC languages +and seeks to formalize these implementations. + +## Background + +With the addition of server side xDS support +[A36: xDS-Enabled Servers](https://github.com/grpc/proposal/blob/master/A36-xds-for-servers.md), +it is now possible to configure both client (for TLS origination) and server (for TLS termination) +ends of a gRPC connection from the control plane when the infrastructure provides the required +security or certificate capabilities. + +xDS [Listener](https://github.com/envoyproxy/envoy/blob/master/api/envoy/config/listener/v3/listener.proto) +provides server side TLS configuration in something called +[DownstreamTlsContext](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L57) +and the xDS [Cluster](https://github.com/envoyproxy/envoy/blob/master/api/envoy/config/cluster/v3/cluster.proto) +provides client side TLS configuration in something called +[UpstreamTlsContext](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26). +Through these configurations, the xDS-control plane can instruct xDS endpoints to use the infrastructure +provided certificates and keys for their connections which replaces manual provisioning and management of +these certificates. We provide a specification for interpreting and applying these configurations in gRPC. +We also extend the gRPC programming API and the xDS support in gRPC so developers can programmatically +enable (or disable) the use of these configurations. + + +### Related Proposals + +[A27: xDS-Based Global Load Balancing](A27-xds-global-load-balancing.md) + +[A36: xDS-Enabled Servers](A36-xds-for-servers.md) + +[Java: Channel and Server Credentials](L74-java-channel-creds.md) + +[L46: C-core: New TLS Credentials API](https://github.com/grpc/proposal/pull/205) + +## Proposal + +### Programming API + +For each language, the channel and server credentials have been extended to allow a gRPC +channel and server to use xDS provided security configurations. A Xds- Channel or Server credentials +also needs to be provided with something called a fallback credentials. The fallback credentials +is used in the following cases: + +- when xDS is not in use such as when the `xds:` scheme is not used on the client side + +- xDS is in use but the control plane does not provide security configuration. + +The fallback credentials is *not* used in case of error situations e.g. when there is +an error in using the xDS provided security configuration. + +Note that a user is not required to use Xds- Channel or Server Credentials even if they are +using an xDS managed channel or server. Not using Xds Channel or Server Credentials results +into not using xDS-provided TLS configuration. + +On the client side, an XdsChannelCredentials is used and on the server side an +XdsServerCredentials is used as described in the example snippets below. In these examples, +a plaintext or insecure credentials is used as the fallback credentials. + + +#### C++ + +Use of XdsChannelCredentials: + +```C++ + std::shared_ptr credentials = + grpc::experimental::XdsCredentials(grpc::InsecureChannelCredentials()); + std::shared_ptr channel = grpc::CreateChannel(target, credentials); +``` + +Use of XdsServerCredentials: + +```C++ + // TODO: yashykt to add +``` + +#### Java + +Use of XdsChannelCredentials: + +```Java + ChannelCredentials credentials = XdsChannelCredentials.create(InsecureChannelCredentials.create()); + ManagedChannel channel = Grpc.newChannelBuilder(target, credentials).build(); +``` + +Use of XdsServerCredentials: + +```Java + ServerCredentials credentials = XdsServerCredentials.create(InsecureServerCredentials.create()); + Server server = XdsServerBuilder.forPort(port, credentials) + .addService(new HostnameGreeter(hostname)) + .build() + .start(); +``` + +#### Go + +Use of XdsChannelCredentials: + +```Go + // TODO: easwars to add +``` + +Use of XdsServerCredentials: + +```Go + // TODO: easwars to add +``` + +### xDS Protocol + +gRPC uses CDS to configure client side security and LDS for server side security as described below. +The required fields were added to xDS v3 hence xDS v3 is a pre-requisite for this proposal. + +#### CDS for Client Side Security + +The CDS policy is the top level LB policy applied to all the connections under that policy. +[A27:CDS](A27-xds-global-load-balancing.md#cds) describes the flow. The field +[`transport_socket`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/cluster/v3/cluster.proto#L937) +is used to extract the [`UpstreamTlsContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26) +as described [here](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/cluster/v3/cluster.proto#L937). +Note that we don't (currently) support +[`transport_socket_matches`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/cluster/v3/cluster.proto#L680). +The `UpstreamTlsContext` thus obtained is passed down to all the child policies and connections. +How this is done is language dependent and is similar to how the implementations pass policy +information down to child policies. + +[`common_tls_context`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L37) +in the `UpstreamTlsContext` contains the required security configuration. All the other fields are ignored. See below for +[`CommonTlsContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L129) +processing. + +#### LDS for Server Side Security + +Server-side xDS processing is described in [A36: xDS-Enabled Servers](A36-xds-for-servers.md). +An LDS may have one or more [`filter_chains`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener.proto#L120) +and one of those `filter_chain`s is matched against an incoming connection in order to get and apply +the security (and other) configuration for that connection as described in the +[`FilterChainMatch`](A36-xds-for-servers.md#filterchainmatch). The +[`transport_socket`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener_components.proto#L246) +of the matched (selected) `filter_chain` is used to extract the +[`DownstreamTlsContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L57) +as described +[here](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener_components.proto#L246). +The `DownstreamTlsContext` thus obtained is used for the incoming connection. + +[`common_tls_context`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L84) +in the `DownstreamTlsContext` contains the required security configuration. The +[`require_client_certificate`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L88) field +determines whether the client certificate is required (mTLS mode if `true`, TLS if `false`). +All the other fields are ignored. See below for +[`CommonTlsContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L129) +processing. + + +#### CommonTlsContext Processing + +`CommonTlsContext` is present in both the `UpstreamTlsContext` and `DownstreamTlsContext` protos and contains the +certificate and key configuration information needed on the client and server side respectively. The configuration +tells gRPC how to obtain certificates and the keys for the TLS handshake. Although there are various ways to obtain +certificates as per this proto (which are supported by Envoy), gRPC supports only one of them and that is defined by the +[`CertificateProviderInstance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L154) +proto which is based on the notion of CertificateProvider plugin framework (described later). +The field `instance_name` defines a CertificateProvider "instance" that gRPC looks up in the +bootstrap file (described later) to obtain the CertificateProvider configuration. This +configuration along with the CertificateProvider plugin framework enables gRPC to acquire +the certificates necessary for the TLS handshake. + +The field [`tls_certificate_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L234) +is used for the local certificate and the private key. And either +[`validation_context_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L259) +or [`validation_context_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L200) +inside [`combined_validation_context`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251) +is used for the root certificate-chain for validating peer certificates. For mTLS both the local certificate +and root certificate are needed at both client and server. For TLS the server needs only the local certificate +(the [`tls_certificate_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L234)) +and the client needs only the root certificate +(the [`validation_context_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L200)). + +gRPC silently ignores the other fields in `CommonTlsContext` pertaining to other ways of fetching +TLS certificates and keys. Also the processing and parsing of `CommonTlsContext` for any particular +CDS or LDS response does not take into account whether the Xds credentials are in effect for the +respective channel or server. + + +### Use of SPIFFE IDs in Certificates + +To facilitate service mesh secure communication, we support [SPIFFE](https://github.com/spiffe/spiffe) based +certificates and peer certificate verification following the [SPIFFE](https://github.com/spiffe/spiffe) +specification and the [match_subject_alt_names](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#envoy-v3-api-field-extensions-transport-sockets-tls-v3-certificatevalidationcontext-match-subject-alt-names) field in xDS. + +### Certificate Provider Plugin Framework + +The pluggable Certificate Provider framework in gRPC underlies the use of `CertificateProviderInstance` +configuration. The framework supports "Certificate Providers" as pluggable and custom components (plugins) +used for dynamically fetching certificates used during the TLS handshake of gRPC channel and server connections. + +This document discusses just enough of the framework to explain the use-case. Users who want to +implement new plugins will need to understand the detailed design of the framework in the +respective language. + +Envoy was the original and only consumer of the xDS protocol and its security features were tied to +Envoy's security capabilities such as fetching certificates from the file-system or +using a separate SDS protocol to fetch certificates from an agent (that's not defined in the xDS +architecture). Instead of emulating Envoy's functionality and limitations in this area, we decided to +have a generic Certificate Provider plugin architecture in gRPC with the following characteristics: + +* the xDS control plane is not aware of the plugin specifics including its name, instantiation +mechanism or configuration requirements. + +* all of these are abstracted out into a single “plugin-instance-name” which is resolved into an +actual Certificate provider instance using the local bootstrap file and the framework (as explained +later). + +* the xDS control plane only references the “plugin-instance-name”s: it uses one for the local +certificates and another one for root certificates to validate the peer certificates (aka +[`CertificateValidationContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L236)). + +#### Main Elements of the Framework + +**`CertificateProvider`** represents an actual plugin that fetches or "mints" the required certificates +and keys. One example of a (already implemented) plugin is a `FileWatcherCertificateProvider` which +monitors certain files in the file system and reads those files on updates to get the latest +certificates and keys and provide those to the consumers after converting them to the canonical +format e.g. `java.security.PrivateKey` and `java.security.cert.X509Certificate` in Java. +Another example is a plugin that periodically "mints" new certificates by creating +CSRs at regular intervals and getting those signed by a Certification Authority (CA) that is +configured into the plugin. + +A client registers itself as a **`Watcher`** of the plugin to receive certificate updates. +The plugin supports multiple **`Watchers`** to be registered and uses a **`DistributorWatcher`** +internally to propagate a single update to multiple **`Watchers`**. A plugin caches the latest +certificate (and key) it has fetched (or minted) and delivers them to every newly registered +watcher. + +The `CertificateProvider` plugin also has an associated factory or +provider implementation (**`CertificateProviderFactory`**) to instantiate the plugin and this +factory is identified by a unique name e.g. `"file_watcher"` which is also the identity of the +plugin. The factory is responsible for instantiating the plugin after validating the received +configuration. + +**`CertificateProviderRegistry`** is a registry of all registered plugins supported by the gRPC library. +A **`CertificateProviderFactory`** registers itself in the registry. + +**`CertificateProviderStore`** is a store or global map of all instantiated plugins. In this map +the key is the plugin-name plus its config and the value is a reference counted instantiated plugin. +Reference counting ensures that a plugin with a given name and configuration combination is only +instantiated once. A client of the framework looks up a plugin by name and config and adds itself +as a **`Watcher`**. If the plugin is not already present, the store uses the registry to +instantiate it. It then increments the reference-count and adds the new **`Watcher`** to the +**`DistributorWatcher`** of the plugin. The plugin typically creates a new thread and a +timer to periodically fetch or mint a new certificate and send the certificate (and the key) to +all its watchers. + +### Bootstrap File Additions for Security + +The [bootstrap file](A27-xds-global-load-balancing.md#xdsclient-and-bootstrap-file) with +[server side support](A36-xds-for-servers.md#xds-protocol) needs further changes as described +here. The following snippet shows the additions for the `file_watcher` plugin that is +already implemented in all gRPC languages. +``` +{ + // "certificate_providers" contains configurations for all supported plugins + "certificate_providers": { + "google_cloud_private_spiffe": { // certificate_provider_instance name + "plugin_name": "file_watcher", // name of the plugin + "config": { // config to be supplied to the plugin + "certificate_file": "/var/run/gke-spiffe/certs/certificates.pem", + "private_key_file": "/var/run/gke-spiffe/certs/private_key.pem", + "ca_certificate_file": "/var/run/gke-spiffe/certs/ca_certificates.pem", + "refresh_interval": "60s" + } + } + } +} +``` + +`"certificate_providers"` is a new top level field whose value is a map (a JSON object). +The key in this map is the certificate_provider_instance name and the value is a JSON object +having exactly 2 fields: + +* `"plugin_name"` which is the name of the plugin (a string value), and +* `"config"` which is the configuration for the plugin. The value of `"config"` is a JSON object +whose schema is defined by that plugin. + +In the above example, the config for the file_watcher plugin contains 4 fields: the first 3 +fields are the file paths for the identity certificate, private key and the root (or CA) +certificate respectively. The last field is the certificate refresh interval i.e. the interval +to be used by the plugin to monitor the file paths to refresh the certificates. + +#### Use of Bootstrap File by the Certificate Provider Plugin Framework + +The xDS control plane specifies a certificate_provider_instance name as described above in +[CommonTlsContext Processing](#commontlscontext-processing). For this example, let's assume +it uses `"google_cloud_private_spiffe"` as the `"instance_name"` in +`tls_certificate_certificate_provider_instance`. gRPC looks up +`"google_cloud_private_spiffe"` in the `"certificate_providers"` map loaded from the +bootstrap file and use the JSON object value to extract the plugin name (value of +`"plugin_name"` as a string) and configuration (value of `"config"` as a JSON object). +It passes on these values to the `CertificateProviderStore` to retrieve +(after instantiating if necessary) the associated `CertificateProvider` plugin. +The caller of the framework registers a watcher with the plugin to receive +certificate updates as described below. + +### Implementing Security in the xDS Flow + +Let's see how gRPC enables security in xDS managed clients and servers by putting it all +together. Note that gRPC uses the existing low level TLS handshaker code/libraries +(aka security connector or handshaker) after making the certificates and keys available +to that code. The TLS handshaker functionality (which is language dependent) is +out of scope of this document. + +#### Client Side Flow + +The gRPC client xDS flow is described in +[gRPC Client Architecture](./A27-xds-global-load-balancing.md#grpc-client-architecture). +The resolver returns a `Cluster` resource for a channel and the CDS for that cluster has the +[UpstreamTlsContext](https://github.com/envoyproxy/envoy/blob/35702fed462f63a0a237cfbfdf26184272207c11/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L27) +containing the security configuration to be applied to all the child policies of that cluster. +When a channel is using `XdsChannelCredentials`, gRPC processes the `UpstreamTlsContext` +as described [above](#cds-for-client-side-security). + +At this stage the CDS policy uses the flow described above in +[Use of Bootstrap File by the Certificate Provider Plugin Framework](#use-of-bootstrap-file-by-the-certificate-provider-plugin-framework) +to fetch the requisite `CertificateProvider`s (one or two as the case may be). These `CertificateProvider`s, +in one form or another, need to be made available to all the sub-channels of the cluster. How this is +done is language dependent. For example, C-core uses the channel args to pass the individual +`CertificateProvider`s whereas Java constructs a dynamic `SslContextProvider` that is directly +usable by the sub-channel's TLS handshaker to build an `SslContext` for the impending handshake. + +##### Server Authorization aka Subject-Alt-Name Checks + +If [match_subject_alt_names](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L373) +is populated in the +[combined_validation_context](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251) +of the received `UpstreamTlsContext` then gRPC validates the SAN entries in the server certificate +by matching the `match_subject_alt_names` values using the +[StringMatcher](https://github.com/envoyproxy/envoy/blob/main/api/envoy/type/matcher/string.proto#L20) +semantics. This is called server authorization because this is how a client "authorizes" a server for +the connection. + +The implementation is language dependent. As an example, Java uses an implementation +of `X509TrustManager` through the `SslContext` provided to the client sub-channel. The other +languages use similar hooks provided by the underlying TLS framework to implement server +authorization. + +#### Server Side Flow + +The gRPC server xDS flow is described in +[gRPC Server ](./A27-xds-global-load-balancing.md#grpc-client-architecture). The server +configuration comes from the +[`Listener`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener.proto#L39) +resource which contains a list of +[`FilterChain`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener_components.proto#L193)s. +The `FilterChain` contains the `DownstreamTlsContext` that is applied to an incoming connection +after selecting the best-matching `FilterChain` as described in +[FilterChainMatch](A36-xds-for-servers.md#filterchainmatch). If the server is using `XdsServerCredentials`, +gRPC processes the `DownstreamTlsContext` as described [above](#lds-for-server-side-security) and then +uses the flow described above in +[Use of Bootstrap File by the Certificate Provider Plugin Framework](#use-of-bootstrap-file-by-the-certificate-provider-plugin-framework) +to fetch the requisite `CertificateProvider`s (one or two as the case may be). These `CertificateProvider`s, +in one form or another, need to be made available to the incoming connection. Similar to the +client side, this part of the flow is language dependent. For example, Java constructs a dynamic +`SslContextProvider` that is directly usable by the connection's TLS handshaker to build an +`SslContext` for the impending handshake. + +## Rationale + +gRPC has been steadily adding support for various xDS features including load balancing and +advanced traffic management. xDS-based security was next in the roadmap and this proposal +addresses that. gRPC makes a proxyless service mesh (PSM) possible. A secure proxyless +service mesh requires the security features described in this proposal. + +The Certificate Provider Plugin Framework does not depend on an agent (SDS server). The +SDS server/agent based solution compromised security (by sharing the private key with the +agent). The combination of Envoy sidecar and the SDS server was also somewhat tied to the +Kubernetes architecture where Envoy runs in a sidecar container and the SDS server runs +as a Node agent in the cluster. The Certificate Provider Plugin Framework has eliminated that +dependency. The framework has also made the certificate provider functionality extensible +and pluggable which enables support for new certificate providers without requiring +changes to the xDS protocol or the control plane. These advantages plus the extensions +made to the xDS protocol are providing an impetus to the Envoy community so that Envoy +will hopefully have a similar framework in the near future to support pluggable and +extensible certificate providers. + +In any case the addition of xDS based security has brought gRPC xDS support closer to +Envoy in terms of capabilities. This enables various use-cases such as migration to +proxyless and interop or co-existence with Envoy. + +## Implementation + +Java had an early prototype implementation of xDS-based security that used SDS similar to Envoy. It was +then modified and refined to match this spec. Other languages followed soon after to complete +the implementation. The implementations (in Java, C++ and Go) are currently "hidden" behing the +environment variable `GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT` which will be removed +once this proposal is official. From 414e01c80dff3ed2ff57a7be582d4e73ed659fd2 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Wed, 23 Jun 2021 21:58:02 -0700 Subject: [PATCH 02/26] address review comments --- A29-xds-tls-security.md | 187 +++++++++++++++++++++------------------- 1 file changed, 99 insertions(+), 88 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 2fc665e50..82cde903b 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -12,41 +12,38 @@ A29: xDS-Based Security for gRPC Clients and Servers This proposal seeks to add transport security (i.e. TLS or mTLS) to xDS-managed gRPC connections. (m)TLS adds encryption and authentication capabilities to the connections. RBAC or client authorization is not part of this proposal but is covered in -[A41:xDS RBAC Support](https://github.com/grpc/proposal/pull/237/files). +[A41:xDS RBAC Support][A41]. -The proposal describes what is already implemented in the 3 core gRPC languages -and seeks to formalize these implementations. +[A41]: https://github.com/grpc/proposal/pull/237/files ## Background With the addition of server side xDS support -[A36: xDS-Enabled Servers](https://github.com/grpc/proposal/blob/master/A36-xds-for-servers.md), +[A36: xDS-Enabled Servers][A36], it is now possible to configure both client (for TLS origination) and server (for TLS termination) ends of a gRPC connection from the control plane when the infrastructure provides the required security or certificate capabilities. -xDS [Listener](https://github.com/envoyproxy/envoy/blob/master/api/envoy/config/listener/v3/listener.proto) -provides server side TLS configuration in something called -[DownstreamTlsContext](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L57) -and the xDS [Cluster](https://github.com/envoyproxy/envoy/blob/master/api/envoy/config/cluster/v3/cluster.proto) -provides client side TLS configuration in something called -[UpstreamTlsContext](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26). -Through these configurations, the xDS-control plane can instruct xDS endpoints to use the infrastructure -provided certificates and keys for their connections which replaces manual provisioning and management of -these certificates. We provide a specification for interpreting and applying these configurations in gRPC. +xDS [Listener][] provides server side TLS configuration in +[DownstreamTlsContext][DTC] and the xDS [Cluster][] provides client side TLS configuration in +[UpstreamTlsContext][UTC]. Through these configurations, the xDS-control plane can instruct +xDS endpoints to use the infrastructure provided certificates and keys for their connections +which replaces manual provisioning and management of these certificates. We provide a +specification for interpreting and applying these configurations in gRPC. We also extend the gRPC programming API and the xDS support in gRPC so developers can programmatically enable (or disable) the use of these configurations. +[Listener]: https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener.proto +[Cluster]: https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/cluster/v3/cluster.proto ### Related Proposals -[A27: xDS-Based Global Load Balancing](A27-xds-global-load-balancing.md) + * [A27: xDS-Based Global Load Balancing][A27] + * [A36: xDS-Enabled Servers][A36] + * [Java: Channel and Server Credentials][L74] -[A36: xDS-Enabled Servers](A36-xds-for-servers.md) - -[Java: Channel and Server Credentials](L74-java-channel-creds.md) - -[L46: C-core: New TLS Credentials API](https://github.com/grpc/proposal/pull/205) +[A27]: A27-xds-global-load-balancing.md +[L74]: L74-java-channel-creds.md ## Proposal @@ -54,7 +51,7 @@ enable (or disable) the use of these configurations. For each language, the channel and server credentials have been extended to allow a gRPC channel and server to use xDS provided security configurations. A Xds- Channel or Server credentials -also needs to be provided with something called a fallback credentials. The fallback credentials +also needs to be provided with a "fallback credentials". The fallback credentials is used in the following cases: - when xDS is not in use such as when the `xds:` scheme is not used on the client side @@ -130,43 +127,48 @@ The required fields were added to xDS v3 hence xDS v3 is a pre-requisite for thi #### CDS for Client Side Security The CDS policy is the top level LB policy applied to all the connections under that policy. -[A27:CDS](A27-xds-global-load-balancing.md#cds) describes the flow. The field -[`transport_socket`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/cluster/v3/cluster.proto#L937) -is used to extract the [`UpstreamTlsContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26) -as described [here](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/cluster/v3/cluster.proto#L937). -Note that we don't (currently) support -[`transport_socket_matches`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/cluster/v3/cluster.proto#L680). +[A27:CDS][] describes the flow. The field [`transport_socket`][CL-TS] is used to extract the +[`UpstreamTlsContext`][UTC] as described [here][CL-TS-comment]. +Note that we don't (currently) support [`transport_socket_matches`][CL-TS-matches]. The `UpstreamTlsContext` thus obtained is passed down to all the child policies and connections. How this is done is language dependent and is similar to how the implementations pass policy information down to child policies. -[`common_tls_context`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L37) -in the `UpstreamTlsContext` contains the required security configuration. All the other fields are ignored. See below for -[`CommonTlsContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L129) -processing. +[`common_tls_context`][CTC] in the `UpstreamTlsContext` contains the required security configuration. +All other fields are ignored. See below for [`CommonTlsContext`][CTC-type] processing. + +[A27:CDS]: A27-xds-global-load-balancing.md#cds +[CL-TS]: https://github.com/envoyproxy/envoy/blob/9aca65c395f01020080166e4795455addde167fa/api/envoy/config/cluster/v3/cluster.proto#L937 +[CL-TS-comment]: https://github.com/envoyproxy/envoy/blob/9aca65c395f01020080166e4795455addde167fa/api/envoy/config/cluster/v3/cluster.proto#L932 +[CL-TS-matches]: https://github.com/envoyproxy/envoy/blob/9aca65c395f01020080166e4795455addde167fa/api/envoy/config/cluster/v3/cluster.proto#L680 +[CTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L37 #### LDS for Server Side Security -Server-side xDS processing is described in [A36: xDS-Enabled Servers](A36-xds-for-servers.md). -An LDS may have one or more [`filter_chains`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener.proto#L120) -and one of those `filter_chain`s is matched against an incoming connection in order to get and apply +Server-side xDS processing is described in [A36: xDS-Enabled Servers][A36]. +An LDS may have one or more [`filter_chains`][filter-chains] and one of those +`filter_chain`s is matched against an incoming connection in order to get and apply the security (and other) configuration for that connection as described in the -[`FilterChainMatch`](A36-xds-for-servers.md#filterchainmatch). The -[`transport_socket`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener_components.proto#L246) +[`FilterChainMatch`][filter-chain-match]. The [`transport_socket`][transport-socket] of the matched (selected) `filter_chain` is used to extract the -[`DownstreamTlsContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L57) -as described -[here](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener_components.proto#L246). +[`DownstreamTlsContext`][DTC] as described [here][transport-socket-comment]. The `DownstreamTlsContext` thus obtained is used for the incoming connection. -[`common_tls_context`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L84) -in the `DownstreamTlsContext` contains the required security configuration. The -[`require_client_certificate`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L88) field -determines whether the client certificate is required (mTLS mode if `true`, TLS if `false`). -All the other fields are ignored. See below for -[`CommonTlsContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L129) +[`common_tls_context`][CTC1] in the `DownstreamTlsContext` contains the required +security configuration. The [`require_client_certificate`][RCC] field determines +whether the client certificate is required (mTLS mode if `true`, TLS if `false`). +All the other fields are ignored. See below for [`CommonTlsContext`][CTC-type] processing. +[A36]: A36-xds-for-servers.md +[filter-chains]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#120 +[filter-chain-match]: A36-xds-for-servers.md#filterchainmatch +[transport-socket]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener_components.proto#L246 +[DTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L57 +[transport-socket-comment]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener_components.proto#L241 +[CTC1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#84 +[RCC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#88 +[CTC-type]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L129 #### CommonTlsContext Processing @@ -174,35 +176,36 @@ processing. certificate and key configuration information needed on the client and server side respectively. The configuration tells gRPC how to obtain certificates and the keys for the TLS handshake. Although there are various ways to obtain certificates as per this proto (which are supported by Envoy), gRPC supports only one of them and that is defined by the -[`CertificateProviderInstance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L154) -proto which is based on the notion of CertificateProvider plugin framework (described later). -The field `instance_name` defines a CertificateProvider "instance" that gRPC looks up in the -bootstrap file (described later) to obtain the CertificateProvider configuration. This -configuration along with the CertificateProvider plugin framework enables gRPC to acquire -the certificates necessary for the TLS handshake. - -The field [`tls_certificate_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L234) -is used for the local certificate and the private key. And either -[`validation_context_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L259) -or [`validation_context_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L200) -inside [`combined_validation_context`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251) +[`CertificateProviderInstance`][CPI] proto which is based on the notion of CertificateProvider plugin framework +(described later). The field `instance_name` defines a CertificateProvider "instance" that gRPC looks up in the +bootstrap file (described later) to obtain the CertificateProvider configuration. This configuration along with +the CertificateProvider plugin framework enables gRPC to acquire the certificates necessary for the TLS handshake. + +The field [`tls_certificate_certificate_provider_instance`][TCCPI] is used for the local certificate and the private +key. And either [`validation_context_certificate_provider_instance`][VCCPI] or +[`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] is used for the root certificate-chain for validating peer certificates. For mTLS both the local certificate and root certificate are needed at both client and server. For TLS the server needs only the local certificate -(the [`tls_certificate_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L234)) -and the client needs only the root certificate -(the [`validation_context_certificate_provider_instance`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L200)). +(the [`tls_certificate_certificate_provider_instance`][TCCPI]) and the client needs only the root certificate +(the [`validation_context_certificate_provider_instance`][VCCPI1]). gRPC silently ignores the other fields in `CommonTlsContext` pertaining to other ways of fetching TLS certificates and keys. Also the processing and parsing of `CommonTlsContext` for any particular CDS or LDS response does not take into account whether the Xds credentials are in effect for the respective channel or server. +[CPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#154 +[TCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#234 +[VCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#259 +[VCCPI1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#200 ### Use of SPIFFE IDs in Certificates -To facilitate service mesh secure communication, we support [SPIFFE](https://github.com/spiffe/spiffe) based -certificates and peer certificate verification following the [SPIFFE](https://github.com/spiffe/spiffe) -specification and the [match_subject_alt_names](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#envoy-v3-api-field-extensions-transport-sockets-tls-v3-certificatevalidationcontext-match-subject-alt-names) field in xDS. +To facilitate service mesh secure communication, we support [SPIFFE][] based certificates and peer certificate +verification following the [SPIFFE][] specification and the [match_subject_alt_names][] field in xDS. + +[SPIFFE]: https://github.com/spiffe/spiffe +[match_subject_alt_names]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#envoy-v3-api-field-extensions-transport-sockets-tls-v3-certificatevalidationcontext-match-subject-alt-names ### Certificate Provider Plugin Framework @@ -229,7 +232,9 @@ later). * the xDS control plane only references the “plugin-instance-name”s: it uses one for the local certificates and another one for root certificates to validate the peer certificates (aka -[`CertificateValidationContext`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L236)). +[`CertificateValidationContext`][CVC-proto]). + +[CVC-proto]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L236 #### Main Elements of the Framework @@ -269,10 +274,9 @@ all its watchers. ### Bootstrap File Additions for Security -The [bootstrap file](A27-xds-global-load-balancing.md#xdsclient-and-bootstrap-file) with -[server side support](A36-xds-for-servers.md#xds-protocol) needs further changes as described -here. The following snippet shows the additions for the `file_watcher` plugin that is -already implemented in all gRPC languages. +The [bootstrap file][bootstrap-file] with [server side support][A36-xds-protocol] needs further +changes as described here. The following snippet shows the additions for the `file_watcher` plugin +that is already implemented in all gRPC languages. ``` { // "certificate_providers" contains configurations for all supported plugins @@ -303,6 +307,8 @@ fields are the file paths for the identity certificate, private key and the root certificate respectively. The last field is the certificate refresh interval i.e. the interval to be used by the plugin to monitor the file paths to refresh the certificates. +[bootstrap-file]: A27-xds-global-load-balancing.md#xdsclient-and-bootstrap-file + #### Use of Bootstrap File by the Certificate Provider Plugin Framework The xDS control plane specifies a certificate_provider_instance name as described above in @@ -327,31 +333,30 @@ out of scope of this document. #### Client Side Flow -The gRPC client xDS flow is described in -[gRPC Client Architecture](./A27-xds-global-load-balancing.md#grpc-client-architecture). +The gRPC client xDS flow is described in [gRPC Client Architecture][A27-client-arch]. The resolver returns a `Cluster` resource for a channel and the CDS for that cluster has the -[UpstreamTlsContext](https://github.com/envoyproxy/envoy/blob/35702fed462f63a0a237cfbfdf26184272207c11/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L27) -containing the security configuration to be applied to all the child policies of that cluster. -When a channel is using `XdsChannelCredentials`, gRPC processes the `UpstreamTlsContext` -as described [above](#cds-for-client-side-security). +[UpstreamTlsContext][UTC] containing the security configuration to be applied to all the +child policies of that cluster. When a channel is using `XdsChannelCredentials`, gRPC +processes the `UpstreamTlsContext` as described [above](#cds-for-client-side-security). At this stage the CDS policy uses the flow described above in -[Use of Bootstrap File by the Certificate Provider Plugin Framework](#use-of-bootstrap-file-by-the-certificate-provider-plugin-framework) +[Use of Bootstrap File by the Certificate Provider Plugin Framework][use-of-bootstrap] to fetch the requisite `CertificateProvider`s (one or two as the case may be). These `CertificateProvider`s, in one form or another, need to be made available to all the sub-channels of the cluster. How this is done is language dependent. For example, C-core uses the channel args to pass the individual `CertificateProvider`s whereas Java constructs a dynamic `SslContextProvider` that is directly usable by the sub-channel's TLS handshaker to build an `SslContext` for the impending handshake. +[A27-client-arch]: ./A27-xds-global-load-balancing.md#grpc-client-architecture +[UTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26 +[use-of-bootstrap]: #use-of-bootstrap-file-by-the-certificate-provider-plugin-framework + ##### Server Authorization aka Subject-Alt-Name Checks -If [match_subject_alt_names](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L373) -is populated in the -[combined_validation_context](https://github.com/envoyproxy/envoy/blob/main/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251) +If [match_subject_alt_names][] is populated in the [combined_validation_context][CVC] of the received `UpstreamTlsContext` then gRPC validates the SAN entries in the server certificate -by matching the `match_subject_alt_names` values using the -[StringMatcher](https://github.com/envoyproxy/envoy/blob/main/api/envoy/type/matcher/string.proto#L20) -semantics. This is called server authorization because this is how a client "authorizes" a server for +by matching the `match_subject_alt_names` values using the [StringMatcher][] semantics. +This is called server authorization because this is how a client "authorizes" a server for the connection. The implementation is language dependent. As an example, Java uses an implementation @@ -359,17 +364,18 @@ of `X509TrustManager` through the `SslContext` provided to the client sub-channe languages use similar hooks provided by the underlying TLS framework to implement server authorization. +[match_subject_alt_names]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L373 +[CVC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#251 +[StringMatcher]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L20 + #### Server Side Flow -The gRPC server xDS flow is described in -[gRPC Server ](./A27-xds-global-load-balancing.md#grpc-client-architecture). The server -configuration comes from the -[`Listener`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener.proto#L39) -resource which contains a list of -[`FilterChain`](https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener_components.proto#L193)s. -The `FilterChain` contains the `DownstreamTlsContext` that is applied to an incoming connection +The gRPC server xDS flow is described in [gRPC Server][A36-xds-protocol]. The server +configuration comes from the [`Listener`][Listener] resource which contains a list of +[`FilterChain`][Filter-chain]s. The `FilterChain` contains the `DownstreamTlsContext` +that is applied to an incoming connection after selecting the best-matching `FilterChain` as described in -[FilterChainMatch](A36-xds-for-servers.md#filterchainmatch). If the server is using `XdsServerCredentials`, +[FilterChainMatch][A36-filter-chain-match]. If the server is using `XdsServerCredentials`, gRPC processes the `DownstreamTlsContext` as described [above](#lds-for-server-side-security) and then uses the flow described above in [Use of Bootstrap File by the Certificate Provider Plugin Framework](#use-of-bootstrap-file-by-the-certificate-provider-plugin-framework) @@ -379,6 +385,11 @@ client side, this part of the flow is language dependent. For example, Java cons `SslContextProvider` that is directly usable by the connection's TLS handshaker to build an `SslContext` for the impending handshake. +[A36-xds-protocol]: A36-xds-for-servers.md#xds-protocol +[Listener]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#L39 +[Filter-chain]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener_components.proto#L193 +[A36-filter-chain-match]: A36-xds-for-servers.md#filterchainmatch + ## Rationale gRPC has been steadily adding support for various xDS features including load balancing and From 1103b7f2973f06f2fdb55aaa67ecad7b6ef44804 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 25 Jun 2021 16:14:52 -0700 Subject: [PATCH 03/26] Add C++ section for XdsServerCredentials --- A29-xds-tls-security.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 82cde903b..678a8038f 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -83,7 +83,12 @@ Use of XdsChannelCredentials: Use of XdsServerCredentials: ```C++ - // TODO: yashykt to add + grpc::experimental::XdsServerBuilder builder; + builder.RegisterService(&service); + builder.AddListeningPort(listening_address, + grpc::experimental::XdsServerCredentials( + grpc::InsecureServerCredentials())); + builder.BuildAndStart()->Wait(); ``` #### Java From 19b175a038e8b629fc80c9ac2313d2e201cdba54 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Mon, 28 Jun 2021 10:14:47 -0700 Subject: [PATCH 04/26] typo - added the missing L in line number anchors --- A29-xds-tls-security.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 82cde903b..3ea598e42 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -161,13 +161,13 @@ All the other fields are ignored. See below for [`CommonTlsContext`][CTC-type] processing. [A36]: A36-xds-for-servers.md -[filter-chains]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#120 +[filter-chains]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#L120 [filter-chain-match]: A36-xds-for-servers.md#filterchainmatch [transport-socket]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener_components.proto#L246 [DTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L57 [transport-socket-comment]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener_components.proto#L241 -[CTC1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#84 -[RCC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#88 +[CTC1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L84 +[RCC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L88 [CTC-type]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L129 #### CommonTlsContext Processing @@ -194,10 +194,10 @@ TLS certificates and keys. Also the processing and parsing of `CommonTlsContext` CDS or LDS response does not take into account whether the Xds credentials are in effect for the respective channel or server. -[CPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#154 -[TCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#234 -[VCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#259 -[VCCPI1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#200 +[CPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L154 +[TCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L234 +[VCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L259 +[VCCPI1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L200 ### Use of SPIFFE IDs in Certificates @@ -365,7 +365,7 @@ languages use similar hooks provided by the underlying TLS framework to implemen authorization. [match_subject_alt_names]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L373 -[CVC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#251 +[CVC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251 [StringMatcher]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L20 #### Server Side Flow From 95f01ba67ef8f2487ecc0664f3613024d2d9ea29 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Tue, 29 Jun 2021 14:09:03 -0700 Subject: [PATCH 05/26] address review comments and add Go snippets --- A29-xds-tls-security.md | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 75b30352a..fc8e5c174 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -40,7 +40,7 @@ enable (or disable) the use of these configurations. * [A27: xDS-Based Global Load Balancing][A27] * [A36: xDS-Enabled Servers][A36] - * [Java: Channel and Server Credentials][L74] + * [L74: Java Channel and Server Credentials][L74] [A27]: A27-xds-global-load-balancing.md [L74]: L74-java-channel-creds.md @@ -49,21 +49,25 @@ enable (or disable) the use of these configurations. ### Programming API -For each language, the channel and server credentials have been extended to allow a gRPC -channel and server to use xDS provided security configurations. A Xds- Channel or Server credentials -also needs to be provided with a "fallback credentials". The fallback credentials -is used in the following cases: +We need a mechanism by which a programmer can "opt in" to allow the use of xDS provided security +configuration for a gRPC channel or server. This is achieved by supplying an XdsChannelCredentials +(to a channel) or an XdsServerCredentials (to a server). These two new credentials types are an extension +of the existing channel or server credentials types in each language. Each Xds*Credentials needs to +be provided with a "fallback credentials". The fallback credentials is used in the following cases: - when xDS is not in use such as when the `xds:` scheme is not used on the client side -- xDS is in use but the control plane does not provide security configuration. +- xDS is in use but the control plane does not provide security configuration. The gRPC behavior +in this case is different from Envoy's due to fallback credentials. Envoy will just +use plaintext (insecure) communication mode in this case. But with gRPC, the application +needs to use InsecureCredentials as the fallback credentials to get the same result. The fallback credentials is *not* used in case of error situations e.g. when there is an error in using the xDS provided security configuration. Note that a user is not required to use Xds- Channel or Server Credentials even if they are using an xDS managed channel or server. Not using Xds Channel or Server Credentials results -into not using xDS-provided TLS configuration. +in not using xDS-provided TLS configuration. On the client side, an XdsChannelCredentials is used and on the server side an XdsServerCredentials is used as described in the example snippets below. In these examples, @@ -115,13 +119,28 @@ Use of XdsServerCredentials: Use of XdsChannelCredentials: ```Go - // TODO: easwars to add + import ( + xdscreds "google.golang.org/grpc/credentials/xds" + ) + + if creds, err := xdscreds.NewClientCredentials(xdscreds.ClientOptions{FallbackCreds: insecure.NewCredentials()}); err != nil { + log.Fatalf("Failed to create xDS client credentials: %v", err) + } + conn, err := grpc.Dial(*target, grpc.WithTransportCredentials(creds)) ``` Use of XdsServerCredentials: ```Go - // TODO: easwars to add + import ( + xdscreds "google.golang.org/grpc/credentials/xds" + "google.golang.org/grpc/xds" + ) + + if creds, err := xdscreds.NewServerCredentials(xdscreds.ServerOptions{FallbackCreds: insecure.NewCredentials()}); err != nil { + log.Fatalf("Failed to create xDS server credentials: %v", err) + } + server := xds.NewGRPCServer(grpc.Creds(creds)) ``` ### xDS Protocol From ecd85ca6064cce97229b7b35011183e13e532b0b Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Tue, 29 Jun 2021 21:55:50 -0700 Subject: [PATCH 06/26] address more review comments --- A29-xds-tls-security.md | 110 +++++++++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 19 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index fc8e5c174..df566852d 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -62,7 +62,7 @@ in this case is different from Envoy's due to fallback credentials. Envoy will j use plaintext (insecure) communication mode in this case. But with gRPC, the application needs to use InsecureCredentials as the fallback credentials to get the same result. -The fallback credentials is *not* used in case of error situations e.g. when there is +The fallback credentials is *not* used in case of error situations e.g. whenever there is an error in using the xDS provided security configuration. Note that a user is not required to use Xds- Channel or Server Credentials even if they are @@ -159,30 +159,67 @@ How this is done is language dependent and is similar to how the implementations information down to child policies. [`common_tls_context`][CTC] in the `UpstreamTlsContext` contains the required security configuration. -All other fields are ignored. See below for [`CommonTlsContext`][CTC-type] processing. +See below for [`CommonTlsContext`][CTC-type] processing. + +A secure client at a minimum requires [`validation_context_certificate_provider_instance`][VCCPI1] +inside [`combined_validation_context`][CVC] to be able to validate the server certificate +in the TLS mode. If this field is not set, gRPC will NACK the CDS update. The client identity +certificate is configured via the [`tls_certificate_certificate_provider_instance`][TCCPI] +field which is optional. The client certificate is sent to the server if the server requests +or requires it in the TLS handshake. If the server requires the client certificate but is not +present then the TLS handshake fails. + +If any of the following fields are present, gRPC will NACK the CDS update: + +* [sni][SNI] +* [allow_renegotiation][ALLOW-RENEG] +* [max_session_keys][MAX-SESS-KEYS] [A27:CDS]: A27-xds-global-load-balancing.md#cds [CL-TS]: https://github.com/envoyproxy/envoy/blob/9aca65c395f01020080166e4795455addde167fa/api/envoy/config/cluster/v3/cluster.proto#L937 [CL-TS-comment]: https://github.com/envoyproxy/envoy/blob/9aca65c395f01020080166e4795455addde167fa/api/envoy/config/cluster/v3/cluster.proto#L932 [CL-TS-matches]: https://github.com/envoyproxy/envoy/blob/9aca65c395f01020080166e4795455addde167fa/api/envoy/config/cluster/v3/cluster.proto#L680 [CTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L37 +[SNI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L40 +[ALLOW-RENEG]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L47 +[MAX-SESS-KEYS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L53 #### LDS for Server Side Security Server-side xDS processing is described in [A36: xDS-Enabled Servers][A36]. -An LDS may have one or more [`filter_chains`][filter-chains] and one of those +A Listener resource may have one or more [`filter_chains`][filter-chains] and one of those `filter_chain`s is matched against an incoming connection in order to get and apply the security (and other) configuration for that connection as described in the [`FilterChainMatch`][filter-chain-match]. The [`transport_socket`][transport-socket] of the matched (selected) `filter_chain` is used to extract the [`DownstreamTlsContext`][DTC] as described [here][transport-socket-comment]. The `DownstreamTlsContext` thus obtained is used for the incoming connection. +If it is not present (such as when [`transport_socket`][transport-socket] is +not present or is not named `"envoy.transport_sockets.tls"`) then we use the +fallback credentials for the incoming connection. [`common_tls_context`][CTC1] in the `DownstreamTlsContext` contains the required -security configuration. The [`require_client_certificate`][RCC] field determines -whether the client certificate is required (mTLS mode if `true`, TLS if `false`). -All the other fields are ignored. See below for [`CommonTlsContext`][CTC-type] -processing. +security configuration. See below for [`CommonTlsContext`][CTC-type] processing. + +A secure server at a minimum requires an identity certificate which is provided +by [`tls_certificate_certificate_provider_instance`][TCCPI]. If that field is +empty, gRPC will NACK the update. If +[`validation_context_certificate_provider_instance`][VCCPI1] inside +[`combined_validation_context`][CVC] is provided then the server will request +the client certificate. When [`require_client_certificate`][RCC] is `true`, +gRPC requires the client certificate and will reject a connection without a valid +client certificate. When [`require_client_certificate`][RCC] is `true`, the +[`validation_context_certificate_provider_instance`][VCCPI1] value should be +present otherwise gRPC should NACK the LDS update. + +If any of the following fields are present, gRPC will NACK the LDS update: + +* [require_sni][REQ-SNI] +* [session_ticket_keys][SESSION-TICKET-KEYS] +* [session_ticket_keys_sds_secret_config][SESSION-TICKET-KEYS-SDS] +* [disable_stateless_session_resumption][DIS-STATELESS-SESS-RES] +* [session_timeout][SESSION-TIMEOUT] +* [ocsp_staple_policy][OCSP-STAPLE-POLICY] [A36]: A36-xds-for-servers.md [filter-chains]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#L120 @@ -193,6 +230,12 @@ processing. [CTC1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L84 [RCC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L88 [CTC-type]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L129 +[REQ-SNI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L92 +[SESSION-TICKET-KEYS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L96 +[SESSION-TICKET-KEYS-SDS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L99 +[DIS-STATELESS-SESS-RES]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L109 +[SESSION-TIMEOUT]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L116 +[OCSP-STAPLE-POLICY]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L124 #### CommonTlsContext Processing @@ -205,23 +248,52 @@ certificates as per this proto (which are supported by Envoy), gRPC supports onl bootstrap file (described later) to obtain the CertificateProvider configuration. This configuration along with the CertificateProvider plugin framework enables gRPC to acquire the certificates necessary for the TLS handshake. -The field [`tls_certificate_certificate_provider_instance`][TCCPI] is used for the local certificate and the private -key. And either [`validation_context_certificate_provider_instance`][VCCPI] or -[`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] -is used for the root certificate-chain for validating peer certificates. For mTLS both the local certificate -and root certificate are needed at both client and server. For TLS the server needs only the local certificate -(the [`tls_certificate_certificate_provider_instance`][TCCPI]) and the client needs only the root certificate -(the [`validation_context_certificate_provider_instance`][VCCPI1]). +The field [`tls_certificate_certificate_provider_instance`][TCCPI] is used for the identity certificate and the private +key. And [`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] +is used for the root certificate-chain for validating peer certificates. + +gRPC does not support the other certificate acquisition mechanisms specified by the following fields: + +* [tls_certificates][TLS-CERT] +* [tls_certificate_sds_secret_configs][CERT-SDS] +* [tls_certificate_certificate_provider][CERT-PROVIDER] +* [validation_context_sds_secret_config][VAL-SDS] +* [validation_context_certificate_provider][VAL-PROVIDER] + +When the supported fields of type [`CertificateProviderInstance`][CPI] are present gRPC ignores the respective +unsupported fields but if the unsupported fields are present by themselves gRPC will NACK the update. + +For example, in [`UpstreamTlsContext`][UTC] (on the client side), the identity certificate is not needed for the TLS mode, +which is indicated by [`tls_certificate_certificate_provider_instance`][TCCPI] being absent. However in this case +if any of the other unsupported identity certificate fields ([tls_certificates][TLS-CERT], +[tls_certificate_sds_secret_configs][CERT-SDS], [tls_certificate_certificate_provider][CERT-PROVIDER]) are +present then gRPC will NACK the update. But if [`tls_certificate_certificate_provider_instance`][TCCPI] is +present, then the unsupported fields are ignored. This allows a control plane to formulate a single +`CommonTlsContext` that works for both gRPC (which only supports [`CertificateProviderInstance`][CPI]) +and Envoy (which does not support [`CertificateProviderInstance`][CPI]) to achieve consistent +security configuration between gRPC and Envoy. + +The following fields are unsupported and if present will cause a NACK from gRPC: + +* [tls_params][TLS-PARAMS] +* [custom_handshaker][CUSTOM-HS] -gRPC silently ignores the other fields in `CommonTlsContext` pertaining to other ways of fetching -TLS certificates and keys. Also the processing and parsing of `CommonTlsContext` for any particular -CDS or LDS response does not take into account whether the Xds credentials are in effect for the -respective channel or server. +[alpn_protocols][ALPN-PROTOCOLS] on server side (inside [`DownstreamTlsContext`][DTC]) should +be absent. On the client side (inside [`UpstreamTlsContext`][UTC]) it is ignored if present. +The processing and parsing of `CommonTlsContext` inside any particular CDS or LDS response does +not take into account whether Xds credentials are in effect for the respective channel or server. [CPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L154 [TCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L234 -[VCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L259 [VCCPI1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L200 +[TLS-CERT]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L215 +[CERT-SDS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L225 +[CERT-PROVIDER]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L230 +[VAL-SDS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L242 +[VAL-PROVIDER]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L255 +[TLS-PARAMS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L207 +[CUSTOM-HS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L276 +[ALPN-PROTOCOLS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L272 ### Use of SPIFFE IDs in Certificates From cf2fff4707e1978cc180a4d01ead56ac1e7d8553 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Wed, 7 Jul 2021 08:23:31 -0700 Subject: [PATCH 07/26] address some more review comments --- A29-xds-tls-security.md | 71 ++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index df566852d..1c9d2c4eb 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -80,17 +80,17 @@ Use of XdsChannelCredentials: ```C++ std::shared_ptr credentials = - grpc::experimental::XdsCredentials(grpc::InsecureChannelCredentials()); + grpc::XdsCredentials(grpc::InsecureChannelCredentials()); std::shared_ptr channel = grpc::CreateChannel(target, credentials); ``` Use of XdsServerCredentials: ```C++ - grpc::experimental::XdsServerBuilder builder; + grpc::XdsServerBuilder builder; builder.RegisterService(&service); builder.AddListeningPort(listening_address, - grpc::experimental::XdsServerCredentials( + grpc::XdsServerCredentials( grpc::InsecureServerCredentials())); builder.BuildAndStart()->Wait(); ``` @@ -154,9 +154,9 @@ The CDS policy is the top level LB policy applied to all the connections under t [A27:CDS][] describes the flow. The field [`transport_socket`][CL-TS] is used to extract the [`UpstreamTlsContext`][UTC] as described [here][CL-TS-comment]. Note that we don't (currently) support [`transport_socket_matches`][CL-TS-matches]. -The `UpstreamTlsContext` thus obtained is passed down to all the child policies and connections. -How this is done is language dependent and is similar to how the implementations pass policy -information down to child policies. +The security configuration extracted from the `UpstreamTlsContext` thus obtained +is passed down to all the child policies and connections. How this is done is language dependent +and is similar to how the implementations pass policy information down to child policies. [`common_tls_context`][CTC] in the `UpstreamTlsContext` contains the required security configuration. See below for [`CommonTlsContext`][CTC-type] processing. @@ -193,7 +193,9 @@ the security (and other) configuration for that connection as described in the [`FilterChainMatch`][filter-chain-match]. The [`transport_socket`][transport-socket] of the matched (selected) `filter_chain` is used to extract the [`DownstreamTlsContext`][DTC] as described [here][transport-socket-comment]. -The `DownstreamTlsContext` thus obtained is used for the incoming connection. +If the `transport_socket` name is not `envoy.transport_sockets.tls` i.e. +something we don't recognize, gRPC will NACK the LDS update. Otherwise +the `DownstreamTlsContext` thus obtained is used for the incoming connection. If it is not present (such as when [`transport_socket`][transport-socket] is not present or is not named `"envoy.transport_sockets.tls"`) then we use the fallback credentials for the incoming connection. @@ -260,7 +262,7 @@ gRPC does not support the other certificate acquisition mechanisms specified by * [validation_context_sds_secret_config][VAL-SDS] * [validation_context_certificate_provider][VAL-PROVIDER] -When the supported fields of type [`CertificateProviderInstance`][CPI] are present gRPC ignores the respective +When fields of type [`CertificateProviderInstance`][CPI] are present gRPC ignores the respective unsupported fields but if the unsupported fields are present by themselves gRPC will NACK the update. For example, in [`UpstreamTlsContext`][UTC] (on the client side), the identity certificate is not needed for the TLS mode, @@ -334,22 +336,23 @@ certificates and another one for root certificates to validate the peer certific #### Main Elements of the Framework -**`CertificateProvider`** represents an actual plugin that fetches or "mints" the required certificates -and keys. One example of a (already implemented) plugin is a `FileWatcherCertificateProvider` which -monitors certain files in the file system and reads those files on updates to get the latest -certificates and keys and provide those to the consumers after converting them to the canonical -format e.g. `java.security.PrivateKey` and `java.security.cert.X509Certificate` in Java. -Another example is a plugin that periodically "mints" new certificates by creating -CSRs at regular intervals and getting those signed by a Certification Authority (CA) that is +**`CertificateProvider`** represents an actual plugin that fetches or "mints" the required +certificates and keys. **`FileWatcherCertificateProvider`** (described below) is an +implementation of the **`CertificateProvider`** that is part of this framework. Another example +of a **`CertificateProvider`** is a plugin that periodically "mints" new certificates by creating +CSRs at regular intervals and getting those signed by a Certification Authority (CA) which is configured into the plugin. -A client registers itself as a **`Watcher`** of the plugin to receive certificate updates. -The plugin supports multiple **`Watchers`** to be registered and uses a **`DistributorWatcher`** +A "consumer" registers itself as a **`Watcher`** of the plugin to receive certificate updates. +The plugin supports multiple **`Watcher`s** to be registered and uses a **`DistributorWatcher`** internally to propagate a single update to multiple **`Watchers`**. A plugin caches the latest certificate (and key) it has fetched (or minted) and delivers them to every newly registered +watcher. Note that it is possible for an implementation to use a fetch-style API instead of a +watch-style API. For example, in the Go implementation a consumer calls into the +**`CertificateProvider`** whenever it needs certificates and keys instead of registering a watcher. -The `CertificateProvider` plugin also has an associated factory or +The **`CertificateProvider`** plugin also has an associated factory or provider implementation (**`CertificateProviderFactory`**) to instantiate the plugin and this factory is identified by a unique name e.g. `"file_watcher"` which is also the identity of the plugin. The factory is responsible for instantiating the plugin after validating the received @@ -366,7 +369,12 @@ as a **`Watcher`**. If the plugin is not already present, the store uses the reg instantiate it. It then increments the reference-count and adds the new **`Watcher`** to the **`DistributorWatcher`** of the plugin. The plugin typically creates a new thread and a timer to periodically fetch or mint a new certificate and send the certificate (and the key) to -all its watchers. +all its watchers. + +**`FileWatcherCertificateProvider`** is an implementation of **`CertificateProvider`** which +monitors configured file-paths in the file system and reads those files on updates to get the latest +certificates and keys and provide those to the consumers after converting them to the canonical +format e.g. `java.security.PrivateKey` and `java.security.cert.X509Certificate` in Java. ### Bootstrap File Additions for Security @@ -375,7 +383,7 @@ changes as described here. The following snippet shows the additions for the `fi that is already implemented in all gRPC languages. ``` { - // "certificate_providers" contains configurations for all supported plugins + // "certificate_providers" lists the instances available for xDS to use. "certificate_providers": { "google_cloud_private_spiffe": { // certificate_provider_instance name "plugin_name": "file_watcher", // name of the plugin @@ -396,12 +404,8 @@ having exactly 2 fields: * `"plugin_name"` which is the name of the plugin (a string value), and * `"config"` which is the configuration for the plugin. The value of `"config"` is a JSON object -whose schema is defined by that plugin. - -In the above example, the config for the file_watcher plugin contains 4 fields: the first 3 -fields are the file paths for the identity certificate, private key and the root (or CA) -certificate respectively. The last field is the certificate refresh interval i.e. the interval -to be used by the plugin to monitor the file paths to refresh the certificates. +whose schema is defined by that plugin. For the file_watcher plugin the `"config"` consists +of the 3 file-paths to watch and the polling interval value. [bootstrap-file]: A27-xds-global-load-balancing.md#xdsclient-and-bootstrap-file @@ -493,12 +497,13 @@ advanced traffic management. xDS-based security was next in the roadmap and this addresses that. gRPC makes a proxyless service mesh (PSM) possible. A secure proxyless service mesh requires the security features described in this proposal. -The Certificate Provider Plugin Framework does not depend on an agent (SDS server). The -SDS server/agent based solution compromised security (by sharing the private key with the -agent). The combination of Envoy sidecar and the SDS server was also somewhat tied to the -Kubernetes architecture where Envoy runs in a sidecar container and the SDS server runs -as a Node agent in the cluster. The Certificate Provider Plugin Framework has eliminated that -dependency. The framework has also made the certificate provider functionality extensible +The Certificate Provider Plugin Framework provides a generic alternative to the SDS +server/agent based solution and eliminates the dependency on the SDS protocol. An SDS +protocol based client can still be added just as another plugin implementation in the +framework. The plugin framework allows different environments to have different +dependencies because the xDS client environment is abstracted out via the plugin +framework and the control plane can be agnostic to the specific client environment. +The framework has also made the certificate provider functionality extensible and pluggable which enables support for new certificate providers without requiring changes to the xDS protocol or the control plane. These advantages plus the extensions made to the xDS protocol are providing an impetus to the Envoy community so that Envoy @@ -513,6 +518,6 @@ proxyless and interop or co-existence with Envoy. Java had an early prototype implementation of xDS-based security that used SDS similar to Envoy. It was then modified and refined to match this spec. Other languages followed soon after to complete -the implementation. The implementations (in Java, C++ and Go) are currently "hidden" behing the +the implementation. The implementations (in Java, C++ and Go) are currently "hidden" behind the environment variable `GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT` which will be removed once this proposal is official. From c80082f4147b0fccb26e13af4f1644fb05eb88e7 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 8 Jul 2021 09:14:10 -0700 Subject: [PATCH 08/26] address next set of comments --- A29-xds-tls-security.md | 294 +++++++++++++++++----------------------- 1 file changed, 127 insertions(+), 167 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 1c9d2c4eb..8f91bbbb5 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -157,9 +157,13 @@ Note that we don't (currently) support [`transport_socket_matches`][CL-TS-matche The security configuration extracted from the `UpstreamTlsContext` thus obtained is passed down to all the child policies and connections. How this is done is language dependent and is similar to how the implementations pass policy information down to child policies. +For example, C-core uses the channel args to pass security configuration down, whereas +Java constructs a dynamic `SslContextProvider` that is directly usable by a sub-channel's +TLS handshaker to build an SslContext for the upcoming TLS handshake. -[`common_tls_context`][CTC] in the `UpstreamTlsContext` contains the required security configuration. -See below for [`CommonTlsContext`][CTC-type] processing. +Only when a channel is using `XdsChannelCredentials`, gRPC uses the security configuration +in `UpstreamTlsContext`. [`common_tls_context`][CTC] in the `UpstreamTlsContext` contains +the required security configuration. See below for [`CommonTlsContext`][CTC-type] processing. A secure client at a minimum requires [`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] to be able to validate the server certificate @@ -184,21 +188,48 @@ If any of the following fields are present, gRPC will NACK the CDS update: [ALLOW-RENEG]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L47 [MAX-SESS-KEYS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L53 +##### Server Authorization aka Subject-Alt-Name Checks + +"Server authorization" is performed by the client in which the client authorizes +a server for the connection as described below. This check is in lieu of the +canonical [hostname check in Web PKI][RFC6125-6]. + +If [match_subject_alt_names][] is populated in the [combined_validation_context][CVC] +of the received `UpstreamTlsContext` then gRPC validates the SAN entries in the server +certificate by matching the `match_subject_alt_names` values using the [StringMatcher][] +semantics. If the match does not succeed the connection attempt fails indicating a +"certificate check failure". + +Individual Implementations will use hooks provided by the underlying TLS framework to +implement server authorization. As an example, Java may use a custom `X509TrustManager` +implementation through the `SslContext` provided to the client sub-channel. + +[match_subject_alt_names]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L373 +[CVC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251 +[StringMatcher]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L20 +[RFC6125-6]: https://datatracker.ietf.org/doc/html/rfc6125#section-6 + #### LDS for Server Side Security Server-side xDS processing is described in [A36: xDS-Enabled Servers][A36]. -A Listener resource may have one or more [`filter_chains`][filter-chains] and one of those -`filter_chain`s is matched against an incoming connection in order to get and apply +A Listener resource has zero or more [`filter_chains`][filter-chains] and one of those +`filter_chain`s is matched against an incoming connection (or +[`default_filter_chain`][default-filter-chain] if none matches) in order to get and apply the security (and other) configuration for that connection as described in the [`FilterChainMatch`][filter-chain-match]. The [`transport_socket`][transport-socket] of the matched (selected) `filter_chain` is used to extract the [`DownstreamTlsContext`][DTC] as described [here][transport-socket-comment]. If the `transport_socket` name is not `envoy.transport_sockets.tls` i.e. something we don't recognize, gRPC will NACK the LDS update. Otherwise -the `DownstreamTlsContext` thus obtained is used for the incoming connection. -If it is not present (such as when [`transport_socket`][transport-socket] is -not present or is not named `"envoy.transport_sockets.tls"`) then we use the -fallback credentials for the incoming connection. +the `DownstreamTlsContext` thus obtained is used for the incoming connection +if the server is using `XdsServerCredentials`. How the security configuration +in `DownstreamTlsContext` is made available to the incoming connection is language +dependent. For example, Java constructs a dynamic `SslContextProvider` that is +directly usable by the connection's TLS handshaker to build an `SslContext` for +the upcoming TLS handshake. If there is no `DownstreamTlsContext` (such as when +[`transport_socket`][transport-socket] is not present or is not named +`"envoy.transport_sockets.tls"`) then gRPC uses the fallback credentials +for the incoming connection. [`common_tls_context`][CTC1] in the `DownstreamTlsContext` contains the required security configuration. See below for [`CommonTlsContext`][CTC-type] processing. @@ -225,6 +256,7 @@ If any of the following fields are present, gRPC will NACK the LDS update: [A36]: A36-xds-for-servers.md [filter-chains]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#L120 +[default-filter-chain]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#L131 [filter-chain-match]: A36-xds-for-servers.md#filterchainmatch [transport-socket]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener_components.proto#L246 [DTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L57 @@ -296,6 +328,7 @@ not take into account whether Xds credentials are in effect for the respective c [TLS-PARAMS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L207 [CUSTOM-HS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L276 [ALPN-PROTOCOLS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L272 +[UTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26 ### Use of SPIFFE IDs in Certificates @@ -307,87 +340,70 @@ verification following the [SPIFFE][] specification and the [match_subject_alt_n ### Certificate Provider Plugin Framework -The pluggable Certificate Provider framework in gRPC underlies the use of `CertificateProviderInstance` -configuration. The framework supports "Certificate Providers" as pluggable and custom components (plugins) -used for dynamically fetching certificates used during the TLS handshake of gRPC channel and server connections. - -This document discusses just enough of the framework to explain the use-case. Users who want to -implement new plugins will need to understand the detailed design of the framework in the -respective language. - -Envoy was the original and only consumer of the xDS protocol and its security features were tied to -Envoy's security capabilities such as fetching certificates from the file-system or -using a separate SDS protocol to fetch certificates from an agent (that's not defined in the xDS -architecture). Instead of emulating Envoy's functionality and limitations in this area, we decided to -have a generic Certificate Provider plugin architecture in gRPC with the following characteristics: - -* the xDS control plane is not aware of the plugin specifics including its name, instantiation -mechanism or configuration requirements. - -* all of these are abstracted out into a single “plugin-instance-name” which is resolved into an -actual Certificate provider instance using the local bootstrap file and the framework (as explained -later). +xDS supports many different configurations for endpoints to obtain certificates but gRPC supports only +`CertificateProviderInstance`. Through this object the control plane tells the xDS client the name of +a certificate and the "instance" name of a provider to use to obtain a certificate. This provider +instance name is translated into a provider implementation and a configuration for that implementation +using the client's own configuration instead of being sent by the control plane. This enables flexibility +in heterogeneous deployments where different clients can use different implementations for the same +provider instance name. For example, an on-prem client may get its certificate using a local certificate +provider whereas a client running in cloud may use a cloud-vendor provided implementation to obtain +the certificate. + +gRPC provides a `CertificateProvider` plugin API that can support multiple implementations. The plugin API +is not currently public, so applications cannot currently add their own provider implementations although +we might make this API public in the future. However gRPC currently includes a `file_watcher` provider +implementation - descibed [below][FILE-WATCHER-LINK] - which reads certificates from the local file system. + +[FILE-WATCHER-LINK]: #file_watcher-certificate-provider + +Certificate provider plugin instances are configured via the xDS bootstrap file. There is a new +top-level field called `"certificate_providers"` whose value is a map (a JSON object). The key +in this map is the certificate_provider_instance name and the value is a JSON object +having exactly 2 fields: -* the xDS control plane only references the “plugin-instance-name”s: it uses one for the local -certificates and another one for root certificates to validate the peer certificates (aka -[`CertificateValidationContext`][CVC-proto]). +* `"plugin_name"` which is the name of the plugin implementation (a string value), and +* `"config"` which is the configuration for the plugin. The value of `"config"` is a JSON object +whose schema is defined by that plugin. -[CVC-proto]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L236 +The structure in the bootstrap file is as follows: -#### Main Elements of the Framework +``` +"certificate_providers": { + "instance_name": { + "plugin_name": "implementation_name", + "config": { + // ...config for implementation_name plugin... + } + } +} +``` -**`CertificateProvider`** represents an actual plugin that fetches or "mints" the required -certificates and keys. **`FileWatcherCertificateProvider`** (described below) is an -implementation of the **`CertificateProvider`** that is part of this framework. Another example -of a **`CertificateProvider`** is a plugin that periodically "mints" new certificates by creating -CSRs at regular intervals and getting those signed by a Certification Authority (CA) which is -configured into the plugin. +This defines a plugin instance for the instance name `instance_name` which consists of a +plugin implementation called `implementation_name` with the corresponding configuration +defined as the value for the key `config`. When the xDS server tells the client to obtain +a certificate from `instance_name`, the client will use this plugin instance. -A "consumer" registers itself as a **`Watcher`** of the plugin to receive certificate updates. -The plugin supports multiple **`Watcher`s** to be registered and uses a **`DistributorWatcher`** -internally to propagate a single update to multiple **`Watchers`**. A plugin caches the latest -certificate (and key) it has fetched (or minted) and delivers them to every newly registered -watcher. Note that it is possible for an implementation to use a fetch-style API instead of a -watch-style API. For example, in the Go implementation a consumer calls into the -**`CertificateProvider`** whenever it needs certificates and keys instead of registering a -watcher. +#### `file_watcher` Certificate Provider -The **`CertificateProvider`** plugin also has an associated factory or -provider implementation (**`CertificateProviderFactory`**) to instantiate the plugin and this -factory is identified by a unique name e.g. `"file_watcher"` which is also the identity of the -plugin. The factory is responsible for instantiating the plugin after validating the received -configuration. - -**`CertificateProviderRegistry`** is a registry of all registered plugins supported by the gRPC library. -A **`CertificateProviderFactory`** registers itself in the registry. - -**`CertificateProviderStore`** is a store or global map of all instantiated plugins. In this map -the key is the plugin-name plus its config and the value is a reference counted instantiated plugin. -Reference counting ensures that a plugin with a given name and configuration combination is only -instantiated once. A client of the framework looks up a plugin by name and config and adds itself -as a **`Watcher`**. If the plugin is not already present, the store uses the registry to -instantiate it. It then increments the reference-count and adds the new **`Watcher`** to the -**`DistributorWatcher`** of the plugin. The plugin typically creates a new thread and a -timer to periodically fetch or mint a new certificate and send the certificate (and the key) to -all its watchers. - -**`FileWatcherCertificateProvider`** is an implementation of **`CertificateProvider`** which -monitors configured file-paths in the file system and reads those files on updates to get the latest -certificates and keys and provide those to the consumers after converting them to the canonical -format e.g. `java.security.PrivateKey` and `java.security.cert.X509Certificate` in Java. +As mentioned before, we currently only have one plugin implementation called `file_watcher`. +The configuration for this plugin has the following fields: +- `certificate_file`: The path to the file containing the identity certificate. The file should contain +a PEM-formatted X.509 conforming certificate. +- `private_key_file`: The path to the file containing the private key. The file should contain a +PEM-formatted PKCS encoded private key. +- `ca_certificate_file`: The path to the file containing the root certificate. The file should contain +a PEM-formatted X.509 conforming certificate chain. +- `refresh_interval`: Specifies how frequently the plugin should read the files. The value must be +in the [JSON format described for a `Duration`][DURATION-JSON] protobuf message. -### Bootstrap File Additions for Security +For example, the bootstrap file might contain the following: -The [bootstrap file][bootstrap-file] with [server side support][A36-xds-protocol] needs further -changes as described here. The following snippet shows the additions for the `file_watcher` plugin -that is already implemented in all gRPC languages. ``` -{ - // "certificate_providers" lists the instances available for xDS to use. "certificate_providers": { "google_cloud_private_spiffe": { // certificate_provider_instance name - "plugin_name": "file_watcher", // name of the plugin - "config": { // config to be supplied to the plugin + "plugin_name": "file_watcher", // name of the plugin instance + "config": { // config to be supplied to the plugin instance "certificate_file": "/var/run/gke-spiffe/certs/certificates.pem", "private_key_file": "/var/run/gke-spiffe/certs/private_key.pem", "ca_certificate_file": "/var/run/gke-spiffe/certs/ca_certificates.pem", @@ -395,100 +411,44 @@ that is already implemented in all gRPC languages. } } } -} ``` -`"certificate_providers"` is a new top level field whose value is a map (a JSON object). -The key in this map is the certificate_provider_instance name and the value is a JSON object -having exactly 2 fields: +With this configuration, when the xDS server tells the client to get a certificate from +plugin instance "google_cloud_private_spiffe", the client will load the certificate data +from the specified files. -* `"plugin_name"` which is the name of the plugin (a string value), and -* `"config"` which is the configuration for the plugin. The value of `"config"` is a JSON object -whose schema is defined by that plugin. For the file_watcher plugin the `"config"` consists -of the 3 file-paths to watch and the polling interval value. - -[bootstrap-file]: A27-xds-global-load-balancing.md#xdsclient-and-bootstrap-file - -#### Use of Bootstrap File by the Certificate Provider Plugin Framework - -The xDS control plane specifies a certificate_provider_instance name as described above in -[CommonTlsContext Processing](#commontlscontext-processing). For this example, let's assume -it uses `"google_cloud_private_spiffe"` as the `"instance_name"` in -`tls_certificate_certificate_provider_instance`. gRPC looks up -`"google_cloud_private_spiffe"` in the `"certificate_providers"` map loaded from the -bootstrap file and use the JSON object value to extract the plugin name (value of -`"plugin_name"` as a string) and configuration (value of `"config"` as a JSON object). -It passes on these values to the `CertificateProviderStore` to retrieve -(after instantiating if necessary) the associated `CertificateProvider` plugin. -The caller of the framework registers a watcher with the plugin to receive -certificate updates as described below. - -### Implementing Security in the xDS Flow - -Let's see how gRPC enables security in xDS managed clients and servers by putting it all -together. Note that gRPC uses the existing low level TLS handshaker code/libraries -(aka security connector or handshaker) after making the certificates and keys available -to that code. The TLS handshaker functionality (which is language dependent) is -out of scope of this document. - -#### Client Side Flow - -The gRPC client xDS flow is described in [gRPC Client Architecture][A27-client-arch]. -The resolver returns a `Cluster` resource for a channel and the CDS for that cluster has the -[UpstreamTlsContext][UTC] containing the security configuration to be applied to all the -child policies of that cluster. When a channel is using `XdsChannelCredentials`, gRPC -processes the `UpstreamTlsContext` as described [above](#cds-for-client-side-security). - -At this stage the CDS policy uses the flow described above in -[Use of Bootstrap File by the Certificate Provider Plugin Framework][use-of-bootstrap] -to fetch the requisite `CertificateProvider`s (one or two as the case may be). These `CertificateProvider`s, -in one form or another, need to be made available to all the sub-channels of the cluster. How this is -done is language dependent. For example, C-core uses the channel args to pass the individual -`CertificateProvider`s whereas Java constructs a dynamic `SslContextProvider` that is directly -usable by the sub-channel's TLS handshaker to build an `SslContext` for the impending handshake. - -[A27-client-arch]: ./A27-xds-global-load-balancing.md#grpc-client-architecture -[UTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26 -[use-of-bootstrap]: #use-of-bootstrap-file-by-the-certificate-provider-plugin-framework +[DURATION-JSON]: https://developers.google.com/protocol-buffers/docs/proto3#json. -##### Server Authorization aka Subject-Alt-Name Checks +## Implementation Details -If [match_subject_alt_names][] is populated in the [combined_validation_context][CVC] -of the received `UpstreamTlsContext` then gRPC validates the SAN entries in the server certificate -by matching the `match_subject_alt_names` values using the [StringMatcher][] semantics. -This is called server authorization because this is how a client "authorizes" a server for -the connection. - -The implementation is language dependent. As an example, Java uses an implementation -of `X509TrustManager` through the `SslContext` provided to the client sub-channel. The other -languages use similar hooks provided by the underlying TLS framework to implement server -authorization. +High level implementation details common to all the implementing gRPC languages +are described here. -[match_subject_alt_names]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L373 -[CVC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251 -[StringMatcher]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L20 +A **`CertificateProvider`** object represents a plugin that provides the required +certificates and keys to the gRPC application. A component registers itself as a **`Watcher`** +of the plugin to receive certificate updates. The plugin supports multiple +**`Watcher`s** and uses a **`DistributorWatcher`** internally to propagate a +single update to multiple **`Watchers`**. The plugin caches the last +certificate (and key) and delivers them to every newly registered +watcher. Note that it is possible for an implementation to use a fetch-style API instead of a +watch-style API. For example, in the Go implementation a consumer calls into the +**`CertificateProvider`** whenever it needs certificates and keys instead of registering a +watcher. -#### Server Side Flow - -The gRPC server xDS flow is described in [gRPC Server][A36-xds-protocol]. The server -configuration comes from the [`Listener`][Listener] resource which contains a list of -[`FilterChain`][Filter-chain]s. The `FilterChain` contains the `DownstreamTlsContext` -that is applied to an incoming connection -after selecting the best-matching `FilterChain` as described in -[FilterChainMatch][A36-filter-chain-match]. If the server is using `XdsServerCredentials`, -gRPC processes the `DownstreamTlsContext` as described [above](#lds-for-server-side-security) and then -uses the flow described above in -[Use of Bootstrap File by the Certificate Provider Plugin Framework](#use-of-bootstrap-file-by-the-certificate-provider-plugin-framework) -to fetch the requisite `CertificateProvider`s (one or two as the case may be). These `CertificateProvider`s, -in one form or another, need to be made available to the incoming connection. Similar to the -client side, this part of the flow is language dependent. For example, Java constructs a dynamic -`SslContextProvider` that is directly usable by the connection's TLS handshaker to build an -`SslContext` for the impending handshake. - -[A36-xds-protocol]: A36-xds-for-servers.md#xds-protocol -[Listener]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#L39 -[Filter-chain]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener_components.proto#L193 -[A36-filter-chain-match]: A36-xds-for-servers.md#filterchainmatch +The **`CertificateProvider`** plugin also has an associated factory +(**`CertificateProviderFactory`**) that is used to instantiate the plugin. The +factory is identified by a unique name e.g. `"file_watcher"` that is also the identity of the +plugin. The factory is used to instantiate the plugin after validating the received +configuration. The framework uses deduping and reference counting mechanism to +ensure that a plugin of a given kind and configuration is instantiated only once. + +A plugin typically creates a new thread and a timer to periodically query and +send a certificate (and the key) to all its watchers. **`FileWatcherCertificateProvider`** +(aka `file_watcher` described [above][FILE-WATCHER-LINK]) is an implementation of +the **`CertificateProvider`**. This plugin monitors configured file-paths in the file +system and reads those files on updates to get the latest certificates and keys and +provide those to the watchers after converting them to the canonical +format e.g. `java.security.PrivateKey` and `java.security.cert.X509Certificate` in Java. ## Rationale @@ -514,10 +474,10 @@ In any case the addition of xDS based security has brought gRPC xDS support clos Envoy in terms of capabilities. This enables various use-cases such as migration to proxyless and interop or co-existence with Envoy. -## Implementation +## Implementation Status Java had an early prototype implementation of xDS-based security that used SDS similar to Envoy. It was then modified and refined to match this spec. Other languages followed soon after to complete the implementation. The implementations (in Java, C++ and Go) are currently "hidden" behind the environment variable `GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT` which will be removed -once this proposal is official. +once this proposal is approved. From 929e4faf49c2951c63528bb46acb595b70dd0f56 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Fri, 9 Jul 2021 10:20:19 -0700 Subject: [PATCH 09/26] minor typos and fixes --- A29-xds-tls-security.md | 58 ++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 8f91bbbb5..48f61001d 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -50,9 +50,9 @@ enable (or disable) the use of these configurations. ### Programming API We need a mechanism by which a programmer can "opt in" to allow the use of xDS provided security -configuration for a gRPC channel or server. This is achieved by supplying an XdsChannelCredentials -(to a channel) or an XdsServerCredentials (to a server). These two new credentials types are an extension -of the existing channel or server credentials types in each language. Each Xds*Credentials needs to +configuration for a gRPC channel or server. This is achieved by supplying an `XdsChannelCredentials` +(to a channel) or an `XdsServerCredentials` (to a server). These two new credentials types are an extension +of the existing channel or server credentials types in each language. Each `Xds*Credentials` needs to be provided with a "fallback credentials". The fallback credentials is used in the following cases: - when xDS is not in use such as when the `xds:` scheme is not used on the client side @@ -62,17 +62,16 @@ in this case is different from Envoy's due to fallback credentials. Envoy will j use plaintext (insecure) communication mode in this case. But with gRPC, the application needs to use InsecureCredentials as the fallback credentials to get the same result. -The fallback credentials is *not* used in case of error situations e.g. whenever there is -an error in using the xDS provided security configuration. +Note that the fallback credentials is *not* used in case of errors. For example, if there is +an error encountered while using the xDS provided security configuration a connection will be +terminated rather than using the fallback credentials. -Note that a user is not required to use Xds- Channel or Server Credentials even if they are -using an xDS managed channel or server. Not using Xds Channel or Server Credentials results -in not using xDS-provided TLS configuration. - -On the client side, an XdsChannelCredentials is used and on the server side an -XdsServerCredentials is used as described in the example snippets below. In these examples, -a plaintext or insecure credentials is used as the fallback credentials. +A user is not required to use Xds- Channel or Server Credentials even if they are +using an xDS managed channel or server. Not using Xds- Channel or Server Credentials results +in not using the xDS provided TLS configuration. +The example snippets below show the use of `XdsChannelCredentials` and `XdsServerCredentials`. +In these examples a plaintext or insecure credentials is used as the fallback credentials. #### C++ @@ -157,9 +156,9 @@ Note that we don't (currently) support [`transport_socket_matches`][CL-TS-matche The security configuration extracted from the `UpstreamTlsContext` thus obtained is passed down to all the child policies and connections. How this is done is language dependent and is similar to how the implementations pass policy information down to child policies. -For example, C-core uses the channel args to pass security configuration down, whereas +For example, C-core uses channel args to pass security configuration down, whereas Java constructs a dynamic `SslContextProvider` that is directly usable by a sub-channel's -TLS handshaker to build an SslContext for the upcoming TLS handshake. +TLS handshaker to build an `SslContext` for the pending TLS handshake. Only when a channel is using `XdsChannelCredentials`, gRPC uses the security configuration in `UpstreamTlsContext`. [`common_tls_context`][CTC] in the `UpstreamTlsContext` contains @@ -190,7 +189,7 @@ If any of the following fields are present, gRPC will NACK the CDS update: ##### Server Authorization aka Subject-Alt-Name Checks -"Server authorization" is performed by the client in which the client authorizes +"Server authorization" is performed by the client where the client authorizes a server for the connection as described below. This check is in lieu of the canonical [hostname check in Web PKI][RFC6125-6]. @@ -201,7 +200,7 @@ semantics. If the match does not succeed the connection attempt fails indicating "certificate check failure". Individual Implementations will use hooks provided by the underlying TLS framework to -implement server authorization. As an example, Java may use a custom `X509TrustManager` +implement server authorization. As an example, Java uses a custom `X509TrustManager` implementation through the `SslContext` provided to the client sub-channel. [match_subject_alt_names]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L373 @@ -213,10 +212,10 @@ implementation through the `SslContext` provided to the client sub-channel. Server-side xDS processing is described in [A36: xDS-Enabled Servers][A36]. A Listener resource has zero or more [`filter_chains`][filter-chains] and one of those -`filter_chain`s is matched against an incoming connection (or -[`default_filter_chain`][default-filter-chain] if none matches) in order to get and apply +`filter_chain`s is matched against an incoming connection (or the +[`default_filter_chain`][default-filter-chain] if there is no match) in order to get and apply the security (and other) configuration for that connection as described in the -[`FilterChainMatch`][filter-chain-match]. The [`transport_socket`][transport-socket] +[`FilterChainMatch`][filter-chain-match] section. The [`transport_socket`][transport-socket] of the matched (selected) `filter_chain` is used to extract the [`DownstreamTlsContext`][DTC] as described [here][transport-socket-comment]. If the `transport_socket` name is not `envoy.transport_sockets.tls` i.e. @@ -243,7 +242,7 @@ the client certificate. When [`require_client_certificate`][RCC] is `true`, gRPC requires the client certificate and will reject a connection without a valid client certificate. When [`require_client_certificate`][RCC] is `true`, the [`validation_context_certificate_provider_instance`][VCCPI1] value should be -present otherwise gRPC should NACK the LDS update. +present otherwise gRPC will NACK the LDS update. If any of the following fields are present, gRPC will NACK the LDS update: @@ -414,7 +413,7 @@ For example, the bootstrap file might contain the following: ``` With this configuration, when the xDS server tells the client to get a certificate from -plugin instance "google_cloud_private_spiffe", the client will load the certificate data +plugin instance `"google_cloud_private_spiffe"`, the client will load the certificate data from the specified files. [DURATION-JSON]: https://developers.google.com/protocol-buffers/docs/proto3#json. @@ -439,23 +438,24 @@ The **`CertificateProvider`** plugin also has an associated factory (**`CertificateProviderFactory`**) that is used to instantiate the plugin. The factory is identified by a unique name e.g. `"file_watcher"` that is also the identity of the plugin. The factory is used to instantiate the plugin after validating the received -configuration. The framework uses deduping and reference counting mechanism to -ensure that a plugin of a given kind and configuration is instantiated only once. +configuration. The framework uses deduping and reference counting to ensure that a plugin +of a given kind and configuration is instantiated only once. A plugin typically creates a new thread and a timer to periodically query and -send a certificate (and the key) to all its watchers. **`FileWatcherCertificateProvider`** +send the certificate (and the key) to all its watchers. **`FileWatcherCertificateProvider`** (aka `file_watcher` described [above][FILE-WATCHER-LINK]) is an implementation of the **`CertificateProvider`**. This plugin monitors configured file-paths in the file system and reads those files on updates to get the latest certificates and keys and -provide those to the watchers after converting them to the canonical -format e.g. `java.security.PrivateKey` and `java.security.cert.X509Certificate` in Java. +provide those to the watchers after converting them to the canonical format. For example, +Java uses `java.security.PrivateKey` and `java.security.cert.X509Certificate` for a +private key and a certificate respectively. ## Rationale -gRPC has been steadily adding support for various xDS features including load balancing and +gRPC has been steadily adding support for various xDS features such as load balancing and advanced traffic management. xDS-based security was next in the roadmap and this proposal -addresses that. gRPC makes a proxyless service mesh (PSM) possible. A secure proxyless -service mesh requires the security features described in this proposal. +addresses that requirement. gRPC makes a proxyless service mesh (PSM) possible. A secure +proxyless service mesh requires the security features described in this proposal. The Certificate Provider Plugin Framework provides a generic alternative to the SDS server/agent based solution and eliminates the dependency on the SDS protocol. An SDS From c1f94ebf6ff0130bac77cf8b384689039d1396c2 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Fri, 9 Jul 2021 13:26:25 -0700 Subject: [PATCH 10/26] add further content about validation of combined_validation_context --- A29-xds-tls-security.md | 52 ++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 48f61001d..1dca75904 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -193,10 +193,11 @@ If any of the following fields are present, gRPC will NACK the CDS update: a server for the connection as described below. This check is in lieu of the canonical [hostname check in Web PKI][RFC6125-6]. -If [match_subject_alt_names][] is populated in the [combined_validation_context][CVC] -of the received `UpstreamTlsContext` then gRPC validates the SAN entries in the server -certificate by matching the `match_subject_alt_names` values using the [StringMatcher][] -semantics. If the match does not succeed the connection attempt fails indicating a +If [match_subject_alt_names][] in [default_validation_context][] +of [combined_validation_context][CVC] of the received `UpstreamTlsContext` is populated +then gRPC validates the SAN entries in the server certificate by matching the +`match_subject_alt_names` values using the [StringMatcher][] semantics. +If the match does not succeed the connection attempt fails indicating a "certificate check failure". Individual Implementations will use hooks provided by the underlying TLS framework to @@ -204,6 +205,7 @@ implement server authorization. As an example, Java uses a custom `X509TrustMana implementation through the `SslContext` provided to the client sub-channel. [match_subject_alt_names]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L373 +[default_validation_context]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L177 [CVC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251 [StringMatcher]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L20 [RFC6125-6]: https://datatracker.ietf.org/doc/html/rfc6125#section-6 @@ -296,15 +298,16 @@ gRPC does not support the other certificate acquisition mechanisms specified by When fields of type [`CertificateProviderInstance`][CPI] are present gRPC ignores the respective unsupported fields but if the unsupported fields are present by themselves gRPC will NACK the update. -For example, in [`UpstreamTlsContext`][UTC] (on the client side), the identity certificate is not needed for the TLS mode, -which is indicated by [`tls_certificate_certificate_provider_instance`][TCCPI] being absent. However in this case -if any of the other unsupported identity certificate fields ([tls_certificates][TLS-CERT], -[tls_certificate_sds_secret_configs][CERT-SDS], [tls_certificate_certificate_provider][CERT-PROVIDER]) are -present then gRPC will NACK the update. But if [`tls_certificate_certificate_provider_instance`][TCCPI] is -present, then the unsupported fields are ignored. This allows a control plane to formulate a single -`CommonTlsContext` that works for both gRPC (which only supports [`CertificateProviderInstance`][CPI]) -and Envoy (which does not support [`CertificateProviderInstance`][CPI]) to achieve consistent -security configuration between gRPC and Envoy. +For example, in [`UpstreamTlsContext`][UTC] (on the client side), the identity certificate is not +needed for the TLS mode, which is indicated by [`tls_certificate_certificate_provider_instance`][TCCPI] +being absent. However in this case if any of the other unsupported identity certificate fields +([tls_certificates][TLS-CERT], [tls_certificate_sds_secret_configs][CERT-SDS], +[tls_certificate_certificate_provider][CERT-PROVIDER]) are present then gRPC will NACK the update. +But if [`tls_certificate_certificate_provider_instance`][TCCPI] is present, then the unsupported +fields are ignored. This allows a control plane to formulate a single `CommonTlsContext` that works +for both gRPC (which only supports [`CertificateProviderInstance`][CPI]) and Envoy (which does not +support [`CertificateProviderInstance`][CPI]) to achieve consistent security configuration between +gRPC and Envoy. The following fields are unsupported and if present will cause a NACK from gRPC: @@ -316,6 +319,26 @@ be absent. On the client side (inside [`UpstreamTlsContext`][UTC]) it is ignored The processing and parsing of `CommonTlsContext` inside any particular CDS or LDS response does not take into account whether Xds credentials are in effect for the respective channel or server. +[`combined_validation_context`][CVC] is validated as follows: [default_validation_context][] +is accepted only on the client side i.e. inside `UpstreamTlsContext`. And inside that field +only [match_subject_alt_names][] is processed as described [above][server-authz]. If any of +the other fields (listed below) are present, the update is NACKed. + +* `trusted_ca` +* `watched_directory` +* `verify_certificate_spki` +* `verify_certificate_hash` +* `require_signed_certificate_timestamp` +* `crl` +* `allow_expired_certificate` +* `trust_chain_verification` +* `custom_validator_config` + +Only [`validation_context_certificate_provider_instance`][VCCPI1] is accepted. When that value is present +in the [`combined_validation_context`][CVC] the other fields +[`validation_context_certificate_provider`][VCCP1] and [`validation_context_sds_secret_config`][VCSSC1] +are ignored otherwise the presence of those fields will cause a NACK. + [CPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L154 [TCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L234 [VCCPI1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L200 @@ -328,6 +351,9 @@ not take into account whether Xds credentials are in effect for the respective c [CUSTOM-HS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L276 [ALPN-PROTOCOLS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L272 [UTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26 +[server-authz]: #server-authorization-aka-subject-alt-name-checks +[VCCP1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L193 +[VCSSC1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L184 ### Use of SPIFFE IDs in Certificates From 0f0193785d0f88ff0d55db4f6cfc46ba4587318e Mon Sep 17 00:00:00 2001 From: sanjaypujare Date: Thu, 15 Jul 2021 10:18:03 -0700 Subject: [PATCH 11/26] Update A29-xds-tls-security.md Co-authored-by: Sergii Tkachenko --- A29-xds-tls-security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 1dca75904..0c5694c09 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -498,7 +498,7 @@ extensible certificate providers. In any case the addition of xDS based security has brought gRPC xDS support closer to Envoy in terms of capabilities. This enables various use-cases such as migration to -proxyless and interop or co-existence with Envoy. +proxyless and interop or coexistence with Envoy. ## Implementation Status From 89ffe5e548af4e9bc61adb0bd833bbcd65f0f48a Mon Sep 17 00:00:00 2001 From: sanjaypujare Date: Mon, 19 Jul 2021 21:48:10 -0700 Subject: [PATCH 12/26] Apply suggestions from code review 7 suggestions accepted Co-authored-by: Sergii Tkachenko --- A29-xds-tls-security.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 0c5694c09..caf4b93d2 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -51,14 +51,14 @@ enable (or disable) the use of these configurations. We need a mechanism by which a programmer can "opt in" to allow the use of xDS provided security configuration for a gRPC channel or server. This is achieved by supplying an `XdsChannelCredentials` -(to a channel) or an `XdsServerCredentials` (to a server). These two new credentials types are an extension -of the existing channel or server credentials types in each language. Each `Xds*Credentials` needs to -be provided with a "fallback credentials". The fallback credentials is used in the following cases: +(to a channel) or an `XdsServerCredentials` (to a server). These two new credentials types extend +the existing channel or server credentials types in each language. Each `Xds*Credentials` needs to +be provided with _fallback credentials_. The fallback credentials are used in the following cases: -- when xDS is not in use such as when the `xds:` scheme is not used on the client side +- when xDS is not in use (such as when the `xds:` scheme is not used on the client side) -- xDS is in use but the control plane does not provide security configuration. The gRPC behavior -in this case is different from Envoy's due to fallback credentials. Envoy will just +- xDS is in use, but the control plane does not provide security configuration. The gRPC behavior +in this case is different from Envoy's due to fallback credentials. Envoy will use plaintext (insecure) communication mode in this case. But with gRPC, the application needs to use InsecureCredentials as the fallback credentials to get the same result. @@ -393,7 +393,7 @@ whose schema is defined by that plugin. The structure in the bootstrap file is as follows: -``` +```jsonc "certificate_providers": { "instance_name": { "plugin_name": "implementation_name", @@ -424,7 +424,7 @@ in the [JSON format described for a `Duration`][DURATION-JSON] protobuf message. For example, the bootstrap file might contain the following: -``` +```jsonc "certificate_providers": { "google_cloud_private_spiffe": { // certificate_provider_instance name "plugin_name": "file_watcher", // name of the plugin instance From fdd686e8d3d3e16e983f11148ff864ce7862125e Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Tue, 20 Jul 2021 01:23:00 -0700 Subject: [PATCH 13/26] address remaining comments --- A29-xds-tls-security.md | 113 +++++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 42 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index caf4b93d2..1bbabbde3 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -144,8 +144,13 @@ Use of XdsServerCredentials: ### xDS Protocol -gRPC uses CDS to configure client side security and LDS for server side security as described below. -The required fields were added to xDS v3 hence xDS v3 is a pre-requisite for this proposal. +xDS v3 is a pre-requisite for this proposal because the required fields were added to xDS v3. +gRPC uses CDS to configure client side security and LDS for server side security as described in the +sections below. The sections describe how the CDS or LDS updates are processed by gRPC. Note that gRPC +always validates all security configurations in CDS or LDS regardless of whether an XdsChannelCredentials +or XdsServerCredentials is in force. If validation fails, the update is NACKed. When an update is +accepted the correponding security configuration in CDS or LDS is used if the corresponding +Xds*Credentials is in force. #### CDS for Client Side Security @@ -160,19 +165,21 @@ For example, C-core uses channel args to pass security configuration down, where Java constructs a dynamic `SslContextProvider` that is directly usable by a sub-channel's TLS handshaker to build an `SslContext` for the pending TLS handshake. -Only when a channel is using `XdsChannelCredentials`, gRPC uses the security configuration -in `UpstreamTlsContext`. [`common_tls_context`][CTC] in the `UpstreamTlsContext` contains -the required security configuration. See below for [`CommonTlsContext`][CTC-type] processing. +[`common_tls_context`][CTC] in the `UpstreamTlsContext` contains the required security +configuration. See below for [`CommonTlsContext`][CTC-type] processing. A secure client at a minimum requires [`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] to be able to validate the server certificate -in the TLS mode. If this field is not set, gRPC will NACK the CDS update. The client identity -certificate is configured via the [`tls_certificate_certificate_provider_instance`][TCCPI] -field which is optional. The client certificate is sent to the server if the server requests -or requires it in the TLS handshake. If the server requires the client certificate but is not -present then the TLS handshake fails. +in the TLS mode. As part of validating all CDS updates, if this field is not set in a CDS, +gRPC will NACK the CDS update. The client identity certificate is configured via the +[`tls_certificate_certificate_provider_instance`][TCCPI] field which is optional. The +client certificate is sent to the server if the server requests or requires it in the +TLS handshake. If the server requires the client certificate but is not +configured on the client side then the TLS handshake will fail because of the client's inability +to send the certificate. -If any of the following fields are present, gRPC will NACK the CDS update: +As part of validating all CDS updates, if any of the following fields are present, gRPC +will NACK a CDS update: * [sni][SNI] * [allow_renegotiation][ALLOW-RENEG] @@ -193,14 +200,34 @@ If any of the following fields are present, gRPC will NACK the CDS update: a server for the connection as described below. This check is in lieu of the canonical [hostname check in Web PKI][RFC6125-6]. -If [match_subject_alt_names][] in [default_validation_context][] -of [combined_validation_context][CVC] of the received `UpstreamTlsContext` is populated -then gRPC validates the SAN entries in the server certificate by matching the -`match_subject_alt_names` values using the [StringMatcher][] semantics. -If the match does not succeed the connection attempt fails indicating a -"certificate check failure". +If [`match_subject_alt_names`][match_subject_alt_names] in +[`default_validation_context`][default_validation_context] of +[combined_validation_context][CVC] of the received `UpstreamTlsContext` is populated +then gRPC checks the SAN entries in the leaf server certificate against the +`match_subject_alt_names` values as follows: -Individual Implementations will use hooks provided by the underlying TLS framework to +* if the `match_subject_alt_names` list is empty then there is nothing to match and the +check succeeds. + +* if there is no leaf server certificate, or there are no SAN entries in the certificate +the check fails. + +* each SAN entry of type DNS, URI and IP address is considered for the below match +logic. If an entry matches as per the logic, the check succeeds and it exits the check +logic. + + * if the SAN entry is empty then the match fails for that entry. + + * the SAN entry is matched against each value of +[`match_subject_alt_names`][match_subject_alt_names] as follows. + * A `match_subject_alt_names` is a [`StringMatcher`][StringMatcher] and + the match is performed as per the semantics described for each `match_pattern` + in the [`StringMatcher`][StringMatcher] type. If there is a match, then the + check succeeds and it exits the check logic. + +If the check fails, the connection attempt fails with a "certificate check failure". + +Individual implementations will use hooks provided by the underlying TLS framework to implement server authorization. As an example, Java uses a custom `X509TrustManager` implementation through the `SslContext` provided to the client sub-channel. @@ -220,33 +247,34 @@ the security (and other) configuration for that connection as described in the [`FilterChainMatch`][filter-chain-match] section. The [`transport_socket`][transport-socket] of the matched (selected) `filter_chain` is used to extract the [`DownstreamTlsContext`][DTC] as described [here][transport-socket-comment]. -If the `transport_socket` name is not `envoy.transport_sockets.tls` i.e. -something we don't recognize, gRPC will NACK the LDS update. Otherwise -the `DownstreamTlsContext` thus obtained is used for the incoming connection -if the server is using `XdsServerCredentials`. How the security configuration -in `DownstreamTlsContext` is made available to the incoming connection is language -dependent. For example, Java constructs a dynamic `SslContextProvider` that is -directly usable by the connection's TLS handshaker to build an `SslContext` for -the upcoming TLS handshake. If there is no `DownstreamTlsContext` (such as when -[`transport_socket`][transport-socket] is not present or is not named -`"envoy.transport_sockets.tls"`) then gRPC uses the fallback credentials -for the incoming connection. +As part of validating all LDS updates, if a `transport_socket` name is not +`envoy.transport_sockets.tls` i.e. something we don't recognize, gRPC will +NACK an LDS update. Otherwise the `DownstreamTlsContext` thus obtained is used +for the incoming connection if the server is using `XdsServerCredentials`. +How the security configuration in `DownstreamTlsContext` is made available to +the incoming connection is language dependent. For example, Java constructs a +dynamic `SslContextProvider` that is directly usable by the connection's TLS +handshaker to build an `SslContext` for the upcoming TLS handshake. If there +is no `DownstreamTlsContext` (such as when [`transport_socket`][transport-socket] +is not present) then gRPC uses the fallback credentials for the incoming connection. [`common_tls_context`][CTC1] in the `DownstreamTlsContext` contains the required security configuration. See below for [`CommonTlsContext`][CTC-type] processing. A secure server at a minimum requires an identity certificate which is provided by [`tls_certificate_certificate_provider_instance`][TCCPI]. If that field is -empty, gRPC will NACK the update. If +empty, gRPC will NACK an update as part of validating all LDS updates. If [`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] is provided then the server will request the client certificate. When [`require_client_certificate`][RCC] is `true`, gRPC requires the client certificate and will reject a connection without a valid client certificate. When [`require_client_certificate`][RCC] is `true`, the [`validation_context_certificate_provider_instance`][VCCPI1] value should be -present otherwise gRPC will NACK the LDS update. +present otherwise gRPC will NACK an LDS update as part of validating all LDS +updates. -If any of the following fields are present, gRPC will NACK the LDS update: +If any of the following fields are present, gRPC will NACK an LDS update as +part of validating all LDS updates: * [require_sni][REQ-SNI] * [session_ticket_keys][SESSION-TICKET-KEYS] @@ -296,33 +324,34 @@ gRPC does not support the other certificate acquisition mechanisms specified by * [validation_context_certificate_provider][VAL-PROVIDER] When fields of type [`CertificateProviderInstance`][CPI] are present gRPC ignores the respective -unsupported fields but if the unsupported fields are present by themselves gRPC will NACK the update. +unsupported fields but if the unsupported fields are present by themselves gRPC will NACK an update +as part of validating all CDS/LDS updates. For example, in [`UpstreamTlsContext`][UTC] (on the client side), the identity certificate is not needed for the TLS mode, which is indicated by [`tls_certificate_certificate_provider_instance`][TCCPI] being absent. However in this case if any of the other unsupported identity certificate fields ([tls_certificates][TLS-CERT], [tls_certificate_sds_secret_configs][CERT-SDS], -[tls_certificate_certificate_provider][CERT-PROVIDER]) are present then gRPC will NACK the update. +[tls_certificate_certificate_provider][CERT-PROVIDER]) are present then gRPC will NACK a CDS update. But if [`tls_certificate_certificate_provider_instance`][TCCPI] is present, then the unsupported fields are ignored. This allows a control plane to formulate a single `CommonTlsContext` that works for both gRPC (which only supports [`CertificateProviderInstance`][CPI]) and Envoy (which does not support [`CertificateProviderInstance`][CPI]) to achieve consistent security configuration between gRPC and Envoy. -The following fields are unsupported and if present will cause a NACK from gRPC: +The following fields are unsupported and if present will cause a NACK from gRPC for any update: * [tls_params][TLS-PARAMS] * [custom_handshaker][CUSTOM-HS] -[alpn_protocols][ALPN-PROTOCOLS] on server side (inside [`DownstreamTlsContext`][DTC]) should -be absent. On the client side (inside [`UpstreamTlsContext`][UTC]) it is ignored if present. +[alpn_protocols][ALPN-PROTOCOLS] on server side (inside [`DownstreamTlsContext`][DTC]) and +on the client side (inside [`UpstreamTlsContext`][UTC]) is ignored if present. The processing and parsing of `CommonTlsContext` inside any particular CDS or LDS response does not take into account whether Xds credentials are in effect for the respective channel or server. -[`combined_validation_context`][CVC] is validated as follows: [default_validation_context][] -is accepted only on the client side i.e. inside `UpstreamTlsContext`. And inside that field -only [match_subject_alt_names][] is processed as described [above][server-authz]. If any of -the other fields (listed below) are present, the update is NACKed. +[`combined_validation_context`][CVC] is validated in any CDS/LDS update as follows: +[default_validation_context][] is accepted only on the client side i.e. inside `UpstreamTlsContext`. +And inside that field only [match_subject_alt_names][] is processed as described [above][server-authz]. +If any of the other fields (listed below) are present, the update is NACKed. * `trusted_ca` * `watched_directory` @@ -375,7 +404,7 @@ provider instance name. For example, an on-prem client may get its certificate u provider whereas a client running in cloud may use a cloud-vendor provided implementation to obtain the certificate. -gRPC provides a `CertificateProvider` plugin API that can support multiple implementations. The plugin API +gRPC offers a `CertificateProvider` plugin API that can support multiple implementations. The plugin API is not currently public, so applications cannot currently add their own provider implementations although we might make this API public in the future. However gRPC currently includes a `file_watcher` provider implementation - descibed [below][FILE-WATCHER-LINK] - which reads certificates from the local file system. From f0aea10c0a2b942e21229ea1650136f72194ff68 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Tue, 20 Jul 2021 17:54:40 -0700 Subject: [PATCH 14/26] add IPv6 canonical string representation spec --- A29-xds-tls-security.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 1bbabbde3..69be24467 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -213,17 +213,19 @@ check succeeds. the check fails. * each SAN entry of type DNS, URI and IP address is considered for the below match -logic. If an entry matches as per the logic, the check succeeds and it exits the check -logic. +logic. An IP address is converted to its canonical string representation. For +IPv6 this includes [maximum zero compression][zero-compr], [no leading zeros][no-leading-0] +and [lower case][lower-case] e.g. `2001:db8::1` but *not* `2001:DB8:0::01`. +If an entry matches as per this logic, the check completes successfully. - * if the SAN entry is empty then the match fails for that entry. + * if a SAN entry is empty then the match fails for that entry. - * the SAN entry is matched against each value of + * a SAN entry is matched against each value of [`match_subject_alt_names`][match_subject_alt_names] as follows. - * A `match_subject_alt_names` is a [`StringMatcher`][StringMatcher] and + * A `match_subject_alt_names` value is a [`StringMatcher`][StringMatcher] and the match is performed as per the semantics described for each `match_pattern` in the [`StringMatcher`][StringMatcher] type. If there is a match, then the - check succeeds and it exits the check logic. + check completes successfully. If the check fails, the connection attempt fails with a "certificate check failure". @@ -236,6 +238,9 @@ implementation through the `SslContext` provided to the client sub-channel. [CVC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251 [StringMatcher]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L20 [RFC6125-6]: https://datatracker.ietf.org/doc/html/rfc6125#section-6 +[zero-compr]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.2 +[no-leading-0]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.1 +[lower-case]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.3 #### LDS for Server Side Security From a9483669f7ded7a86b78879419e4496be8becf4e Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Tue, 3 Aug 2021 20:26:47 -0700 Subject: [PATCH 15/26] address latest review comments --- A29-xds-tls-security.md | 149 ++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 66 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 69be24467..9d541edf2 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -148,9 +148,14 @@ xDS v3 is a pre-requisite for this proposal because the required fields were add gRPC uses CDS to configure client side security and LDS for server side security as described in the sections below. The sections describe how the CDS or LDS updates are processed by gRPC. Note that gRPC always validates all security configurations in CDS or LDS regardless of whether an XdsChannelCredentials -or XdsServerCredentials is in force. If validation fails, the update is NACKed. When an update is -accepted the correponding security configuration in CDS or LDS is used if the corresponding -Xds*Credentials is in force. +or XdsServerCredentials is in force. If validation fails on an update, the update is NACKed. + +An unsupported field is normally ignored. However if ignoring a field compromises security, or +if the unsupported field affects how we interpret other fields, we NACK the update when the +field is present. + +When an update is accepted, the security configuration contained in that update is used if the +application used Xds*Credentials. #### CDS for Client Side Security @@ -159,27 +164,23 @@ The CDS policy is the top level LB policy applied to all the connections under t [`UpstreamTlsContext`][UTC] as described [here][CL-TS-comment]. Note that we don't (currently) support [`transport_socket_matches`][CL-TS-matches]. The security configuration extracted from the `UpstreamTlsContext` thus obtained -is passed down to all the child policies and connections. How this is done is language dependent -and is similar to how the implementations pass policy information down to child policies. -For example, C-core uses channel args to pass security configuration down, whereas -Java constructs a dynamic `SslContextProvider` that is directly usable by a sub-channel's -TLS handshaker to build an `SslContext` for the pending TLS handshake. +is passed down to all the child policies and connections similar to how gRPC passes +load balancer policy information down to child policies. [`common_tls_context`][CTC] in the `UpstreamTlsContext` contains the required security configuration. See below for [`CommonTlsContext`][CTC-type] processing. A secure client at a minimum requires [`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] to be able to validate the server certificate -in the TLS mode. As part of validating all CDS updates, if this field is not set in a CDS, -gRPC will NACK the CDS update. The client identity certificate is configured via the -[`tls_certificate_certificate_provider_instance`][TCCPI] field which is optional. The +in the TLS mode. As part of validating all CDS updates, if this field is not set in a CDS +resource, gRPC will NACK the CDS update. The client identity certificate is configured via +the [`tls_certificate_certificate_provider_instance`][TCCPI] field which is optional. The client certificate is sent to the server if the server requests or requires it in the -TLS handshake. If the server requires the client certificate but is not -configured on the client side then the TLS handshake will fail because of the client's inability -to send the certificate. +TLS handshake. If the server requires the client certificate but is not configured on the +client side then the TLS handshake will fail because of the client's inability to send the +certificate. -As part of validating all CDS updates, if any of the following fields are present, gRPC -will NACK a CDS update: +The following fields in a CDS update are ignored: * [sni][SNI] * [allow_renegotiation][ALLOW-RENEG] @@ -212,7 +213,7 @@ check succeeds. * if there is no leaf server certificate, or there are no SAN entries in the certificate the check fails. -* each SAN entry of type DNS, URI and IP address is considered for the below match +* each SAN entry of type DNS, URI, email and IP address is considered for the below match logic. An IP address is converted to its canonical string representation. For IPv6 this includes [maximum zero compression][zero-compr], [no leading zeros][no-leading-0] and [lower case][lower-case] e.g. `2001:db8::1` but *not* `2001:DB8:0::01`. @@ -224,10 +225,11 @@ If an entry matches as per this logic, the check completes successfully. [`match_subject_alt_names`][match_subject_alt_names] as follows. * A `match_subject_alt_names` value is a [`StringMatcher`][StringMatcher] and the match is performed as per the semantics described for each `match_pattern` - in the [`StringMatcher`][StringMatcher] type. If there is a match, then the - check completes successfully. + in the [`StringMatcher`][StringMatcher] type. Note that [exact match][ExactMatch] + supports subdomain matching for wildcard DNS SAN entries as described + [here][DNS-wildcard]. If there is a match, then the check completes successfully. -If the check fails, the connection attempt fails with a "certificate check failure". +If the check fails, the connection attempt fails with "certificate check failure". Individual implementations will use hooks provided by the underlying TLS framework to implement server authorization. As an example, Java uses a custom `X509TrustManager` @@ -237,10 +239,12 @@ implementation through the `SslContext` provided to the client sub-channel. [default_validation_context]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L177 [CVC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251 [StringMatcher]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L20 +[ExactMatch]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L29 [RFC6125-6]: https://datatracker.ietf.org/doc/html/rfc6125#section-6 [zero-compr]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.2 [no-leading-0]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.1 [lower-case]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.3 +[DNS-wildcard]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L358-L360 #### LDS for Server Side Security @@ -256,11 +260,7 @@ As part of validating all LDS updates, if a `transport_socket` name is not `envoy.transport_sockets.tls` i.e. something we don't recognize, gRPC will NACK an LDS update. Otherwise the `DownstreamTlsContext` thus obtained is used for the incoming connection if the server is using `XdsServerCredentials`. -How the security configuration in `DownstreamTlsContext` is made available to -the incoming connection is language dependent. For example, Java constructs a -dynamic `SslContextProvider` that is directly usable by the connection's TLS -handshaker to build an `SslContext` for the upcoming TLS handshake. If there -is no `DownstreamTlsContext` (such as when [`transport_socket`][transport-socket] +If there is no `DownstreamTlsContext` (such as when [`transport_socket`][transport-socket] is not present) then gRPC uses the fallback credentials for the incoming connection. [`common_tls_context`][CTC1] in the `DownstreamTlsContext` contains the required @@ -278,15 +278,18 @@ client certificate. When [`require_client_certificate`][RCC] is `true`, the present otherwise gRPC will NACK an LDS update as part of validating all LDS updates. +The following fields in an LDS update are ignored: + +* [disable_stateless_session_resumption][DIS-STATELESS-SESS-RES] +* [session_timeout][SESSION-TIMEOUT] + If any of the following fields are present, gRPC will NACK an LDS update as part of validating all LDS updates: * [require_sni][REQ-SNI] * [session_ticket_keys][SESSION-TICKET-KEYS] * [session_ticket_keys_sds_secret_config][SESSION-TICKET-KEYS-SDS] -* [disable_stateless_session_resumption][DIS-STATELESS-SESS-RES] -* [session_timeout][SESSION-TIMEOUT] -* [ocsp_staple_policy][OCSP-STAPLE-POLICY] +* [ocsp_staple_policy][OCSP-STAPLE-POLICY]: any value other than `LENIENT_STAPLING` causes NACK. [A36]: A36-xds-for-servers.md [filter-chains]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#L120 @@ -343,35 +346,40 @@ for both gRPC (which only supports [`CertificateProviderInstance`][CPI]) and Env support [`CertificateProviderInstance`][CPI]) to achieve consistent security configuration between gRPC and Envoy. -The following fields are unsupported and if present will cause a NACK from gRPC for any update: +The following fields are unsupported and if present will cause a NACK from gRPC for any update +since ignoring these fields will compromise security: * [tls_params][TLS-PARAMS] * [custom_handshaker][CUSTOM-HS] -[alpn_protocols][ALPN-PROTOCOLS] on server side (inside [`DownstreamTlsContext`][DTC]) and +[alpn_protocols][ALPN-PROTOCOLS] on the server side (inside [`DownstreamTlsContext`][DTC]) and on the client side (inside [`UpstreamTlsContext`][UTC]) is ignored if present. The processing and parsing of `CommonTlsContext` inside any particular CDS or LDS response does not take into account whether Xds credentials are in effect for the respective channel or server. [`combined_validation_context`][CVC] is validated in any CDS/LDS update as follows: -[default_validation_context][] is accepted only on the client side i.e. inside `UpstreamTlsContext`. -And inside that field only [match_subject_alt_names][] is processed as described [above][server-authz]. -If any of the other fields (listed below) are present, the update is NACKed. +The field [match_subject_alt_names][] inside [default_validation_context][] is accepted only on +the client side i.e. inside `UpstreamTlsContext` and is processed as described [above][server-authz]. +If any of the other fields (listed below) are present in [default_validation_context][], the update +is NACKed since ignoring these fields will compromise security: -* `trusted_ca` -* `watched_directory` * `verify_certificate_spki` * `verify_certificate_hash` * `require_signed_certificate_timestamp` * `crl` -* `allow_expired_certificate` -* `trust_chain_verification` +* `trust_chain_verification`: any value other than `VERIFY_TRUST_CHAIN` causes NACK. * `custom_validator_config` -Only [`validation_context_certificate_provider_instance`][VCCPI1] is accepted. When that value is present -in the [`combined_validation_context`][CVC] the other fields -[`validation_context_certificate_provider`][VCCP1] and [`validation_context_sds_secret_config`][VCSSC1] -are ignored otherwise the presence of those fields will cause a NACK. +The following fields from [default_validation_context][] are ignored: + +* `trusted_ca` +* `watched_directory` +* `allow_expired_certificate` + +In [`combined_validation_context`][CVC], only [`validation_context_certificate_provider_instance`][VCCPI1] +is accepted. When that field is present, the other fields [`validation_context_certificate_provider`][VCCP1] +and [`validation_context_sds_secret_config`][VCSSC1] are ignored otherwise the presence of those fields will +cause a NACK. [CPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L154 [TCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L234 @@ -389,25 +397,17 @@ are ignored otherwise the presence of those fields will cause a NACK. [VCCP1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L193 [VCSSC1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L184 -### Use of SPIFFE IDs in Certificates - -To facilitate service mesh secure communication, we support [SPIFFE][] based certificates and peer certificate -verification following the [SPIFFE][] specification and the [match_subject_alt_names][] field in xDS. - -[SPIFFE]: https://github.com/spiffe/spiffe -[match_subject_alt_names]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#envoy-v3-api-field-extensions-transport-sockets-tls-v3-certificatevalidationcontext-match-subject-alt-names - ### Certificate Provider Plugin Framework xDS supports many different configurations for endpoints to obtain certificates but gRPC supports only -`CertificateProviderInstance`. Through this object the control plane tells the xDS client the name of -a certificate and the "instance" name of a provider to use to obtain a certificate. This provider -instance name is translated into a provider implementation and a configuration for that implementation -using the client's own configuration instead of being sent by the control plane. This enables flexibility -in heterogeneous deployments where different clients can use different implementations for the same -provider instance name. For example, an on-prem client may get its certificate using a local certificate -provider whereas a client running in cloud may use a cloud-vendor provided implementation to obtain -the certificate. +[`CertificateProviderInstance`][CPI]. In this approach, the control plane tells the xDS client the +[name of a certificate][CERT-NAME] (which is currently ignored) and the ["instance" name][INST-NAME] +of a provider to use to obtain a certificate. This provider [instance name][INST-NAME] is translated +into a provider implementation and a configuration for that implementation using the client's own +configuration instead of being sent by the control plane. This enables flexibility in heterogeneous +deployments where different clients can use different implementations for the same provider instance +name. For example, an on-prem client may get its certificate using a local certificate provider whereas +a client running in cloud may use a cloud-vendor provided implementation to obtain the certificate. gRPC offers a `CertificateProvider` plugin API that can support multiple implementations. The plugin API is not currently public, so applications cannot currently add their own provider implementations although @@ -415,6 +415,8 @@ we might make this API public in the future. However gRPC currently includes a ` implementation - descibed [below][FILE-WATCHER-LINK] - which reads certificates from the local file system. [FILE-WATCHER-LINK]: #file_watcher-certificate-provider +[CERT-NAME]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L169 +[INST-NAME]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L163 Certificate provider plugin instances are configured via the xDS bootstrap file. There is a new top-level field called `"certificate_providers"` whose value is a map (a JSON object). The key @@ -447,12 +449,12 @@ a certificate from `instance_name`, the client will use this plugin instance. As mentioned before, we currently only have one plugin implementation called `file_watcher`. The configuration for this plugin has the following fields: -- `certificate_file`: The path to the file containing the identity certificate. The file should contain -a PEM-formatted X.509 conforming certificate. +- `certificate_file`: The path to the file containing the identity certificate or certificate chain. +The file should contain a PEM-formatted X.509 conforming certificate or certificate chain. - `private_key_file`: The path to the file containing the private key. The file should contain a PEM-formatted PKCS encoded private key. -- `ca_certificate_file`: The path to the file containing the root certificate. The file should contain -a PEM-formatted X.509 conforming certificate chain. +- `ca_certificate_file`: The path to the file containing the root certificates aka trust bundle. +The file should contain PEM-formatted X.509 conforming certificates. - `refresh_interval`: Specifies how frequently the plugin should read the files. The value must be in the [JSON format described for a `Duration`][DURATION-JSON] protobuf message. @@ -461,7 +463,7 @@ For example, the bootstrap file might contain the following: ```jsonc "certificate_providers": { "google_cloud_private_spiffe": { // certificate_provider_instance name - "plugin_name": "file_watcher", // name of the plugin instance + "plugin_name": "file_watcher", // name of the plugin implementation "config": { // config to be supplied to the plugin instance "certificate_file": "/var/run/gke-spiffe/certs/certificates.pem", "private_key_file": "/var/run/gke-spiffe/certs/private_key.pem", @@ -473,15 +475,30 @@ For example, the bootstrap file might contain the following: ``` With this configuration, when the xDS server tells the client to get a certificate from -plugin instance `"google_cloud_private_spiffe"`, the client will load the certificate data -from the specified files. +plugin instance `"google_cloud_private_spiffe"` (the value of [`instance_name`][INST-NAME]), +the client will load the certificate data from the specified files. [DURATION-JSON]: https://developers.google.com/protocol-buffers/docs/proto3#json. ## Implementation Details -High level implementation details common to all the implementing gRPC languages -are described here. +The gRPC client xDS flow is described in [gRPC Client Architecture][A27:CDS]. After +obtaining the cluster load balancing policy configuration and optional security +configuration (in [`UpstreamTlsContext`][UTC]), gRPC passes it down to child policies +via channel arguments or a similar mechanism depending on the language. For example, +C-core uses channel arguments to pass down the configuration, whereas Java constructs +a dynamic `SslContextProvider` that is made available to sub-channels via channel +attributes. The `SslContextProvider` is used by a sub-channel's TLS handshaker to +build an `SslContext` for the pending TLS handshake. + +Server-side xDS processing is described in [A36: xDS-Enabled Servers][A36]. After +obtaining the routing and optional security configuration (in +[`DownstreamTlsContext`][DTC]), gRPC makes it available to each incoming connection. +How this is done is language dependent. For example, Java uses a `ProtocolNegotiator` +to pick a [`DownstreamTlsContext`][DTC] for each incoming connection and construct a +dynamic `SslContextProvider` that is passed to the channel handler for that +connection. The channel handler uses the `SslContextProvider` to build an `SslContext` +for the pending TLS handshake. A **`CertificateProvider`** object represents a plugin that provides the required certificates and keys to the gRPC application. A component registers itself as a **`Watcher`** From f3b7a961c96e02785786c8fbc49f8009dbc0529d Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Tue, 3 Aug 2021 21:17:51 -0700 Subject: [PATCH 16/26] address latest review comments - part2 --- A29-xds-tls-security.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 9d541edf2..937f55480 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -172,8 +172,10 @@ configuration. See below for [`CommonTlsContext`][CTC-type] processing. A secure client at a minimum requires [`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] to be able to validate the server certificate -in the TLS mode. As part of validating all CDS updates, if this field is not set in a CDS -resource, gRPC will NACK the CDS update. The client identity certificate is configured via +in the TLS mode. If [`UpstreamTlsContext`][UTC] is present but +[`combined_validation_context`][CVC] is not present or +[`validation_context_certificate_provider_instance`][VCCPI1] is not set, then +gRPC will NACK the CDS update. The client identity certificate is configured via the [`tls_certificate_certificate_provider_instance`][TCCPI] field which is optional. The client certificate is sent to the server if the server requests or requires it in the TLS handshake. If the server requires the client certificate but is not configured on the From 3ce1617a6b6215c3c607d36a4a980a04aaca3e80 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 5 Aug 2021 09:26:51 -0700 Subject: [PATCH 17/26] move a few fields from NACK to ignored category since they don't compromise security --- A29-xds-tls-security.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 937f55480..a58ad35ed 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -283,14 +283,14 @@ updates. The following fields in an LDS update are ignored: * [disable_stateless_session_resumption][DIS-STATELESS-SESS-RES] +* [session_ticket_keys][SESSION-TICKET-KEYS] +* [session_ticket_keys_sds_secret_config][SESSION-TICKET-KEYS-SDS] * [session_timeout][SESSION-TIMEOUT] If any of the following fields are present, gRPC will NACK an LDS update as part of validating all LDS updates: * [require_sni][REQ-SNI] -* [session_ticket_keys][SESSION-TICKET-KEYS] -* [session_ticket_keys_sds_secret_config][SESSION-TICKET-KEYS-SDS] * [ocsp_staple_policy][OCSP-STAPLE-POLICY]: any value other than `LENIENT_STAPLING` causes NACK. [A36]: A36-xds-for-servers.md @@ -369,7 +369,6 @@ is NACKed since ignoring these fields will compromise security: * `verify_certificate_hash` * `require_signed_certificate_timestamp` * `crl` -* `trust_chain_verification`: any value other than `VERIFY_TRUST_CHAIN` causes NACK. * `custom_validator_config` The following fields from [default_validation_context][] are ignored: @@ -377,6 +376,7 @@ The following fields from [default_validation_context][] are ignored: * `trusted_ca` * `watched_directory` * `allow_expired_certificate` +* `trust_chain_verification` In [`combined_validation_context`][CVC], only [`validation_context_certificate_provider_instance`][VCCPI1] is accepted. When that field is present, the other fields [`validation_context_certificate_provider`][VCCP1] From c227dd79fed62b7c3b39d79800dcd2544165a195 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 5 Aug 2021 09:36:40 -0700 Subject: [PATCH 18/26] add text saying certificate_name is ignored by file_watcher --- A29-xds-tls-security.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index a58ad35ed..1308abfeb 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -478,7 +478,8 @@ For example, the bootstrap file might contain the following: With this configuration, when the xDS server tells the client to get a certificate from plugin instance `"google_cloud_private_spiffe"` (the value of [`instance_name`][INST-NAME]), -the client will load the certificate data from the specified files. +the client will load the certificate data from the specified files. Note the +[certificate_name][CERT-NAME] value is currently ignored by this plugin. [DURATION-JSON]: https://developers.google.com/protocol-buffers/docs/proto3#json. From 749f4fa8ccc5d1c82864ec8f661ea658b283af5a Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 5 Aug 2021 14:57:46 -0700 Subject: [PATCH 19/26] update tls.proto and common.proto versions and line numbers --- A29-xds-tls-security.md | 68 ++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 1308abfeb..6f28848aa 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -192,10 +192,10 @@ The following fields in a CDS update are ignored: [CL-TS]: https://github.com/envoyproxy/envoy/blob/9aca65c395f01020080166e4795455addde167fa/api/envoy/config/cluster/v3/cluster.proto#L937 [CL-TS-comment]: https://github.com/envoyproxy/envoy/blob/9aca65c395f01020080166e4795455addde167fa/api/envoy/config/cluster/v3/cluster.proto#L932 [CL-TS-matches]: https://github.com/envoyproxy/envoy/blob/9aca65c395f01020080166e4795455addde167fa/api/envoy/config/cluster/v3/cluster.proto#L680 -[CTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L37 -[SNI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L40 -[ALLOW-RENEG]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L47 -[MAX-SESS-KEYS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L53 +[CTC]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L37 +[SNI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L40 +[ALLOW-RENEG]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L47 +[MAX-SESS-KEYS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L53 ##### Server Authorization aka Subject-Alt-Name Checks @@ -237,16 +237,16 @@ Individual implementations will use hooks provided by the underlying TLS framewo implement server authorization. As an example, Java uses a custom `X509TrustManager` implementation through the `SslContext` provided to the client sub-channel. -[match_subject_alt_names]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L373 -[default_validation_context]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L177 -[CVC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251 +[match_subject_alt_names]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L407 +[default_validation_context]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L188 +[CVC]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L274 [StringMatcher]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L20 [ExactMatch]: https://github.com/envoyproxy/envoy/blob/6321e5d95f7e435625d762ea82316b7a9f7071a4/api/envoy/type/matcher/string.proto#L29 [RFC6125-6]: https://datatracker.ietf.org/doc/html/rfc6125#section-6 [zero-compr]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.2 [no-leading-0]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.1 [lower-case]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.3 -[DNS-wildcard]: https://github.com/envoyproxy/envoy/blob/c94e646e0280e4c521f8e613f1ae2a02b274dbbf/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L358-L360 +[DNS-wildcard]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L392-L394 #### LDS for Server Side Security @@ -298,17 +298,17 @@ part of validating all LDS updates: [default-filter-chain]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#L131 [filter-chain-match]: A36-xds-for-servers.md#filterchainmatch [transport-socket]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener_components.proto#L246 -[DTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L57 +[DTC]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L57 [transport-socket-comment]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener_components.proto#L241 -[CTC1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L84 -[RCC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L88 -[CTC-type]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L129 -[REQ-SNI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L92 -[SESSION-TICKET-KEYS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L96 -[SESSION-TICKET-KEYS-SDS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L99 -[DIS-STATELESS-SESS-RES]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L109 -[SESSION-TIMEOUT]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L116 -[OCSP-STAPLE-POLICY]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L124 +[CTC1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L84 +[RCC]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L88 +[CTC-type]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L129 +[REQ-SNI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L92 +[SESSION-TICKET-KEYS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L96 +[SESSION-TICKET-KEYS-SDS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L99 +[DIS-STATELESS-SESS-RES]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L109 +[SESSION-TIMEOUT]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L116 +[OCSP-STAPLE-POLICY]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L124 #### CommonTlsContext Processing @@ -383,21 +383,21 @@ is accepted. When that field is present, the other fields [`validation_context_c and [`validation_context_sds_secret_config`][VCSSC1] are ignored otherwise the presence of those fields will cause a NACK. -[CPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L154 -[TCCPI]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L234 -[VCCPI1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L200 -[TLS-CERT]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L215 -[CERT-SDS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L225 -[CERT-PROVIDER]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L230 -[VAL-SDS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L242 -[VAL-PROVIDER]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L255 -[TLS-PARAMS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L207 -[CUSTOM-HS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L276 -[ALPN-PROTOCOLS]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L272 -[UTC]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26 +[CPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L165 +[TCCPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L256 +[VCCPI1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L205 +[TLS-CERT]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L226 +[CERT-SDS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L239 +[CERT-PROVIDER]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251 +[VAL-SDS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L265 +[VAL-PROVIDER]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L278 +[TLS-PARAMS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L212 +[CUSTOM-HS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L301 +[ALPN-PROTOCOLS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L297 +[UTC]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26 [server-authz]: #server-authorization-aka-subject-alt-name-checks -[VCCP1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L193 -[VCSSC1]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L184 +[VCCP1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L199 +[VCSSC1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L193 ### Certificate Provider Plugin Framework @@ -417,8 +417,8 @@ we might make this API public in the future. However gRPC currently includes a ` implementation - descibed [below][FILE-WATCHER-LINK] - which reads certificates from the local file system. [FILE-WATCHER-LINK]: #file_watcher-certificate-provider -[CERT-NAME]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L169 -[INST-NAME]: https://github.com/envoyproxy/envoy/blob/7d4b2cae486b66b62ba0d3e1e348504699bea1bf/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L163 +[CERT-NAME]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L180 +[INST-NAME]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L174 Certificate provider plugin instances are configured via the xDS bootstrap file. There is a new top-level field called `"certificate_providers"` whose value is a map (a JSON object). The key From 875cca7985f6ee09dc568bc0d78066285c2c328c Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 5 Aug 2021 21:38:57 -0700 Subject: [PATCH 20/26] update content to reference the new fields in tls and common.proto --- A29-xds-tls-security.md | 109 ++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 42 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 6f28848aa..2b69bd785 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -170,13 +170,19 @@ load balancer policy information down to child policies. [`common_tls_context`][CTC] in the `UpstreamTlsContext` contains the required security configuration. See below for [`CommonTlsContext`][CTC-type] processing. -A secure client at a minimum requires [`validation_context_certificate_provider_instance`][VCCPI1] -inside [`combined_validation_context`][CVC] to be able to validate the server certificate -in the TLS mode. If [`UpstreamTlsContext`][UTC] is present but -[`combined_validation_context`][CVC] is not present or -[`validation_context_certificate_provider_instance`][VCCPI1] is not set, then -gRPC will NACK the CDS update. The client identity certificate is configured via -the [`tls_certificate_certificate_provider_instance`][TCCPI] field which is optional. The +A secure client at a minimum requires a CA root certificate to be able to validate the server +certificate in the TLS mode and this is provided by [ca_certificate_provider_instance][CCPI] +inside the [`default_validation_context`][default_validation_context] of +[combined_validation_context][CVC]. For backward compatibility gRPC will use the deprecated +field [`validation_context_certificate_provider_instance`][VCCPI1] inside +[`combined_validation_context`][CVC] if [ca_certificate_provider_instance][CCPI] is not +present. If [`UpstreamTlsContext`][UTC] is present but +[`combined_validation_context`][CVC] is not present or neither of +[ca_certificate_provider_instance][CCPI] and [`validation_context_certificate_provider_instance`][VCCPI1] +is set, then gRPC will NACK the CDS update. The client identity certificate is configured via +[`tls_certificate_provider_instance`][TCPI] (or the deprecated +[`tls_certificate_certificate_provider_instance`][TCCPI] if [`tls_certificate_provider_instance`][TCPI] +is not set). Note that the identity certificate on the client side is optional. The client certificate is sent to the server if the server requests or requires it in the TLS handshake. If the server requires the client certificate but is not configured on the client side then the TLS handshake will fail because of the client's inability to send the @@ -269,14 +275,19 @@ is not present) then gRPC uses the fallback credentials for the incoming connect security configuration. See below for [`CommonTlsContext`][CTC-type] processing. A secure server at a minimum requires an identity certificate which is provided -by [`tls_certificate_certificate_provider_instance`][TCCPI]. If that field is +by [`tls_certificate_provider_instance`][TCPI] (or in its absence the deprecated +field [`tls_certificate_certificate_provider_instance`][TCCPI]). If both fields are empty, gRPC will NACK an update as part of validating all LDS updates. If +[ca_certificate_provider_instance][CCPI] inside the +[`default_validation_context`][default_validation_context] of [combined_validation_context][CVC] +(or in its absence the deprecated field [`validation_context_certificate_provider_instance`][VCCPI1] inside -[`combined_validation_context`][CVC] is provided then the server will request +[`combined_validation_context`][CVC]) is provided then the server will request the client certificate. When [`require_client_certificate`][RCC] is `true`, gRPC requires the client certificate and will reject a connection without a valid client certificate. When [`require_client_certificate`][RCC] is `true`, the -[`validation_context_certificate_provider_instance`][VCCPI1] value should be +[ca_certificate_provider_instance][CCPI] field (or in its absence +[`validation_context_certificate_provider_instance`][VCCPI1]) should be present otherwise gRPC will NACK an LDS update as part of validating all LDS updates. @@ -315,15 +326,20 @@ part of validating all LDS updates: `CommonTlsContext` is present in both the `UpstreamTlsContext` and `DownstreamTlsContext` protos and contains the certificate and key configuration information needed on the client and server side respectively. The configuration tells gRPC how to obtain certificates and the keys for the TLS handshake. Although there are various ways to obtain -certificates as per this proto (which are supported by Envoy), gRPC supports only one of them and that is defined by the -[`CertificateProviderInstance`][CPI] proto which is based on the notion of CertificateProvider plugin framework -(described later). The field `instance_name` defines a CertificateProvider "instance" that gRPC looks up in the -bootstrap file (described later) to obtain the CertificateProvider configuration. This configuration along with -the CertificateProvider plugin framework enables gRPC to acquire the certificates necessary for the TLS handshake. - -The field [`tls_certificate_certificate_provider_instance`][TCCPI] is used for the identity certificate and the private -key. And [`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] -is used for the root certificate-chain for validating peer certificates. +certificates as per this proto (which are supported by Envoy), gRPC supports only two of them. The preferred mechanism +is the [`CertificateProviderPluginInstance`][CPPI] proto and the less preferred mechanism is +[`CertificateProviderInstance`][CPI] which is a deprecated proto but looks identical to +[`CertificateProviderPluginInstance`][CPPI]. They are both based on the notion of CertificateProvider plugin framework +(described later). The field `instance_name` defines a CertificateProvider "instance" that gRPC looks up in the bootstrap +file (described later) to obtain the CertificateProvider configuration. This configuration along with the CertificateProvider +plugin framework enables gRPC to acquire the certificates necessary for the TLS handshake. + +The field [`tls_certificate_provider_instance`][TCPI] (or in its absence the deprecated +field [`tls_certificate_certificate_provider_instance`][TCCPI]) is used for the identity certificate and the +private key. And [`ca_certificate_provider_instance`][CCPI] inside the +[`default_validation_context`][default_validation_context] of [`combined_validation_context`][CVC] +(or in its absence the deprecated field [`validation_context_certificate_provider_instance`][VCCPI1] inside +[`combined_validation_context`][CVC]) is used for the root certificates for validating peer certificates. gRPC does not support the other certificate acquisition mechanisms specified by the following fields: @@ -333,23 +349,26 @@ gRPC does not support the other certificate acquisition mechanisms specified by * [validation_context_sds_secret_config][VAL-SDS] * [validation_context_certificate_provider][VAL-PROVIDER] -When fields of type [`CertificateProviderInstance`][CPI] are present gRPC ignores the respective +When fields of type [`CertificateProviderPluginInstance`][CPPI] (or the deprecated +[`CertificateProviderInstance`][CPI]) are present gRPC ignores the respective unsupported fields but if the unsupported fields are present by themselves gRPC will NACK an update as part of validating all CDS/LDS updates. For example, in [`UpstreamTlsContext`][UTC] (on the client side), the identity certificate is not -needed for the TLS mode, which is indicated by [`tls_certificate_certificate_provider_instance`][TCCPI] -being absent. However in this case if any of the other unsupported identity certificate fields -([tls_certificates][TLS-CERT], [tls_certificate_sds_secret_configs][CERT-SDS], +needed for the TLS mode, which is indicated by the absence of both [`tls_certificate_provider_instance`][TCPI] +and [`tls_certificate_certificate_provider_instance`][TCCPI]. However in this case if any of the other +unsupported identity certificate fields ([tls_certificates][TLS-CERT], [tls_certificate_sds_secret_configs][CERT-SDS], [tls_certificate_certificate_provider][CERT-PROVIDER]) are present then gRPC will NACK a CDS update. -But if [`tls_certificate_certificate_provider_instance`][TCCPI] is present, then the unsupported +But if [`tls_certificate_provider_instance`][TCPI] (or in its absence the deprecated +[`tls_certificate_certificate_provider_instance`][TCCPI]) is present, then the unsupported fields are ignored. This allows a control plane to formulate a single `CommonTlsContext` that works -for both gRPC (which only supports [`CertificateProviderInstance`][CPI]) and Envoy (which does not -support [`CertificateProviderInstance`][CPI]) to achieve consistent security configuration between +for both gRPC (which only supports [`CertificateProviderPluginInstance`][CPPI] or the deprecated +[`CertificateProviderInstance`][CPI]) and Envoy (which supports neither [`CertificateProviderPluginInstance`][CPPI] +nor [`CertificateProviderInstance`][CPI]) to achieve consistent security configuration between gRPC and Envoy. The following fields are unsupported and if present will cause a NACK from gRPC for any update -since ignoring these fields will compromise security: +because ignoring these fields compromises security: * [tls_params][TLS-PARAMS] * [custom_handshaker][CUSTOM-HS] @@ -363,7 +382,7 @@ not take into account whether Xds credentials are in effect for the respective c The field [match_subject_alt_names][] inside [default_validation_context][] is accepted only on the client side i.e. inside `UpstreamTlsContext` and is processed as described [above][server-authz]. If any of the other fields (listed below) are present in [default_validation_context][], the update -is NACKed since ignoring these fields will compromise security: +is NACKed because ignoring these fields compromises security: * `verify_certificate_spki` * `verify_certificate_hash` @@ -378,13 +397,16 @@ The following fields from [default_validation_context][] are ignored: * `allow_expired_certificate` * `trust_chain_verification` -In [`combined_validation_context`][CVC], only [`validation_context_certificate_provider_instance`][VCCPI1] -is accepted. When that field is present, the other fields [`validation_context_certificate_provider`][VCCP1] -and [`validation_context_sds_secret_config`][VCSSC1] are ignored otherwise the presence of those fields will -cause a NACK. +In [`combined_validation_context`][CVC], (other than [default_validation_context][]) only +[`validation_context_certificate_provider_instance`][VCCPI1] is accepted as a deprecated alternative to +[ca_certificate_provider_instance][CCPI]. When one of those fields ([ca_certificate_provider_instance][CCPI] +or [`validation_context_certificate_provider_instance`][VCCPI1]) is present, the other fields +[`validation_context_certificate_provider`][VCCP1] and [`validation_context_sds_secret_config`][VCSSC1] +are ignored otherwise the presence of any of those fields will cause a NACK. [CPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L165 [TCCPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L256 +[TCPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L247 [VCCPI1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L205 [TLS-CERT]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L226 [CERT-SDS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L239 @@ -398,18 +420,21 @@ cause a NACK. [server-authz]: #server-authorization-aka-subject-alt-name-checks [VCCP1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L199 [VCSSC1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L193 +[CCPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L315 +[CPPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L241 ### Certificate Provider Plugin Framework xDS supports many different configurations for endpoints to obtain certificates but gRPC supports only -[`CertificateProviderInstance`][CPI]. In this approach, the control plane tells the xDS client the -[name of a certificate][CERT-NAME] (which is currently ignored) and the ["instance" name][INST-NAME] -of a provider to use to obtain a certificate. This provider [instance name][INST-NAME] is translated -into a provider implementation and a configuration for that implementation using the client's own -configuration instead of being sent by the control plane. This enables flexibility in heterogeneous -deployments where different clients can use different implementations for the same provider instance -name. For example, an on-prem client may get its certificate using a local certificate provider whereas -a client running in cloud may use a cloud-vendor provided implementation to obtain the certificate. +[`CertificateProviderPluginInstance`][CPPI] (or its deprecated version [`CertificateProviderInstance`][CPI]). +In this approach, the control plane tells the xDS client the [name of a certificate][CERT-NAME] (which +is currently ignored) and the ["instance" name][INST-NAME] of a provider to use to obtain a certificate. +This provider [instance name][INST-NAME] is translated into a provider implementation and a configuration +for that implementation using the client's own configuration instead of being sent by the control plane. +This enables flexibility in heterogeneous deployments where different clients can use different +implementations for the same provider instance name. For example, an on-prem client may get its certificate +using a local certificate provider whereas a client running in cloud may use a cloud-vendor provided +implementation to obtain the certificate. gRPC offers a `CertificateProvider` plugin API that can support multiple implementations. The plugin API is not currently public, so applications cannot currently add their own provider implementations although @@ -417,8 +442,8 @@ we might make this API public in the future. However gRPC currently includes a ` implementation - descibed [below][FILE-WATCHER-LINK] - which reads certificates from the local file system. [FILE-WATCHER-LINK]: #file_watcher-certificate-provider -[CERT-NAME]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L180 -[INST-NAME]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L174 +[CERT-NAME]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L253 +[INST-NAME]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L247 Certificate provider plugin instances are configured via the xDS bootstrap file. There is a new top-level field called `"certificate_providers"` whose value is a map (a JSON object). The key From 878817c8505900b5fa7f22ccefd1131128c9f90f Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 12 Aug 2021 11:44:34 -0700 Subject: [PATCH 21/26] update the last updated date and minor typos --- A29-xds-tls-security.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 2b69bd785..7fe216bc2 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -4,7 +4,7 @@ A29: xDS-Based Security for gRPC Clients and Servers * Approver: markdroth * Status: Draft * Implemented in: C-core, Java, and Go -* Last updated: 2021-06-08 +* Last updated: 2021-08-12 * Discussion at: ## Abstract @@ -173,7 +173,7 @@ configuration. See below for [`CommonTlsContext`][CTC-type] processing. A secure client at a minimum requires a CA root certificate to be able to validate the server certificate in the TLS mode and this is provided by [ca_certificate_provider_instance][CCPI] inside the [`default_validation_context`][default_validation_context] of -[combined_validation_context][CVC]. For backward compatibility gRPC will use the deprecated +[combined_validation_context][CVC]. For backward compatibility, gRPC will use the deprecated field [`validation_context_certificate_provider_instance`][VCCPI1] inside [`combined_validation_context`][CVC] if [ca_certificate_provider_instance][CCPI] is not present. If [`UpstreamTlsContext`][UTC] is present but @@ -224,8 +224,9 @@ the check fails. * each SAN entry of type DNS, URI, email and IP address is considered for the below match logic. An IP address is converted to its canonical string representation. For IPv6 this includes [maximum zero compression][zero-compr], [no leading zeros][no-leading-0] -and [lower case][lower-case] e.g. `2001:db8::1` but *not* `2001:DB8:0::01`. -If an entry matches as per this logic, the check completes successfully. +and [lower case][lower-case] e.g. an address like `"2001:DB8:0::01"` will be converted to +`"2001:db8::1"` for matching. If an entry matches as per this logic, the check completes +successfully. * if a SAN entry is empty then the match fails for that entry. From c22f8fe790bef536301222809a334ed02a191b62 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Mon, 23 Aug 2021 18:06:35 -0700 Subject: [PATCH 22/26] address latest review comments --- A29-xds-tls-security.md | 197 ++++++++++++++++++++-------------------- 1 file changed, 101 insertions(+), 96 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 7fe216bc2..472c15c8e 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -147,8 +147,9 @@ Use of XdsServerCredentials: xDS v3 is a pre-requisite for this proposal because the required fields were added to xDS v3. gRPC uses CDS to configure client side security and LDS for server side security as described in the sections below. The sections describe how the CDS or LDS updates are processed by gRPC. Note that gRPC -always validates all security configurations in CDS or LDS regardless of whether an XdsChannelCredentials -or XdsServerCredentials is in force. If validation fails on an update, the update is NACKed. +always validates all security configurations in CDS or LDS regardless of whether the application used +`XdsChannelCredentials` or `XdsServerCredentials`. If validation fails on an update, the update is +NACKed. An unsupported field is normally ignored. However if ignoring a field compromises security, or if the unsupported field affects how we interpret other fields, we NACK the update when the @@ -170,23 +171,29 @@ load balancer policy information down to child policies. [`common_tls_context`][CTC] in the `UpstreamTlsContext` contains the required security configuration. See below for [`CommonTlsContext`][CTC-type] processing. -A secure client at a minimum requires a CA root certificate to be able to validate the server -certificate in the TLS mode and this is provided by [ca_certificate_provider_instance][CCPI] -inside the [`default_validation_context`][default_validation_context] of -[combined_validation_context][CVC]. For backward compatibility, gRPC will use the deprecated -field [`validation_context_certificate_provider_instance`][VCCPI1] inside -[`combined_validation_context`][CVC] if [ca_certificate_provider_instance][CCPI] is not -present. If [`UpstreamTlsContext`][UTC] is present but -[`combined_validation_context`][CVC] is not present or neither of -[ca_certificate_provider_instance][CCPI] and [`validation_context_certificate_provider_instance`][VCCPI1] -is set, then gRPC will NACK the CDS update. The client identity certificate is configured via -[`tls_certificate_provider_instance`][TCPI] (or the deprecated -[`tls_certificate_certificate_provider_instance`][TCCPI] if [`tls_certificate_provider_instance`][TCPI] -is not set). Note that the identity certificate on the client side is optional. The -client certificate is sent to the server if the server requests or requires it in the -TLS handshake. If the server requires the client certificate but is not configured on the -client side then the TLS handshake will fail because of the client's inability to send the -certificate. +A secure client performs validation of the server's certificate. This validation is configured +via the `CertificateValidationContext` message, which is present in either the +[`validation_context`][validation_context] field or in the +[`default_validation_context`][default_validation_context] field inside of the +[`combined_validation_context`][CVC] field. If neither of those fields are set, gRPC will NACK +the CDS update. + +At minimum, a secure client requires a CA root certificate to be able to validate the server +certificate. The CA root certificate is obtained using the certificate provider instance configured +via the [`ca_certificate_provider_instance`][CCPI] field of the `CertificateValidationContext` +message. If this field is not present, or if it specifies a certificate provider instance that +is not configured in the bootstrap file, gRPC will NACK the CDS update. + +The client's identity certificate, if configured, is obtained using the certificate provider instance +configured via the [`tls_certificate_provider_instance`][TCPI] field of the `CommonTlsContext` message. +If this field is set, the client certificate is sent to the server if the server requests or requires +it in the TLS handshake. If the server requires the client certificate but is not configured on the +client side then the TLS handshake will fail because of the client's inability to send the certificate. +If this field specifies a certificate provider instance that is not configured in the bootstrap file, +gRPC will NACK the CDS update. Note that gRPC does not support any of the other mechanisms in xDS for +configuring the client's identity certificate. If the [`tls_certificate_provider_instance`][TCPI] field +is unset but either of the [`tls_certificates`][TLS-CERT] or [`tls_certificate_sds_secret_configs`][CERT-SDS] +fields are set, gRPC will NACK the CDS update. The following fields in a CDS update are ignored: @@ -210,10 +217,9 @@ a server for the connection as described below. This check is in lieu of the canonical [hostname check in Web PKI][RFC6125-6]. If [`match_subject_alt_names`][match_subject_alt_names] in -[`default_validation_context`][default_validation_context] of -[combined_validation_context][CVC] of the received `UpstreamTlsContext` is populated -then gRPC checks the SAN entries in the leaf server certificate against the -`match_subject_alt_names` values as follows: +the `CertificateValidationContext` is populated then gRPC checks the SAN entries +in the leaf server certificate against the +[`match_subject_alt_names`][match_subject_alt_names] values as follows: * if the `match_subject_alt_names` list is empty then there is nothing to match and the check succeeds. @@ -254,6 +260,7 @@ implementation through the `SslContext` provided to the client sub-channel. [no-leading-0]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.1 [lower-case]: https://datatracker.ietf.org/doc/html/rfc5952#section-2.3 [DNS-wildcard]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L392-L394 +[validation_context]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L261 #### LDS for Server Side Security @@ -275,22 +282,31 @@ is not present) then gRPC uses the fallback credentials for the incoming connect [`common_tls_context`][CTC1] in the `DownstreamTlsContext` contains the required security configuration. See below for [`CommonTlsContext`][CTC-type] processing. -A secure server at a minimum requires an identity certificate which is provided -by [`tls_certificate_provider_instance`][TCPI] (or in its absence the deprecated -field [`tls_certificate_certificate_provider_instance`][TCCPI]). If both fields are -empty, gRPC will NACK an update as part of validating all LDS updates. If -[ca_certificate_provider_instance][CCPI] inside the -[`default_validation_context`][default_validation_context] of [combined_validation_context][CVC] -(or in its absence the deprecated field -[`validation_context_certificate_provider_instance`][VCCPI1] inside -[`combined_validation_context`][CVC]) is provided then the server will request -the client certificate. When [`require_client_certificate`][RCC] is `true`, -gRPC requires the client certificate and will reject a connection without a valid -client certificate. When [`require_client_certificate`][RCC] is `true`, the -[ca_certificate_provider_instance][CCPI] field (or in its absence -[`validation_context_certificate_provider_instance`][VCCPI1]) should be -present otherwise gRPC will NACK an LDS update as part of validating all LDS -updates. +The server's identity certificate is obtained using the certificate provider instance +configured via the [`tls_certificate_provider_instance`][TCPI] field of the +`CommonTlsContext` message. If this field is not present, or if it specifies a certificate +provider instance that is not configured in the bootstrap file, gRPC will NACK the LDS +update. + +If a secure server is configured for mTLS, it will need configuration for how to validate +the client's certificate. This validation is configured via the `CertificateValidationContext` +message, which is present in either the [`validation_context`][validation_context] field or +in the [`default_validation_context`][default_validation_context] field inside of the +[`combined_validation_context`][CVC] field. If neither of those fields are set, the server +will not request the client's certificate during the TLS handshake (i.e., it will use TLS +instead of mTLS). + +If a `CertificateValidationContext` is provided, then the server requires a CA root certificate +to be able to validate the client certificate. The CA root certificate is obtained using the +certificate provider instance configured via the [`ca_certificate_provider_instance`][CCPI] +field. If this field is not present, or if it specifies a certificate provider instance that +is not configured in the bootstrap file, gRPC will NACK the LDS update. + +If the [`require_client_certificate`][RCC] field in the `DownstreamTlsContext` message is set +to true, gRPC requires the client certificate and will reject a connection without a client +certificate that is successfully validated as per the `CertificateValidationContext`. Note +that if [`require_client_certificate`][RCC] is true, and if no `CertificateValidationContext` +is provided, gRPC will NACK the LDS resource. The following fields in an LDS update are ignored: @@ -302,8 +318,18 @@ The following fields in an LDS update are ignored: If any of the following fields are present, gRPC will NACK an LDS update as part of validating all LDS updates: -* [require_sni][REQ-SNI] -* [ocsp_staple_policy][OCSP-STAPLE-POLICY]: any value other than `LENIENT_STAPLING` causes NACK. +* [require_sni][REQ-SNI]: when this is set to `true`, it requires the server to +["reject connections without a valid and matching SNI"][sni-comment]. However SNI is +almost always used for "name-based virtual hosting" web-servers and is not applicable +to gRPC. Silently ignoring the `true` value will result into gRPC not rejecting connections +without a valid and matching SNI thereby making the implementation less secure than +what the control plane intended, hence gRPC will NACK such an LDS update. + +* [ocsp_staple_policy][OCSP-STAPLE-POLICY]: Instead of mandating the implementation of +[`STRICT_STAPLING`][STRICT_STAPLING] and [`MUST_STAPLE`][MUST_STAPLE] in gRPC, +we NACK any value other than [`LENIENT_STAPLING`][LENIENT_STAPLING] because ignoring +the unsupported values would make the implementation less secure than what the control +plane intended. [A36]: A36-xds-for-servers.md [filter-chains]: https://github.com/envoyproxy/envoy/blob/45ec050f91407147ed53a999434b09ef77590177/api/envoy/config/listener/v3/listener.proto#L120 @@ -321,54 +347,38 @@ part of validating all LDS updates: [DIS-STATELESS-SESS-RES]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L109 [SESSION-TIMEOUT]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L116 [OCSP-STAPLE-POLICY]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L124 +[sni-comment]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L90 +[STRICT_STAPLING]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L73 +[MUST_STAPLE]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L80 +[LENIENT_STAPLING]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L65 #### CommonTlsContext Processing `CommonTlsContext` is present in both the `UpstreamTlsContext` and `DownstreamTlsContext` protos and contains the certificate and key configuration information needed on the client and server side respectively. The configuration tells gRPC how to obtain certificates and the keys for the TLS handshake. Although there are various ways to obtain -certificates as per this proto (which are supported by Envoy), gRPC supports only two of them. The preferred mechanism -is the [`CertificateProviderPluginInstance`][CPPI] proto and the less preferred mechanism is -[`CertificateProviderInstance`][CPI] which is a deprecated proto but looks identical to -[`CertificateProviderPluginInstance`][CPPI]. They are both based on the notion of CertificateProvider plugin framework -(described later). The field `instance_name` defines a CertificateProvider "instance" that gRPC looks up in the bootstrap -file (described later) to obtain the CertificateProvider configuration. This configuration along with the CertificateProvider -plugin framework enables gRPC to acquire the certificates necessary for the TLS handshake. - -The field [`tls_certificate_provider_instance`][TCPI] (or in its absence the deprecated -field [`tls_certificate_certificate_provider_instance`][TCCPI]) is used for the identity certificate and the -private key. And [`ca_certificate_provider_instance`][CCPI] inside the -[`default_validation_context`][default_validation_context] of [`combined_validation_context`][CVC] -(or in its absence the deprecated field [`validation_context_certificate_provider_instance`][VCCPI1] inside -[`combined_validation_context`][CVC]) is used for the root certificates for validating peer certificates. +certificates as per this proto (which are supported by Envoy), gRPC supports only one of them and that is +the [`CertificateProviderPluginInstance`][CPPI] proto. This proto is based on the notion of the CertificateProvider +plugin framework (described later). The field `instance_name` defines a CertificateProvider "instance" that gRPC looks +up in the bootstrap file (described later) to obtain the CertificateProvider configuration. This configuration along +with the CertificateProvider plugin framework enables gRPC to acquire the certificates necessary for the TLS handshake. + +The field [`tls_certificate_provider_instance`][TCPI] is used for the identity certificate and the +private key. And [`ca_certificate_provider_instance`][CCPI] inside a `CertificateValidationContext` +is used for the root certificates for validating peer certificates. gRPC does not support the other certificate acquisition mechanisms specified by the following fields: -* [tls_certificates][TLS-CERT] -* [tls_certificate_sds_secret_configs][CERT-SDS] -* [tls_certificate_certificate_provider][CERT-PROVIDER] -* [validation_context_sds_secret_config][VAL-SDS] -* [validation_context_certificate_provider][VAL-PROVIDER] - -When fields of type [`CertificateProviderPluginInstance`][CPPI] (or the deprecated -[`CertificateProviderInstance`][CPI]) are present gRPC ignores the respective -unsupported fields but if the unsupported fields are present by themselves gRPC will NACK an update -as part of validating all CDS/LDS updates. - -For example, in [`UpstreamTlsContext`][UTC] (on the client side), the identity certificate is not -needed for the TLS mode, which is indicated by the absence of both [`tls_certificate_provider_instance`][TCPI] -and [`tls_certificate_certificate_provider_instance`][TCCPI]. However in this case if any of the other -unsupported identity certificate fields ([tls_certificates][TLS-CERT], [tls_certificate_sds_secret_configs][CERT-SDS], -[tls_certificate_certificate_provider][CERT-PROVIDER]) are present then gRPC will NACK a CDS update. -But if [`tls_certificate_provider_instance`][TCPI] (or in its absence the deprecated -[`tls_certificate_certificate_provider_instance`][TCCPI]) is present, then the unsupported -fields are ignored. This allows a control plane to formulate a single `CommonTlsContext` that works -for both gRPC (which only supports [`CertificateProviderPluginInstance`][CPPI] or the deprecated -[`CertificateProviderInstance`][CPI]) and Envoy (which supports neither [`CertificateProviderPluginInstance`][CPPI] -nor [`CertificateProviderInstance`][CPI]) to achieve consistent security configuration between -gRPC and Envoy. - -The following fields are unsupported and if present will cause a NACK from gRPC for any update +* [tls_certificates][TLS-CERT]: if this is present but [`tls_certificate_provider_instance`][TCPI] is +not present, then gRPC will NACK the update. +* [tls_certificate_sds_secret_configs][CERT-SDS]: similar to above, if this is present but +[`tls_certificate_provider_instance`][TCPI] is not present, then gRPC will NACK the update. +* [validation_context_sds_secret_config][VAL-SDS]: if this is present but a +`CertificateValidationContext` (either the [`validation_context`][validation_context] field or +the [`default_validation_context`][default_validation_context] field inside of the +[`combined_validation_context`][CVC]) is not present, then gRPC will NACK the update. + +The following fields are unsupported and if present will cause a NACK from gRPC because ignoring these fields compromises security: * [tls_params][TLS-PARAMS] @@ -379,11 +389,13 @@ on the client side (inside [`UpstreamTlsContext`][UTC]) is ignored if present. The processing and parsing of `CommonTlsContext` inside any particular CDS or LDS response does not take into account whether Xds credentials are in effect for the respective channel or server. -[`combined_validation_context`][CVC] is validated in any CDS/LDS update as follows: -The field [match_subject_alt_names][] inside [default_validation_context][] is accepted only on -the client side i.e. inside `UpstreamTlsContext` and is processed as described [above][server-authz]. -If any of the other fields (listed below) are present in [default_validation_context][], the update -is NACKed because ignoring these fields compromises security: +A `CertificateValidationContext` (either the [`validation_context`][validation_context] field or +the [`default_validation_context`][default_validation_context] field inside of the +[`combined_validation_context`][CVC]) is validated in any CDS/LDS update as follows: +The field [match_subject_alt_names][] is accepted only on the client side i.e. inside +`UpstreamTlsContext` and is processed as described [above][server-authz]. If any of the other +fields (listed below) are present, the update is NACKed because ignoring these fields compromises +security: * `verify_certificate_spki` * `verify_certificate_hash` @@ -391,20 +403,13 @@ is NACKed because ignoring these fields compromises security: * `crl` * `custom_validator_config` -The following fields from [default_validation_context][] are ignored: +The following fields from `CertificateValidationContext` are ignored: * `trusted_ca` * `watched_directory` * `allow_expired_certificate` * `trust_chain_verification` -In [`combined_validation_context`][CVC], (other than [default_validation_context][]) only -[`validation_context_certificate_provider_instance`][VCCPI1] is accepted as a deprecated alternative to -[ca_certificate_provider_instance][CCPI]. When one of those fields ([ca_certificate_provider_instance][CCPI] -or [`validation_context_certificate_provider_instance`][VCCPI1]) is present, the other fields -[`validation_context_certificate_provider`][VCCP1] and [`validation_context_sds_secret_config`][VCSSC1] -are ignored otherwise the presence of any of those fields will cause a NACK. - [CPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L165 [TCCPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L256 [TCPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L247 @@ -428,9 +433,9 @@ are ignored otherwise the presence of any of those fields will cause a NACK. xDS supports many different configurations for endpoints to obtain certificates but gRPC supports only [`CertificateProviderPluginInstance`][CPPI] (or its deprecated version [`CertificateProviderInstance`][CPI]). -In this approach, the control plane tells the xDS client the [name of a certificate][CERT-NAME] (which -is currently ignored) and the ["instance" name][INST-NAME] of a provider to use to obtain a certificate. -This provider [instance name][INST-NAME] is translated into a provider implementation and a configuration +In this approach, the control plane tells the xDS client the [name of a certificate][CERT-NAME] and the +["instance" name][INST-NAME] of a provider to use to obtain a certificate. This provider +[instance name][INST-NAME] is translated into a provider implementation and a configuration for that implementation using the client's own configuration instead of being sent by the control plane. This enables flexibility in heterogeneous deployments where different clients can use different implementations for the same provider instance name. For example, an on-prem client may get its certificate From 356b843b6c32c37c76550bf9c13f9ebba54e9e9b Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Mon, 23 Aug 2021 22:58:18 -0700 Subject: [PATCH 23/26] address latest review comments-2 --- A29-xds-tls-security.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 472c15c8e..249d5ef3b 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -410,29 +410,22 @@ The following fields from `CertificateValidationContext` are ignored: * `allow_expired_certificate` * `trust_chain_verification` -[CPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L165 -[TCCPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L256 [TCPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L247 -[VCCPI1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L205 [TLS-CERT]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L226 [CERT-SDS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L239 -[CERT-PROVIDER]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L251 [VAL-SDS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L265 -[VAL-PROVIDER]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L278 [TLS-PARAMS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L212 [CUSTOM-HS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L301 [ALPN-PROTOCOLS]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L297 [UTC]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L26 [server-authz]: #server-authorization-aka-subject-alt-name-checks -[VCCP1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L199 -[VCSSC1]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L193 [CCPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L315 [CPPI]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/common.proto#L241 ### Certificate Provider Plugin Framework xDS supports many different configurations for endpoints to obtain certificates but gRPC supports only -[`CertificateProviderPluginInstance`][CPPI] (or its deprecated version [`CertificateProviderInstance`][CPI]). +[`CertificateProviderPluginInstance`][CPPI]. In this approach, the control plane tells the xDS client the [name of a certificate][CERT-NAME] and the ["instance" name][INST-NAME] of a provider to use to obtain a certificate. This provider [instance name][INST-NAME] is translated into a provider implementation and a configuration From ce24e588d4b260c2032526fa9e89917658299ea7 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Tue, 24 Aug 2021 15:53:55 -0700 Subject: [PATCH 24/26] address the latest review comments-3 --- A29-xds-tls-security.md | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 249d5ef3b..810543036 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -290,11 +290,13 @@ update. If a secure server is configured for mTLS, it will need configuration for how to validate the client's certificate. This validation is configured via the `CertificateValidationContext` -message, which is present in either the [`validation_context`][validation_context] field or -in the [`default_validation_context`][default_validation_context] field inside of the -[`combined_validation_context`][CVC] field. If neither of those fields are set, the server -will not request the client's certificate during the TLS handshake (i.e., it will use TLS -instead of mTLS). +message, which comes from one of the options in the [`validation_context_type`][validation_context_type] oneof. +If the [`validation_context_sds_secret_config`][VAL-SDS] field is set, gRPC will NACK the CDS update, +since we do not support SDS. If the [`validation_context`][validation_context] field is set, we get +the `CertificateValidationContext` from there. If the [`combined_validation_context`][CVC] field is +set, we get the `CertificateValidationContext` from its [`default_validation_context`][default_validation_context] +field. If there is no `CertificateValidationContext`, then the server will not request the client's +certificate during the TLS handshake (i.e., it will use TLS instead of mTLS). If a `CertificateValidationContext` is provided, then the server requires a CA root certificate to be able to validate the client certificate. The CA root certificate is obtained using the @@ -351,6 +353,7 @@ plane intended. [STRICT_STAPLING]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L73 [MUST_STAPLE]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L80 [LENIENT_STAPLING]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L65 +[validation_context_type]: https://github.com/envoyproxy/envoy/blob/b29d6543e7568a8a3e772c7909a1daa182acc670/api/envoy/extensions/transport_sockets/tls/v3/tls.proto#L259 #### CommonTlsContext Processing @@ -367,17 +370,6 @@ The field [`tls_certificate_provider_instance`][TCPI] is used for the identity c private key. And [`ca_certificate_provider_instance`][CCPI] inside a `CertificateValidationContext` is used for the root certificates for validating peer certificates. -gRPC does not support the other certificate acquisition mechanisms specified by the following fields: - -* [tls_certificates][TLS-CERT]: if this is present but [`tls_certificate_provider_instance`][TCPI] is -not present, then gRPC will NACK the update. -* [tls_certificate_sds_secret_configs][CERT-SDS]: similar to above, if this is present but -[`tls_certificate_provider_instance`][TCPI] is not present, then gRPC will NACK the update. -* [validation_context_sds_secret_config][VAL-SDS]: if this is present but a -`CertificateValidationContext` (either the [`validation_context`][validation_context] field or -the [`default_validation_context`][default_validation_context] field inside of the -[`combined_validation_context`][CVC]) is not present, then gRPC will NACK the update. - The following fields are unsupported and if present will cause a NACK from gRPC because ignoring these fields compromises security: @@ -392,10 +384,10 @@ not take into account whether Xds credentials are in effect for the respective c A `CertificateValidationContext` (either the [`validation_context`][validation_context] field or the [`default_validation_context`][default_validation_context] field inside of the [`combined_validation_context`][CVC]) is validated in any CDS/LDS update as follows: -The field [match_subject_alt_names][] is accepted only on the client side i.e. inside -`UpstreamTlsContext` and is processed as described [above][server-authz]. If any of the other -fields (listed below) are present, the update is NACKed because ignoring these fields compromises -security: +The field [match_subject_alt_names][] is used only on the client side i.e. inside +`UpstreamTlsContext` and is processed as described [above][server-authz]; it is ignored on the +server side. If any of the other fields (listed below) are present, the update is NACKed because +ignoring these fields compromises security: * `verify_certificate_spki` * `verify_certificate_hash` From e9f99d562aff8e4a931be1ee2124a5b461dab96b Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 26 Aug 2021 11:20:01 -0700 Subject: [PATCH 25/26] clarify the match_subject_alt_names semantics on the server side --- A29-xds-tls-security.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 810543036..81a82c3db 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -384,10 +384,10 @@ not take into account whether Xds credentials are in effect for the respective c A `CertificateValidationContext` (either the [`validation_context`][validation_context] field or the [`default_validation_context`][default_validation_context] field inside of the [`combined_validation_context`][CVC]) is validated in any CDS/LDS update as follows: -The field [match_subject_alt_names][] is used only on the client side i.e. inside -`UpstreamTlsContext` and is processed as described [above][server-authz]; it is ignored on the -server side. If any of the other fields (listed below) are present, the update is NACKed because -ignoring these fields compromises security: +The field [match_subject_alt_names][] is used on the client side i.e. inside `UpstreamTlsContext` +as described [above][server-authz]. On the server side an implementation may support this field +and its semantics, or NACK the update it if it doesn't. If any of the other fields (listed below) +are present, the update is NACKed because ignoring these fields compromises security: * `verify_certificate_spki` * `verify_certificate_hash` From 36812104c8358fcb8f9ddba330be557312574676 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Mon, 30 Aug 2021 11:39:33 -0700 Subject: [PATCH 26/26] make the grfc final --- A29-xds-tls-security.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/A29-xds-tls-security.md b/A29-xds-tls-security.md index 81a82c3db..f4b16c281 100644 --- a/A29-xds-tls-security.md +++ b/A29-xds-tls-security.md @@ -2,10 +2,10 @@ A29: xDS-Based Security for gRPC Clients and Servers ---- * Author(s): [Sanjay M. Pujare](https://github.com/sanjaypujare), [Easwar Swaminathan](https://github.com/easwars), [Yash Tibrewal](https://github.com/yashykt) * Approver: markdroth -* Status: Draft +* Status: Final * Implemented in: C-core, Java, and Go -* Last updated: 2021-08-12 -* Discussion at: +* Last updated: 2021-08-30 +* Discussion at: https://groups.google.com/g/grpc-io/c/4IwVLPeTAe4/m/ng9w3D0XBgAJ ## Abstract