密鑰探索服務 (SDS)
TLS 憑證 (密鑰) 可以在 bootstrap.static_resource secrets 中指定。但它們也可以透過密鑰探索服務 (SDS) 遠端擷取。
SDS 最重要的優點是簡化憑證管理。如果沒有此功能,在 k8s 部署中,憑證必須建立為密鑰並掛載到 Proxy 容器中。如果憑證過期,則需要更新密鑰並重新部署 Proxy 容器。透過 SDS,中央 SDS 伺服器會將憑證推送至所有 Envoy 實例。如果憑證過期,伺服器只會將新憑證推送至 Envoy 實例,Envoy 會立即使用新憑證而無需重新部署。
如果需要透過 SDS 遠端擷取監聽器伺服器憑證,則在擷取憑證之前,它不會被標記為作用中,其連接埠將不會開啟。如果 Envoy 因連線失敗或錯誤的回應資料而無法擷取憑證,監聽器將會被標記為作用中,並且連接埠將會開啟,但與該連接埠的連線將會重設。
上游叢集的處理方式類似,如果需要透過 SDS 遠端擷取叢集用戶端憑證,則在擷取憑證之前,它不會被標記為作用中且不會使用。如果 Envoy 因連線失敗或錯誤的回應資料而無法擷取憑證,叢集將會被標記為作用中,可以用來處理請求,但路由到該叢集的請求將會被拒絕。
如果靜態叢集正在使用 SDS,並且需要定義 SDS 叢集 (除非使用不需要叢集的 Google gRPC),則必須在使用它的靜態叢集之前定義 SDS 叢集。
Envoy Proxy 和 SDS 伺服器之間的連線必須安全。一種選項是在同一主機上執行 SDS 伺服器,並使用 Unix 網域套接字進行連線。否則,連線需要 Proxy 和 SDS 伺服器之間具有驗證的 TLS。目前用於驗證的憑證類型有:
mTLS – 在這種情況下,必須靜態組態 SDS 連線的用戶端憑證。
AWS IAM SigV4
SDS 伺服器
SDS 伺服器需要實作 gRPC 服務 SecretDiscoveryService。它遵循與其他 xDS 相同的協定。
SDS 組態
SdsSecretConfig 用於指定密鑰。其 name 欄位為必填欄位。如果其 sds_config 欄位為空,則 name 欄位會指定 bootstrap static_resource secrets 中的密鑰。否則,它會將 SDS 伺服器指定為 ConfigSource。SDS 服務僅支援 gRPC,因此其 api_config_source 必須指定 grpc_service。
SdsSecretConfig 用於 CommonTlsContext 中的兩個欄位。第一個欄位是 tls_certificate_sds_secret_configs,用於使用 SDS 取得 TlsCertificate。第二個欄位是 validation_context_sds_secret_config,用於使用 SDS 取得 CertificateValidationContext。
金鑰輪換
通常較佳的方式是透過 gRPC SDS 執行金鑰輪換,但是當這不可能或不想要時 (例如,在 SDS 憑證的開機期間),當密鑰參照檔案系統路徑時,SDS 允許檔案系統輪換。目前支援以下密鑰類型:
預設情況下,會監看包含密鑰的目錄以取得檔案系統移動事件。例如,位於 /foo/bar/baz/cert.pem
的金鑰或受信任 CA 憑證將會在 /foo/bar/baz
中監看。可以透過在 TlsCertificate 和 CertificateValidationContext 中指定 watched_directory 路徑,來明確控制監看的目錄。這允許在路徑前置詞中建立監看,例如 /foo/bar
;在實作常見金鑰輪換配置時,此功能非常有用。
下方提供金鑰輪換的範例 範例。
範例一:static_resource
此範例示範如何在 static_resource 中組態密鑰
static_resources:
secrets:
- name: server_cert
tls_certificate:
certificate_chain:
filename: certs/servercert.pem
private_key:
filename: certs/serverkey.pem
- name: client_cert
tls_certificate:
certificate_chain:
filename: certs/clientcert.pem
private_key:
filename: certs/clientkey.pem
- name: validation_context
validation_context:
trusted_ca:
filename: certs/cacert.pem
verify_certificate_hash:
E0:F3:C8:CE:5E:2E:A3:05:F0:70:1F:F5:12:E3:6E:2E:97:92:82:84:A2:28:BC:F7:73:32:D3:39:30:A1:B6:FD
clusters:
- connect_timeout: 0.25s
load_assignment:
cluster_name: local_service_tls
...
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
tls_certificate_sds_secret_configs:
- name: client_cert
listeners:
....
filter_chains:
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificate_sds_secret_configs:
- name: server_cert
validation_context_sds_secret_config:
name: validation_context
在此範例中,憑證在 bootstrap static_resource 中指定,不會遠端擷取。在組態中,secrets 靜態資源具有 3 個密鑰:client_cert、server_cert 和 validation_context。在叢集組態中,其中一個主機在其 tls_certificate_sds_secret_configs 中使用 client_cert。在監聽器區段中,其中一個在其 tls_certificate_sds_secret_configs 中使用 server_cert,並在其 validation_context_sds_secret_config 中使用 validation_context。
範例二:SDS 伺服器
此範例示範如何組態從遠端 SDS 伺服器擷取的密鑰
1node:
2 cluster: envoy_cluster
3 id: envoy_node
4
5static_resources:
6 listeners:
7 - name: listener_0
8 address:
9 socket_address:
10 address: 0.0.0.0
11 port_value: 8000
12 filter_chains:
13 - transport_socket:
14 name: envoy.transport_sockets.tls
15 typed_config:
16 "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
17 common_tls_context:
18 tls_certificate_sds_secret_configs:
19 - name: server_cert
20 sds_config:
21 api_config_source:
22 api_type: GRPC
23 grpc_services:
24 - envoy_grpc:
25 cluster_name: sds_server_mtls
26 validation_context_sds_secret_config:
27 name: validation_context
28 sds_config:
29 api_config_source:
30 api_type: GRPC
31 grpc_services:
32 - envoy_grpc:
33 cluster_name: sds_server_uds
34 clusters:
35 - name: sds_server_mtls
36 typed_extension_protocol_options:
37 envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
38 "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
39 explicit_http_config:
40 http2_protocol_options: {}
41 load_assignment:
42 cluster_name: sds_server_mtls
43 endpoints:
44 - lb_endpoints:
45 - endpoint:
46 address:
47 socket_address:
48 address: 127.0.0.1
49 port_value: 8234
50 transport_socket:
51 name: envoy.transport_sockets.tls
52 typed_config:
53 "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
54 common_tls_context:
55 tls_certificates:
56 - certificate_chain:
57 filename: certs/servercert.pem
58 private_key:
59 filename: certs/serverkey.pem
60 - name: sds_server_uds
61 typed_extension_protocol_options:
62 envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
63 "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
64 explicit_http_config:
65 http2_protocol_options: {}
66 load_assignment:
67 cluster_name: sds_server_uds
68 endpoints:
69 - lb_endpoints:
70 - endpoint:
71 address:
72 pipe:
73 path: /tmp/uds_path
74 - name: example_cluster
75 load_assignment:
76 cluster_name: local_service_tls
77 endpoints:
78 - lb_endpoints:
79 - endpoint:
80 address:
81 socket_address:
82 address: 127.0.0.1
83 port_value: 8443
84 transport_socket:
85 name: envoy.transport_sockets.tls
86 typed_config:
87 "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
88 common_tls_context:
89 tls_certificate_sds_secret_configs:
90 - name: client_cert
91 sds_config:
92 api_config_source:
93 api_type: GRPC
94 grpc_services:
95 - google_grpc:
96 target_uri: unix:/tmp/uds_path
97 stat_prefix: sds_uds_server
為了說明,以上範例使用三種方法存取 SDS 伺服器。可以使用 Unix 網域套接字路徑 /tmp/uds_path 和 127.0.0.1:8234 (透過 mTLS) 來連線 gRPC SDS 伺服器。它提供三個密鑰:client_cert、server_cert 和 validation_context。在組態中,叢集 example_cluster 憑證 client_cert 組態為使用 Google gRPC (使用 UDS) 與 SDS 伺服器通訊。監聽器需要從 SDS 伺服器擷取 server_cert 和 validation_context。server_cert 使用 Envoy gRPC 和叢集 sds_server_mtls (組態為使用用戶端憑證) 以使用 mTLS 與 SDS 伺服器通訊。validate_context 使用 Envoy gRPC 和叢集 sds_server_uds (組態為使用 UDS 路徑) 與 SDS 伺服器通訊。
範例三:xDS gRPC 連線的憑證輪換
管理 Envoy 與 xDS 伺服器之間的 xDS gRPC 連線的憑證會產生開機問題:SDS 伺服器無法管理連線到伺服器所需的憑證。
此範例示範如何透過從檔案系統取得 SDS 組態來設定 xDS 連線。會使用 inotify 監看憑證和金鑰檔案,並在不重新啟動的情況下自動重新載入。相反地,範例二:SDS 伺服器 需要重新啟動,才能在更新後重新載入 xDS 憑證和金鑰。
clusters:
- name: control_plane
type: LOGICAL_DNS
connect_timeout: 1s
load_assignment:
cluster_name: control_plane
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: controlplane
port_value: 8443
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
transport_socket:
name: "envoy.transport_sockets.tls"
typed_config:
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext"
common_tls_context:
tls_certificate_sds_secret_configs:
name: tls_sds
sds_config:
path: /etc/envoy/tls_certificate_sds_secret.yaml
validation_context_sds_secret_config:
name: validation_context_sds
sds_config:
path: /etc/envoy/validation_context_sds_secret.yaml
用戶端憑證 (包含用戶端憑證鏈和私密金鑰) 的路徑在 SDS 組態檔案 /etc/envoy/tls_certificate_sds_secret.yaml
中提供
resources:
- "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret"
name: tls_sds
tls_certificate:
certificate_chain:
filename: /certs/sds_cert.pem
private_key:
filename: /certs/sds_key.pem
驗證 xDS 伺服器憑證的 CA 憑證套件的路徑在 SDS 組態檔案 /etc/envoy/validation_context_sds_secret.yaml
中提供
resources:
- "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret"
name: validation_context_sds
validation_context:
trusted_ca:
filename: /certs/cacert.pem
在以上範例中,會在 /certs
上建立監看。在此目錄中的檔案移動將會觸發更新。另一種可提供更佳原子性的常見金鑰輪換配置是建立作用中符號連結 /certs/current
,並使用原子移動操作來取代符號連結。在這種情況下,監看需要在憑證的上一層目錄中。Envoy 透過使用 watched_directory 來支援此配置。繼續上述範例
resources:
- "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret"
name: tls_sds
tls_certificate:
certificate_chain:
filename: /certs/current/sds_cert.pem
private_key:
filename: /certs/current/sds_key.pem
watched_directory:
path: /certs
resources:
- "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret"
name: validation_context_sds
validation_context:
trusted_ca:
filename: /certs/current/cacert.pem
watched_directory:
path: /certs
可以使用以下方式執行密鑰輪換
ln -s <path to new secrets> /certs/new && mv -Tf /certs/new /certs/current
統計資訊
SSL 通訊端工廠會輸出下列與 SDS 相關的統計資訊。它們都是計數器類型。
對於下游監聽器,它們位於 listener.<LISTENER_IP>.server_ssl_socket_factory. 命名空間中。
名稱 |
描述 |
---|---|
ssl_context_update_by_sds |
已更新的 ssl 內容總數。 |
downstream_context_secrets_not_ready |
因空的 ssl 憑證而重設的下游連線總數。 |
對於上游叢集,它們位於 cluster.<CLUSTER_NAME>.client_ssl_socket_factory. 命名空間中。
名稱 |
描述 |
---|---|
ssl_context_update_by_sds |
已更新的 ssl 內容總數。 |
upstream_context_secrets_not_ready |
因空的 ssl 憑證而重設的上游連線總數。 |
SDS 有一個以 sds.<SECRET_NAME>. 命名空間為根的 統計資訊 樹狀結構。此外,在此命名空間中追蹤以下統計資訊
名稱 |
描述 |
---|---|
key_rotation_failed |
在 SDS 更新之外失敗的檔案系統金鑰輪換總數。 |