TLS 代理

本指南解释了一些传输层安全性(TLS)代理概念,以及如何在KES服务器前设置和配置TLS代理。

K E S C l i e n t T L S P r o x y K E S S e r v e r K M S

TLS 代理基础

使用TLS代理为一个或多个服务提供统一的TLS端点。 一组客户端连接到由TLS代理提供的统一端点。 该代理随后将请求转发给实际的服务。

一些常见的TLS代理包括HAProxy or Nginx

在KES客户端和KES服务器之间运行TLS代理具有以下优缺点:

优点

  • 部署多个KES服务器,并将它们通过一个公共端点和一个TLS证书统一暴露给所有客户端。
  • TLS代理可以在所有KES服务器之间平衡负载。
  • 负载均衡允许您根据流量和可用资源透明地添加或移除KES服务器。
  • TLS代理在一定程度上将面向公众和客户的基础设施部分与内部部分隔离开来。

Cons

  • TLS代理可以充当任何kes identity - 包括root, if not disabled. 安全配置TLS代理并保持其更新非常重要。 For more information take a look at the安全影响最佳实践以下部分。
  • TLS代理由于需要额外的TLS握手而增加了额外开销。 不过,现代TLS代理已使这种额外开销对用户而言可以忽略不计。

安全影响

在KES服务器前运行TLS代理会带来一些安全影响。 每个KES客户端在建立与KES服务器的连接时都必须提供有效的X.509 TLS客户端证书。 然而,当TLS代理位于KES客户端和KES服务器之间时,客户端无法与KES服务器执行TLS握手。 相反,客户端必须与TLS代理执行TLS握手。 随后,代理会提取客户端的X.509证书并将其转发给KES服务器。

这带来了一个潜在问题:KES服务器无法确保从TLS代理接收到的客户端证书确实属于与TLS代理执行TLS握手的客户端。 恶意的TLS代理可能向KES服务器谎报执行TLS握手的客户端身份。

风险场景

考虑一个客户端场景A连接到TLS代理并呈现其客户端证书。 在此场景中,代理可能向KES服务器谎报并转发客户端的证书。BKES服务器无法验证TLS代理所声称的客户端请求来源是否真实。 KES服务器会默认采信该客户端B发出请求并应用任何关联的策略BTLS代理也可以充当root通过转发证书来验证身份root并执行任意操作,除非root身份已被禁用。

缓解措施

由于这些可能性,TLS代理必须是系统中可信的组件。 您必须配置并妥善管理该代理以减轻这些风险。

最佳实践

The安全影响如上所述,需要一些最佳实践设置,特别是在生产环境中。

一般来说,身份不能将自己分配到策略中。 例如身份A无法分配A对于策略(禁止自我分配)。

然而,恶意TLS代理可以绕过这一点。 如果存在两个身份(AB) 其中A可以创建一个策略并B可以分配A对于一项策略。 TLS代理可以首先使用A创建一个具有过多权限的策略,然后使用B分配A针对这项新政策。 现在,恶意代理可以再次充当A并执行其已授予自身访问权限的任何操作。

对于此类环境,我们建议至少采取以下措施。

在接收来自 TLS 代理请求的 KES 服务器上:

  • 禁用root通过以下任一选项进行身份验证。
    • 设置root配置文件中针对这些服务器的条目_.
    • 传递标志--root=_当你启动服务器时。
  • 不要授予任何身份对危险操作的访问权限,例如/v1/key/delete/<key-name>特别是,考虑/v1/policy/write/<policy-name>API 危险。
  • 仅将 KES 服务器连接到需要处理客户端/应用请求的 TLS 代理。 对于日常管理任务(例如删除密钥),建议为执行这些任务的团队单独设置专用的 KES 服务器。 将管理服务器与其他服务器连接到相同的密钥存储库,但不要将管理 KES 服务器置于 TLS 代理配置之后。
  • 启用审计日志记录。 配置 KES 服务器将所有 API 调用作为审计事件记录到审计日志中。

教程

配置 NGINX

以下 NGINX 配置模板将客户端请求路由到https://your.domain.com到运行在localhost:7373:

server {
    listen         443 ssl http2;
    server_name    your.domain.com;

    proxy_buffering off;
    client_max_body_size 0;

    ssl_certificate     /path/to/the/nginx-server.crt;
    ssl_certificate_key /path/to/the/nginx-server.key;

    # You may set this to:
    # - "ssl_verify_client on"
    #    The client has to provide a TLS client certificate
    #    and it must have been issued by a CA that nginx trusts.
    #
    # - "ssl_verify_client optional"
    #    The client may provide a TLS client certificate. If it does
    #    then the certificate must haven been issued by a CA that nginx
    #    trusts. (e.g. no self-signed)
    #    However, if the client does not send a certificate then the
    #    KES server will reject the request.
    #
    # - "ssl_verify_client optional_no_ca"
    #    The client may provide a TLS client certificate. It may not
    #    be issued by a CA that nginx trusts. (e.g. self-signed)
    #    However, if the client does not send a certificate then the
    #    KES server will reject the request.
    ssl_verify_client   optional_no_ca;
        
    location / {
       # The KES server endpoint.
       proxy_pass            https://localhost:7373;
       
       # Disable response buffering. Nginx will forward any
       # response sent by the KES server directly to the client
       # instead of writing it into its cache first. 
       proxy_buffering off;

       # This requires that the KES server presents a certificate
       # signed by a (public or internal) CA that is trusted by nginx.
       # For testing/development purposes you may set this to "grpc_ssl_verify off". 
       proxy_ssl_verify       on;

       # KES requires TLSv1.3.
       proxy_ssl_protocols    TLSv1.3;

       # The nginx client certificate used to authenticate nginx
       # to the KES server. The identity of this certificate must be
       # included in the list of TLS proxies. See KES config file.
       proxy_ssl_certificate       /path/to/the/nginx-client.cert;
       # The nginx client private key used to authenticate nginx
       # to the KES server.
       proxy_ssl_certificate_key   /path/to/the/nginx-client.key;

       # The header containing the forwarded certificate of the 
       # actual KES client. This value must match the corresponding
       # entry in the kes config file.
       # Nginx will replace $ssl_client_escaped_cert with the certificate
       # presented by the KES client.
       proxy_set_header X-Tls-Client-Cert $ssl_client_escaped_cert;
    }
}

更新 KES 配置

您必须将 NGINX 标识添加到 KES 服务器上的 TLS 代理列表中。

  1. 获取NGINX的身份信息:

    kes identity of </path/to/the/nginx-client.cert>
    

    注意:这是 NGINX 向 KES 出示的证书,用于认证自身为 TLS 代理。必须匹配您在 NGINX 配置文件中指定的路径proxy_ssl_certificate.

  2. 使用以下 KES 配置模板将身份添加到您的 KES 配置文件中:

    tls:
      proxy:
        # Add the identity of your Nginx proxy to the list of TLS proxies.
        # For example:
        identities:
        - c84cc9b91ae2399b043da7eca616048e4b4200edf2ff418d8af3835911db945d
        header:
          # The HTTP header containing the URL-escaped and PEM-encoded
          # certificate of the KES client. This must match the header Nginx
          # will set to forward the client certificate. 
          cert: X-Tls-Client-Cert
    
  3. 重启 KES 服务器。

  4. 验证您可以通过 NGINX 访问 KES 服务器

    • 将 KES CLI 客户端指向您的 NGINX 端点。

      要设置环境变量,请使用以下命令,将 your-domain.com 替换为您的 NGINX 端点地址。

      export KES_SERVER=https://your-domain.com
      
    • 执行您身份有权限执行的操作。

      例如,要列出所有策略:

      kes policy list -k
      

      您只能在附加到您身份的策略允许的情况下执行操作。 如果您作为root身份,因为您已设置KES_CLIENT_TLS_CERT_FILE到根证书文件,那么您应该能够执行任何操作。 如果您以另一个没有列出所有策略的策略权限的身份操作,那么KES服务器将拒绝该请求,并返回prohibited by policy错误。