Envoy TLS

Service Mesh Authentication

  • A service mesh provides the ability to do authentication between your services to ensure traffic flowing in your clusters is secure.
  • There are 4 different authentication options available with a sidecar service mesh:
    • JWT Validation in Applications

    • JWT Validation at Ingress

    • Ingress TLS passthrough + JWT Validation at Sidecars

    • mTLS + JWT Validation

Envoy的身份认证机制

  • Envoy支持两种类型的认证机制

    • 传输认证:即服务间的认证,它基于双向TLS实现传输认证(即mTLS),包括双向认证、信道安全和证书自动管理;每个服务都需要有其用于服务间双向认证的标识,以实现此种认证机制;
    • 用户认证:也称为终端用户认证,用于认证请求的最终用户或者设备;Envoy通过JWT(JSON Web Token)实现此类认证需求,以保护服务端的资源;
      • 客户端基于HTTP标头向服务端发送JWT

      • 服务端验证签名

      • envoy.filters.http.jwt_authn过滤器

Envoy TLS

Envoy 支持侦听器中的TLS 终止以及 与上游集群建立连接时的TLS 发起。支持足以让 Envoy 执行现代 Web 服务的标准边缘代理职责,以及启动与具有高级 TLS 要求(TLS1.2、SNI 等)的外部服务的连接。Envoy 支持以下 TLS 功能:

  • 可配置密码:每个 TLS 侦听器和客户端都可以指定它支持的密码。

  • 客户端证书:除了服务器证书验证之外,上游/客户端连接还可以提供客户端证书。

  • 证书验证和固定:证书验证选项包括基本链验证、主题名称验证和哈希固定。

  • 证书吊销:Envoy 可以根据证书吊销列表 (CRL) 检查对等证书(如果提供的话) 。

  • ALPN:TLS 监听器支持 ALPN。HTTP 连接管理器使用此信息(除了协议推断)来确定客户端使用的是 HTTP/1.1 还是 HTTP/2。

  • SNI:服务器(侦听器)和客户端(上游)连接都支持 SNI。

  • 会话恢复:服务器连接支持通过 TLS 会话票据恢复以前的会话(参见RFC 5077)。可以在热重启和并行 Envoy 实例之间执行恢复(通常在前端代理配置中有用)。

  • BoringSSL 私钥方法:TLS 私钥操作(签名和解密)可以从扩展异步执行。这允许扩展 Envoy 以支持各种密钥管理方案(例如 TPM)和 TLS 加速。该机制使用 BoringSSL 私钥方法接口。

  • OCSP 装订:在线证书装订协议响应可以装订到证书。

Envoy TLS 底层实现

  • 在底层使用BoringSSL作为SSL库;

  • DownstreamTlsContexts支持多个TLS证书(多个证书需要属于同一类型,RSA或ECDSA),但 UpstreamTlsContexts目前仅支持单个证书
  • 支持执行标准边缘代理任务,以及启动与具有高级TLS要求的外部服务(TLS1.2,SNI等)的连接;

启用证书验证

除非验证上下文指定一个或多个受信任的权威证书,否则不会启用上游和下游连接的证书验证。

示例配置

static_resources:
  listeners:
  - name: listener_0
    address: {socket_address: {address: 127.0.0.1, port_value: 10000}}
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            virtual_hosts:
            - name: default
              domains: ["*"]
              routes:
              - match: {prefix: "/"}
                route:
                  cluster: some_service
      transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
          common_tls_context:
            tls_certificates:
            - certificate_chain: {filename: "certs/servercert.pem"}
              private_key: {filename: "certs/serverkey.pem"}
            validation_context:
              trusted_ca:
                filename: certs/cacert.pem
  clusters:
  - name: some_service
    type: STATIC
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: some_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 1234
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        common_tls_context:
          tls_certificates:
          - certificate_chain: {"filename": "certs/servercert.pem"}
            private_key: {"filename": "certs/serverkey.pem"}
            ocsp_staple: {"filename": "certs/server_ocsp_resp.der"}
          validation_context:
            match_typed_subject_alt_names:
            - san_type: DNS
              matcher:
                exact: "foo"
            trusted_ca:
              filename: /etc/ssl/certs/ca-certificates.crt

Linux 和 BSD 上系统 CA 包的常见路径

  • /etc/ssl/certs/ca-certificates.crt(Debian/Ubuntu/Gentoo 等)

  • /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem (CentOS/RHEL 7)

  • /etc/pki/tls/certs/ca-bundle.crt (Fedora/RHEL 6)

  • /etc/ssl/ca-bundle.pem (OpenSUSE)

  • /usr/local/etc/ssl/cert.pem (FreeBSD)

  • /etc/ssl/cert.pem (OpenBSD)

自定义证书验证器

  • Envoy 还支持envoy.tls.cert_validator扩展类别中的自定义验证器,可以在CertificateValidationContext上进行配置。
  • 例如,Envoy 可以配置为在单个侦听器或集群中使用多个信任包验证遵循SPIFFE规范的对等证书。

证书选择

DownstreamTlsContexts支持多个 TLS 证书。这些可能是 RSA 和 P-256 ECDSA 证书的混合。以下规则适用:

  • 只能指定一个特定类型的证书(RSA 或 ECDSA)。

  • 拒绝非 P-256 服务器 ECDSA 证书。

  • 如果客户端支持 P-256 ECDSA,如果一个 P-256 ECDSA 证书存在于 DownstreamTlsContext 中并且符合 OCSP 策略,则将选择该证书。

  • 如果客户端仅支持 RSA 证书,则将选择 RSA 证书(如果存在于 DownstreamTlsContext中)。

  • 否则,使用列出的第一个证书。如果客户端只支持 RSA 证书而服务器只有 ECDSA 证书,这将导致握手失败。

  • 静态和 SDS 证书不能在给定的DownstreamTlsContext中混合使用。

  • 所选证书必须遵守 OCSP 策略。如果没有找到这样的证书,则拒绝连接。

目前UpstreamTlsContexts仅支持单个 TLS 证书。

Envoy中设定数字证书的方式

  • 配置时,可以通过静态资源格式指定使用的TLS证书,也可以通过SDS动态获取TLS证书;

    • SDS可以简化证书管理

      • 各实例的证书可由SDS统一推送;

      • 证书过期后,SDS推送新证书至Envoy实例可立即生效而无需重启或重新部署;

    • 获取到所需要的证书之后侦听器方能就绪;不过,若因同SDS服务器的连接失败或收到其错误响应而无法获取证书,则侦听器会打开端口,但会重置连接请求;
    • Envoy同SDS服务器之间的通信必须使用安全连接;

    • SDS服务器需要实现gRPC服务SecretDiscoveryService,它遵循与其他xDS相同的协议;

  • 设定数字证书的方式

    • 在transport_sockets配置段中,通过tls_certificats基于指定数据源直接加载证书及私钥

    • 在static_resources中定义出静态格式的Secret资源,而后在transport_sockets中的SDS配置里面通过指定Secret名称进行引用
    • 而通过SDS提供证书时,需要配置好SDS集群,并由listener或cluster在transport_sockets中通过sds_config引用;

配置Envoy Downstream TLS

  • Envoy v3 API中移除了v2使用了tls_context,而改用Transport sockets扩展来支持TLS通信

    • 扩展的专用名称为envoy.transport_sockets.tls

    • 针对TLS终止和TLS始发,分别存在一种类型的专用配置

      • TLS始发:extensions.transport_sockets.tls.v3.UpstreamTlsContext

      • TLS终止:extensions.transport_sockets.tls.v3.DownstreamTlsContext

  • DownstreamTlsContext与UpstreamTlsContext各自的配置中,均可定义连接参数、数字证书等,但前者还可强制要求客户端请求证书,从而进行mutual TLS会话
  • Listener中的Transport sockets定义在filter_chains配置段中,与“filters[ ]”位于同一级别

listeners: 
- name: ...
  address: {...}
  ......
  filter_chains: 
  - filters:
    - name: envoy.filters.network.http_connection_manager
    ……
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext 
        common_tls_context:  # 通用的TLS配置,包括TLS通信特征和证书等;
          tls_params: {...}  # TLS 协议版本、密码套件等。
          tls_certificates: []   # tls通信中使用的证书,只能使用tls_certificates、tls_certificate_sds_secret_configs和tls_certificate_provider_instance之一。
          tls_certificate_sds_secret_configs:   # 通过SDS API加载secret(从而加载证书和私钥)的配置,不能与tls_certificates配置段同时使用
            name: ...
            sds_config: {...}
          validation_context:   # 用于校验对端证书的相关配置,只能设置validation_context、validation_context_sds_secret_config、combined_validation_context之一。
            trusted_ca: {...}                  # 信任的CA,相关信息可从filename、inline_bytes和inline_string三种数据源之一中加载
            watched_directory: {...}           # 基于SDS协议从文件系统中加载CA时监视的目录
            verify_certificate_spki: []        # SPKI校验,经过Base64编码的SPKI (Subject Public Key Information)的SHA-256校验码列表
            verify_certificate_hash: []        # Hash校验,仅该列表中的hash码对应的证书会被接受
            match_subject_alt_names: []        # Subject的可替换名称列表
            crl: {...}                         # 证书吊销列表,相关信息可从filename、inline_bytes和inline_string三种数据源之一中加载
            allow_expired_certificate: ...     # 是否接受已然过期的证书
            trust_chain_verification:          # 证书信任链的校验模式,支持VERIFY_TRUST_CHAIN和ACCEPT_UNTRUSTED两种,前者为默认值
            custom_validator_config:           # 扩展特定证书验证器的配置。 envoy.tls.cert_validator.spiffe
              name: envoy.tls.cert_validator.spiffe
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig
                trust_domains:     # 此字段指定用于验证传入 X.509-SVID 的信任域。
                  name: ...   # 信任域的名称,例如example.com foo.bar.gov。请注意,这不能有“spiffe://”前缀。
                  trust_bundle:  # 指定一个包含 x.509 信任包的数据源,用于验证此信任域中的传入 SVID。
                    filename: ...  # 本地文件系统数据源。必须设置filename、inline_bytes、inline_string、environment_variable之一。
                    inline_bytes: ... # 配置中内联的字节。
                    inline_string: ... # 配置中内联的字符串。
                    environment_variable: ... # 环境变量数据源。
            only_verify_leaf_cert_crl: ...     # 如果此选项设置为 true,则只有证书链末尾的证书将由CRL验证。
            max_verify_depth: {...}            # 配置在验证期间解析的链中中间证书的最大数量。默认限制为 100。
          validation_context_sds_secret_config: {...}  #  用于通过 SDS API 获取验证上下文的配置。
          combined_validation_context: {...} # 组合证书验证上下文包含默认的 CertificateValidationContext 和 SDS 配置。
          alpn_protocols: []  # 提供侦听器应公开的 ALPN 协议列表。 “h2,http/1.1” 同时支持 HTTP/2 和 HTTP/1.1。 “http/1.1” 只支持 HTTP/1.1。此参数没有默认值。
          custom_handshaker: {...} # 自定义 TLS 握手。如果为空,则默认为原生 TLS 握手行为。
          key_log : {...} # TLS 密钥日志配置
        require_client_certificate: ... # 是否强制校验客户端证书
        session_ticket_keys: {...} # 为了能够恢复TLS session,服务器会使用session key将session加密后发送给客户端保存;客户端需要透明地支持该功能
        session_ticket_keys_sds_secret_config: {...} # 通过SDS API请求加载session ticket key的配置;
        disable_stateless_session_resumption: “...” # 布尔型值,true表示不生成session ticket,从而启用stateless session;false表示生成并加密会话,加密使用的key可由session_ticket_keys或session_ticket_keys_sds_secret_config定义,未定义时,将由TLS Server自行生成和管理;
        session_timeout: {...} # 会话超时时长
        ocsp_staple_policy: "..." #

配置Envoy Upstream TLS

clusters:
- name: ...
  ...
  transport_socket:
    name: envoy.transport_sockets.tls
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
      sni: ...                    # SNI支持基于FQDN的TLS,创建TLS后端连接时使用的SNI字符串
      allow_renegotiation: ...    # 是否允许启用协调机制,不安全,不建议使用;
      max_session_keys: {...}     # 允许存储的用于进行session恢复的最大session key数量;默认为1,0表示禁止会话恢复
      common_tls_context:         # 通用的TLS配置,包括TLS通信特征和证书等;
        tls_params:               # TLS 协议版本、密码套件等。
          tls_minimum_protocol_version: ... # 支持的最小的TLS协议版本号,默认客户端是TLS 1.2,服务端是TLS 1.0
          tls_maximum_protocol_version: ... # 支持的最大的TLS协议版本号,默认,客户端是TLS 1.2,服务端是TLS 1.3
          cipher_suites: [ ]                # TLS 1.0-1.2版本协商中支持加密算法列表,TLS1.3不受影响;
          ecdh_curves: []                   # 使用的ecdh curve算法;
        tls_certificates:    # tls通信中使用的证书,只能使用tls_certificates、tls_certificate_sds_secret_configs和tls_certificate_provider_instance之一。
          certificate_chain:      # 加载的证书信息的数据源,相关数据源只能是下列三种之一,而且仅可设置一种
            filename: ...         # 证书文件路径
            inline_bytes: ...     # 包含在配置文件中直接给出字节字串中
            inline_string: ...    # 包含在配置文件中直接给出字串中
          private_key:            # 加载的私钥信息的数据源,格式同上面的certificate_chain
          watched_directory:      # 基于SDS协议从文件系统中加载证书和私钥时监视的目录
            path: ...             # 监视的目录路径
        tls_certificate_sds_secret_configs:  # 通过SDS API加载secret(从而加载证书和私钥)的配置,不能与tls_certificates配置段同时使用
        - name: ...                          # 引用的secret的惟一标识名,secret为静态配置;若同时给出了下面的sds_config配置,则会从其SDS API动态加载secret
          sds_config:                        # SDS API服务配置,path、api_config_source和ads三种配置一次仅可定义一种
            path: ...                        # 基于文件
            api_config_source: {...}         # 基于SDS订阅
            ads: {...}                       # 基于ADS订阅
            initial_fetch_timeout: ...       # 初始加载的超时时长
            resource_api_version: ...        # 资源的API版本        
        validation_context:                  # 用于校验对端证书的相关配置
          trusted_ca: {...}                  # 信任的CA,相关信息可从filename、inline_bytes和inline_string三种数据源之一中加载
          watched_directory: {...}           # 基于SDS协议从文件系统中加载CA时监视的目录
          verify_certificate_spki: []        # SPKI校验,经过Base64编码的SPKI (Subject Public Key Information)的SHA-256校验码列表
          verify_certificate_hash: []        # Hash校验,仅该列表中的hash码对应的证书会被接受
          match_subject_alt_names: []        # Subject的可替换名称列表
          crl: {...}                         # 证书吊销列表,相关信息可从filename、inline_bytes和inline_string三种数据源之一中加载
          allow_expired_certificate: ...     # 是否接受已然过期的证书
          trust_chain_verification:          # 证书信任链的校验模式,支持VERIFY_TRUST_CHAIN和ACCEPT_UNTRUSTED两种,前者为默认值
          custom_validator_config:           # 扩展特定证书验证器的配置。 envoy.tls.cert_validator.spiffe
            name: envoy.tls.cert_validator.spiffe
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig
              trust_domains:     # 此字段指定用于验证传入 X.509-SVID 的信任域。
                name: ...   # 信任域的名称,例如example.com foo.bar.gov。请注意,这不能有“spiffe://”前缀。
                trust_bundle:  # 指定一个包含 x.509 信任包的数据源,用于验证此信任域中的传入 SVID。
                  filename: ...  # 本地文件系统数据源。必须设置filename、inline_bytes、inline_string、environment_variable之一。
                  inline_bytes: ... # 配置中内联的字节。
                  inline_string: ... # 配置中内联的字符串。
                  environment_variable: ... # 环境变量数据源。
          only_verify_leaf_cert_crl: ...     # 如果此选项设置为 true,则只有证书链末尾的证书将由CRL验证。
          max_verify_depth: {...}            # 配置在验证期间解析的链中中间证书的最大数量。默认限制为 100。
        validation_context_sds_secret_config: # 通过SDS API动态加载validation context
          name: ...                # 引用的secret的惟一标识名,secret为静态配置;若同时给出了下面的sds_config配置,则会从其SDS API动态加载secret
          sds_config:              # SDS API服务配置
        combined_validation_context           # 混合模式的validation context加载机制,同时给了静态配置和SDS,SDS有返回数据时将二者合并后使用
          default_validation_context: {...}   # 默认使用的静态配置的validation context
          validation_context_sds_secret_config: {...} # 动态加载validation context secret的SDS API

静态Secret

静态Secret配置格式

  •  静态的secrets资源直接定义在static_resources字段中,与listeners和clusters位于同一配置级别
    • 根据其功能,Secret通常有数字证书(服务端或客户端)、票证密钥和证书校验机制三种类型,但每个定义仅能指定为其中一种类型;
static_resources:
  listeners: [ ]
  clusters: [ ]
  secrets: [ ] # 静态指定的Secret列表,定义时,以下三种方式可选其一;
    - name: ... # 可用于引用此秘密(Secret)的惟一标识;
      tls_cretificate: {...} # 数字证书
        certificate_chain: {...} # 加载的TLS证书链,其数据源可以是filename、inline_bytes和inline_string三者之一;
        private_key: {...} # TLS私钥,遵循DataSource格式;
        password: {...} # 私钥信息的加解密密钥,未指定时需要私钥文件处于未加密状态,遵循DataSource格式;
        watched_directory: {...} #基于SDS协议从文件系统中加载证书和私钥时监视的目录
    - name: ... # 可用于引用此秘密的惟一标识;
      session_ticket_keys: {...} # 定义用于加密和解密TLS会话票证的密钥
        keys: [ ] # 密钥列表,未指定时将使用内部生成和管理的密钥,定义格式遵循DataSource格式;
    - name: ... # 可用于引用此秘密(Secret)的惟一标识;
      validation_context: {...} # 对等证书验证机制的相关配置
        trusted_ca: {...} # 信任的CA的证书,未指定时不会验证对端证书;
        crl: {...} # 可选的PEM格式的证书吊销列表,定义格式遵循DataSource格式;
        verify_certificate_spki: [ ] # base64编码的SHA-256哈希码,用于验证DER编码枨证书的公钥信息的SHA-256编码是否与列表项之一匹配
        verify_certificate_hash: [ ] # base64编码的SHA-256哈希码,用于验证DER编码格式证书的SHA-256编码是否与列表项之一匹配
        verify_subject_alt_name: [ ] # Subject备用名称列表,可选,用于验证证书的主题备用名称是否与列表项之一匹配
        match_subject_alt_names: [] # Subject的可替换名称列表
        allow_expired_certificate: ... # 布尔型数据,用于定义是滞不会拒绝过期的证书
        watched_directory: {...} # 基于SDS协议从文件系统中加载CA时监视的目录
    -name: ...
      generic_secret: # 可由filter使用的通用类型的secret
        secret: {...} # 从指定的DataSource格式的数据源加载secret

静态Secret配置示例

node:
  id: front-envoy
  cluster: front-envoy

admin:
  profile_path: /tmp/envoy.prof
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
       address: 0.0.0.0
       port_value: 9901

layered_runtime:
  layers:
  - name: admin
    admin_layer: {}

static_resources:
  secrets:
  - name: server_cert
    tls_certificate:
      certificate_chain:
        filename: "/etc/envoy/certs/server.crt"
      private_key:
        filename: "/etc/envoy/certs/server.key"
  - name: client_cert
    tls_certificate:
      certificate_chain:
        filename: "/etc/envoy/certs/client.crt"
      private_key:
        filename: "/etc/envoy/certs/client.key"
  - name: validation_context
    validation_context:
      trusted_ca:
        filename: "/etc/envoy/ca/ca.crt"

  listeners:
  - name: listener_http
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 80
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          codec_type: auto
          stat_prefix: ingress_http
          access_log:
          - name: envoy.access_loggers.file
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog 
              path: "/dev/stdout"           
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                redirect:
                  https_redirect: true
                  port_redirect: 443
          http_filters:
          - name: envoy.filters.http.router
            typed_config: {}

  - name: listener_https
    address:
      socket_address: { address: 0.0.0.0, port_value: 443 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_https
          codec_type: AUTO
          access_log:
          - name: envoy.access_loggers.file
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog 
              path: "/dev/stdout"           
          route_config:
            name: https_route
            virtual_hosts:
            - name: https_route
              domains: ["*"]
              routes:
              - match:
                  prefix: "/service/gray"
                route:
                  cluster: service-gray
              - match:
                  prefix: "/service/purple"
                route:
                  cluster: service-purple
              - match:
                  prefix: "/"
                route:
                  cluster: mycluster
          http_filters:
          - name: envoy.filters.http.router
            typed_config: {}
      transport_socket:  # DownstreamTlsContext
        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

  clusters:
  - name: mycluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: mycluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: myservice
                port_value: 80

  - name: service-gray
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service-gray
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: service-gray
                port_value: 443
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        common_tls_context:
          validation_context_sds_secret_config:
            name: validation_context

  - name: service-purple
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service-purple
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: service-purple
                port_value: 443
    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
          validation_context_sds_secret_config:
            name: validation_context

 

Secret发现服务 (SDS)

TLS 证书可以在静态资源中指定,也可以远程获取。通过从文件系统获取 SDS 配置或从 SDS 服务器推送更新来支持静态资源的证书轮换。

SDS配置示例

clusters:
  - name: sds_server_mtls
    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:
            connection_keepalive:
              interval: 30s
              timeout: 5s
    load_assignment:
      cluster_name: sds_server_mtls
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 8234
    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:
          certificate_chain:
            filename: certs/sds_cert.pem
          private_key:
            filename: certs/sds_key.pem
  - name: sds_server_uds
    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: {}
    load_assignment:
      cluster_name: sds_server_uds
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              pipe:
                path: /tmp/uds_path
  - name: example_cluster
    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
            sds_config:
              resource_api_version: V3
              api_config_source:
                api_type: GRPC
                transport_api_version: V3
                grpc_services:
                  google_grpc:
                    target_uri: unix:/tmp/uds_path
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
            sds_config:
              resource_api_version: V3
              api_config_source:
                api_type: GRPC
                transport_api_version: V3
                grpc_services:
                  envoy_grpc:
                    cluster_name: sds_server_mtls
          validation_context_sds_secret_config:
            name: validation_context
            sds_config:
              resource_api_version: V3
              api_config_source:
                api_type: GRPC
                transport_api_version: V3
                grpc_services:
                  envoy_grpc:
                    cluster_name: sds_server_uds

故障排除

当 Envoy 在与上游集群建立连接时发起 TLS 时,任何错误都将记录到 UPSTREAM_TRANSPORT_FAILURE_REASON字段或 AccessLogCommon.upstream_transport_failure_reason字段中。常见错误有:

  • Secret is not supplied by SDS:Envoy 仍在等待 SDS 交付密钥/证书或根 CA。

  • SSLV3_ALERT_CERTIFICATE_EXPIRED:对等证书已过期,并且不允许在配置中使用。

  • SSLV3_ALERT_CERTIFICATE_UNKNOWN: 对等证书不在配置指定的 SPKI 中。

  • SSLV3_ALERT_HANDSHAKE_FAILURE:握手失败,通常是由于上游需要客户端证书但未提供。

  • TLSV1_ALERT_PROTOCOL_VERSION: TLS 协议版本不匹配。

  • TLSV1_ALERT_UNKNOWN_CA: 对等证书 CA 不在受信任的 CA 中。

参考文档

https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/security/ssl

https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/tls.proto#envoy-v3-api-msg-extensions-transport-sockets-tls-v3-upstreamtlscontext

posted @ 2022-09-22 16:26  小吉猫  阅读(807)  评论(0编辑  收藏  举报