跟我学EnvoyGateway:网关证书配置

跟我学EnvoyGateway:网关证书配置

一、引言

在 K8s 环境下,安全网关的运用有着诸多重要作用。本文将围绕 Envoy Gateway 相关的安全网关配置及应用场景展开详细介绍,旨在帮助使用者更好地理解和运用相关技术,实现安全高效的网络通信。

二、安装

按照快速入门任务中的步骤来安装 Envoy Gateway 以及示例清单。在继续操作之前,应当能够使用 HTTP 来查询示例后端。

验证网关状态:

  • kubectl get gateway/eg -o yaml
三、TLS 证书
  1. 生成网关用于终止客户端 TLS 连接所使用的证书和密钥
    • 创建一个根证书和私钥来对证书进行签名:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./***=example.***' -keyout example.***.key -out example.***.crt
- 为 `www.example.***` 创建一个证书和私钥:
openssl req -out www.example.***.csr -newkey rsa:2048 -nodes -keyout www.example.***.key -subj "/***=www.example.***/O=example organization"
openssl x509 -req -days 365 -CA example.***.crt -CAkey example.***.key -set_serial 0 -in www.example.***.csr -out www.example.***.crt
- 将证书/密钥存储在一个 Secret 中:
kubectl create secret tls example-cert --key=www.example.***.key --cert=www.example.***.crt
- 更新快速入门中的网关,使其包含一个监听在 443 端口且引用 `example-cert` Secret 的 HTTPS 监听器:
kubectl patch gateway eg --type=json --patch '
  - op: add
    path: /spec/listeners/-
    value:
      name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
        - kind: Secret
          group: ""
          name: example-cert
  '
- 再次验证网关状态:
kubectl get gateway/eg -o yaml
  1. 多个 HTTPS 监听器
    • 为额外的 HTTPS 监听器创建一个 TLS 证书/密钥:
openssl req -out foo.example.***.csr -newkey rsa:2048 -nodes -keyout foo.example.***.key -subj "/***=foo.example.***/O=example organization"
openssl x509 -req -days 365 -CA example.***.crt -CAkey example.***.key -set_serial 0 -in foo.example.***.csr -out foo.example.***.crt
- 将证书/密钥存储在一个 Secret 中:
kubectl create secret tls foo-cert --key=foo.example.***.key --cert=foo.example.***.crt
- 在示例网关上创建另一个 HTTPS 监听器:
kubectl patch gateway eg --type=json --patch '
  - op: add
    path: /spec/listeners/-
    value:
      name: https-foo
      protocol: HTTPS
      port: 443
      hostname: foo.example.***
      tls:
        mode: Terminate
        certificateRefs:
        - kind: Secret
          group: ""
          name: foo-cert
  '
- 更新 HTTPRoute 以将主机名 `foo.example.***` 的流量路由到示例后端服务:
kubectl patch httproute backend --type=json --patch '
  - op: add
    path: /spec/hostnames/-
    value: foo.example.***
  '
- 验证网关状态:
kubectl get gateway/eg -o yaml
- 按照“测试”部分中的步骤,通过两个网关监听器测试到后端应用的连接性。将 `www.example.***` 替换为 `foo.example.***` 来测试新的 HTTPS 监听器。
  1. 跨命名空间证书引用
    网关可以配置为引用不同命名空间中的证书。这需要在目标命名空间中创建一个 ReferenceGrant。若没有 ReferenceGrant,跨命名空间引用是无效的。
    • 在继续操作之前,确保能够从“测试”部分查询 HTTPS 后端服务。
    • 为了演示跨命名空间证书引用,创建一个 ReferenceGrant,允许来自“default”命名空间的网关引用“envoy-gateway-system”命名空间中的 Secrets:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.***working.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: example
  namespace: envoy-gateway-system
spec:
  from:
  - group: gateway.***working.k8s.io
    kind: Gateway
    namespace: default
  to:
  - group: ""
    kind: Secret
EOF
- 删除之前创建的 Secret:
kubectl delete secret/example-cert

此时网关的 HTTPS 监听器应当会显示 Ready: False 状态条件,并且示例 HTTPS 后端将无法再通过网关访问。

kubectl get gateway/eg -o yaml
- 在“envoy-gateway-system”命名空间中重新创建示例 Secret:
kubectl create secret tls example-cert -n envoy-gateway-system --key=www.example.***.key --cert=www.example.***.crt
- 更新网关的 HTTPS 监听器(指定命名空间为“envoy-gateway-system”),示例如下:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.***working.k8s.io/v1
kind: Gateway
metadata:
  name: eg
spec:
  gatewayClassName: eg
  listeners:
    - name: http
      protocol: HTTP
      port: 80
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            group: ""
            name: example-cert
            namespace: envoy-gateway-system
EOF

此时网关的 HTTPS 监听器状态应当会显示 Ready: True 条件,并且应当能够再次通过网关查询 HTTPS 后端。
最后,使用上述“测试”部分的内容测试连接性。

四、清理

按照快速入门中的步骤卸载 Envoy Gateway 和示例清单。
删除 Secrets:

kubectl delete secret/example-cert
kubectl delete secret/foo-cert
五、RSA + ECDSA 双栈证书
  1. 预检查
    在集群内测试(无外部负载均衡器支持的情况下),我们可以在强制使用 RSA 密码套件时通过 Envoy 代理查询示例应用,如下所示:
curl -v -HHost:www.example.*** --resolve "www.example.***:8443:127.0.0.1" \
--cacert example.***.crt https://www.example.***:8443/get  -Isv --ciphers ECDHE-RSA-CHACHA20-POLY1305 --tlsv1.2 --tls-max 1.2

由于此时配置的 Secret 是基于 RSA 的 Secret,如果我们强制使用 ECDSA 密码套件,调用将会失败,如下所示:

curl -v -HHost:www.example.*** --resolve "www.example.***:8443:127.0.0.1" \
--cacert example.***.crt https://www.example.***:8443/get  -Isv --ciphers ECDHE-ECDSA-CHACHA20-POLY1305 --tlsv1.2 --tls-max 1.2
  1. TLS 证书
    重用在“安全网关”任务中生成的 CA 证书和密钥对,并使用该 CA 来签署 RSA 和 ECDSA 服务器证书。注意,CA 证书和密钥名称分别为 example.***.crtexample.***.key
    • www.example.*** 创建一个 ECDSA 证书和私钥:
openssl ecparam -noout -genkey -name prime256v1 -out www.example.***.ecdsa.key
openssl req -new -SHA384 -key www.example.***.ecdsa.key -nodes -out www.example.***.ecdsa.csr -subj "/***=www.example.***/O=example organization"
openssl x509 -req -SHA384  -days 365 -in www.example.***.ecdsa.csr -CA example.***.crt -CAkey example.***.key -CAcreateserial -out www.example.***.ecdsa.crt
- 将证书/密钥存储在一个 Secret 中:
kubectl create secret tls example-cert-ecdsa --key=www.example.***.ecdsa.key --cert=www.example.***.ecdsa.crt
- 用这个额外的 ECDSA Secret 来修补网关:
kubectl patch gateway eg --type=json --patch '
  - op: add
    path: /spec/listeners/1/tls/certificateRefs/-
    value:
      name: example-cert-ecdsa
  '
- 验证网关状态:
kubectl get gateway/eg -o yaml
  1. 测试
    同样,在集群内测试(无外部负载均衡器支持的情况下),我们可以在强制使用 RSA 密码套件时通过 Envoy 代理查询示例应用,这应当和之前一样能正常工作:
curl -v -HHost:www.example.*** --resolve "www.example.***:8443:127.0.0.1" \
--cacert example.***.crt https://www.example.***:8443/get  -Isv --ciphers ECDHE-RSA-CHACHA20-POLY1305 --tlsv1.2 --tls-max 1.2

此外,现在强制使用 ECDSA 密码套件查询示例应用也应当能正常工作了:

curl -v -HHost:www.example.*** --resolve "www.example.***:8443:127.0.0.1" \
--cacert example.***.crt https://www.example.***:8443/get  -Isv --ciphers ECDHE-ECDSA-CHACHA20-POLY1305 --tlsv1.2 --tls-max 1.2
六、基于 SNI 的证书选择
  1. 额外配置
    使用“TLS 证书”部分的内容,我们首先为另一个主机 www.sample.*** 生成额外的 Secret。
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=sample Inc./***=sample.***' -keyout sample.***.key -out sample.***.crt
openssl req -out www.sample.***.csr -newkey rsa:2048 -nodes -keyout www.sample.***.key -subj "/***=www.sample.***/O=sample organization"
openssl x509 -req -days 365 -CA sample.***.crt -CAkey sample.***.key -set_serial 0 -in www.sample.***.csr -out www.sample.***.crt
kubectl create secret tls sample-cert --key=www.sample.***.key --cert=www.sample.***.crt

然后更新网关配置以适配这个将用于终止 TLS 流量的新证书:

kubectl patch gateway eg --type=json --patch '
  - op: add
    path: /spec/listeners/1/tls/certificateRefs/-
    value:
      name: sample-cert
  '

最后,更新 HTTPRoute 以将主机名 www.sample.*** 的流量路由到示例后端服务:

kubectl patch httproute backend --type=json --patch '
  - op: add
    path: /spec/hostnames/-
    value: www.sample.***
  '
  1. 测试
    参考之前在“有外部负载均衡器支持的集群中的测试”部分提到的步骤。
七、自定义网关 TLS 参数

除了通过网关 API 启用 TLS 之外,Envoy Gateway 还支持自定义 TLS 参数。在本示例中,我们将自定义最小支持的 TLS 版本为 TLSv1.3。

cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
  name: enforce-tls-13
  namespace: default
spec:
  targetRefs:
  - group: gateway.***working.k8s.io
    kind: Gateway
    name: eg
  tls:
    minVersion: "1.3"
EOF
八、测试 TLS 参数

尝试使用不支持的 TLS 版本进行连接:

curl -v -HHost:www.sample.*** --resolve "www.sample.***:8443:127.0.0.1" \
--cacert sample.***.crt --tlsv1.2 --tls-max 1.2 https://www.sample.***:8443/get -I

输出显示,由于客户端使用了不支持的 TLS 协议版本,连接失败。现在,在不指定客户端版本的情况下连接到网关,注意此时连接是使用 TLSv1.3 建立的:

curl -v -HHost:www.sample.*** --resolve "www.sample.***:8443:127.0.0.1" \
--cacert sample.***.crt https://www.sample.***:8443/get -I
专业术语 翻译(若有)
TLS 传输层安全
ReferenceGrant 引用授权
ClientTrafficPolicy 客户端流量策略
Gateway API 网关 API
LoadBalancer 负载均衡器
SNI 服务器名称指示
转载请说明出处内容投诉
CSS教程网 » 跟我学EnvoyGateway:网关证书配置

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买