Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions api/envoy/config/core/v3/base.proto
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,13 @@ message HeaderMap {
repeated HeaderValue headers = 1;
}

// A directory that is watched for changes, e.g. by inotify on Linux. Move/rename
// events inside this directory trigger the watch.
message WatchedDirectory {
// Directory path to watch.
string path = 1 [(validate.rules).string = {min_len: 1}];
}
Comment thread
htuch marked this conversation as resolved.
Outdated

// Data source consisting of either a file or an inline value.
message DataSource {
option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.core.DataSource";
Expand Down
10 changes: 10 additions & 0 deletions api/envoy/config/core/v4alpha/base.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 27 additions & 2 deletions api/envoy/extensions/transport_sockets/tls/v3/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,32 @@ message PrivateKeyProvider {
}
}

// [#next-free-field: 7]
// [#next-free-field: 8]
message TlsCertificate {
option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.auth.TlsCertificate";

// The TLS certificate chain.
//
// If *certificate_chain* is a filesystem path, a watch will be added to the
// parent directory for any file moves to support rotation. This currently
// only applies to dynamic secrets, when the *TlsCertificate* is delivered via
// SDS.
config.core.v3.DataSource certificate_chain = 1;

// The TLS private key.
//
// If *private_key* is a filesystem path, a watch will be added to the parent
// directory for any file moves to support rotation. This currently only
// applies to dynamic secrets, when the *TlsCertificate* is delivered via SDS.
config.core.v3.DataSource private_key = 2 [(udpa.annotations.sensitive) = true];

// If specified, updates of file-based *certificate_chain* and *private_key*
// sources will be triggered by this watch. The certificate/key pair will be
// read together and validated for atomic read consistency (i.e. no intervening
// modification occurred between cert/key read, verified by file hash
// comparisons).
Comment thread
htuch marked this conversation as resolved.
Outdated
config.core.v3.WatchedDirectory watched_directory = 7;

// BoringSSL private key method provider. This is an alternative to :ref:`private_key
// <envoy_api_field_extensions.transport_sockets.tls.v3.TlsCertificate.private_key>` field. This can't be
// marked as ``oneof`` due to API compatibility reasons. Setting both :ref:`private_key
Expand Down Expand Up @@ -191,7 +207,7 @@ message TlsSessionTicketKeys {
[(validate.rules).repeated = {min_items: 1}, (udpa.annotations.sensitive) = true];
}

// [#next-free-field: 11]
// [#next-free-field: 12]
message CertificateValidationContext {
option (udpa.annotations.versioning).previous_message_type =
"envoy.api.v2.auth.CertificateValidationContext";
Expand Down Expand Up @@ -233,8 +249,17 @@ message CertificateValidationContext {
//
// See :ref:`the TLS overview <arch_overview_ssl_enabling_verification>` for a list of common
// system CA locations.
//
// If *trusted_ca* is a filesystem path, a watch will be added to the parent
// directory for any file moves to support rotation. This currently only
// applies to dynamic secrets, when the *CertificateValidationContext* is
// delivered via SDS.
config.core.v3.DataSource trusted_ca = 1;

// If specified, updates of a file-based *trusted_ca* source will be triggered
// by this watch.
config.core.v3.WatchedDirectory watched_directory = 11;
Comment thread
htuch marked this conversation as resolved.
Comment on lines +263 to +269

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't understand how this does anything if there is only a single file above? What's the utility?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's say you have a trusted CA files /foo/bar/baz/ca.pem. By default, envoy watches /foo/bar/baz. If you want to reload when baz is atomically moved, you need to set the watch on /foo/bar. This is what this field allows.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I think having a concrete example might help for this stuff (or ref link back to the docs where you have the example) as it was pretty hard for me to understand the difference.


// An optional list of base64-encoded SHA-256 hashes. If specified, Envoy will verify that the
// SHA-256 of the DER-encoded Subject Public Key Information (SPKI) of the presented certificate
// matches one of the specified values.
Expand Down
29 changes: 27 additions & 2 deletions api/envoy/extensions/transport_sockets/tls/v4alpha/common.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions docs/root/configuration/security/secret.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,39 @@ Path to CA certificate bundle for validating the xDS server certificate is given
trusted_ca:
filename: /certs/cacert.pem

In the above example, a watch will be established on ``/certs``. File movement in this directory
will trigger an update. An alternative common key rotation scheme that provides improved atomicity
is to establish an active symlink ``/certs/current`` and use an atomic move operation to replace the
symlink. The watch in this case needs to be on the certificate's grandparent directory. Envoy
supports this scheme via the use of *watched_path*. Continuing the above examples:

.. code-block:: yaml

resources:
- "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret"
tls_certificate:
certificate_chain:
filename: /certs/current/sds_cert.pem
private_key:
filename: /certs/current/sds_key.pem
watched_directory:
path: /certs

.. code-block:: yaml

resources:
- "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret"
validation_context:
trusted_ca:
filename: /certs/current/cacert.pem
watched_directory:
path: /certs

Secret rotation can be performed with:

.. code-block:: bash

ln -s <path to new secrets> /certs/new && mv -Tf /certs/new /certs/current

Statistics
----------
Expand Down
3 changes: 3 additions & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ New Features
* overload: add :ref:`envoy.overload_actions.reduce_timeouts <config_overload_manager_overload_actions>` overload action to enable scaling timeouts down with load.
* ratelimit: added support for use of various :ref:`metadata <envoy_v3_api_field_config.route.v3.RateLimit.Action.metadata>` as a ratelimit action.
* ratelimit: added :ref:`disable_x_envoy_ratelimited_header <envoy_v3_api_msg_extensions.filters.http.ratelimit.v3.RateLimit>` option to disable `X-Envoy-RateLimited` header.
* sds: improved support for atomic :ref:`key rotations <xds_certificate_rotation>` and added configurable rotation triggers for
:ref:`TlsCertificate <envoy_v3_api_field_extensions.transport_sockets.tls.v3.TlsCertificate.watched_directory>` and
:ref:`CertificateValidationContext <envoy_v3_api_field_extensions.transport_sockets.tls.v3.CertificateValidationContext.watched_directory>`.
* tcp: added a new :ref:`envoy.overload_actions.reject_incoming_connections <config_overload_manager_overload_actions>` action to reject incoming TCP connections.
* tls: added support for RSA certificates with 4096-bit keys in FIPS mode.
* tracing: added SkyWalking tracer.
Expand Down
7 changes: 7 additions & 0 deletions generated_api_shadow/envoy/config/core/v3/base.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions generated_api_shadow/envoy/config/core/v4alpha/base.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions source/common/config/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,17 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "watched_directory_lib",
srcs = ["watched_directory.cc"],
hdrs = ["watched_directory.h"],
deps = [
"//include/envoy/event:dispatcher_interface",
"//include/envoy/filesystem:watcher_interface",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
)

envoy_cc_library(
name = "well_known_names",
srcs = ["well_known_names.cc"],
Expand Down
14 changes: 14 additions & 0 deletions source/common/config/watched_directory.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "common/config/watched_directory.h"

namespace Envoy {
namespace Config {

WatchedDirectory::WatchedDirectory(const envoy::config::core::v3::WatchedDirectory& config,
Event::Dispatcher& dispatcher) {
watcher_ = dispatcher.createFilesystemWatcher();
watcher_->addWatch(absl::StrCat(config.path(), "/"), Filesystem::Watcher::Events::MovedTo,
[this](uint32_t) { cb_(); });
}

} // namespace Config
} // namespace Envoy
Loading