使用Ngnix、Apache、En特使或其他反向代理将Mutal TLS转换为OAuth客户端凭据

使用Ngnix、Apache、En特使或其他反向代理将Mutal TLS转换为OAuth客户端凭据,apache,authentication,ssl,oauth-2.0,envoyproxy,Apache,Authentication,Ssl,Oauth 2.0,Envoyproxy,我有许多使用OAuth承载令牌进行身份验证的服务。我可以使用OAuth客户端凭据授权或资源所有者凭据授权来获取令牌 然而,我有许多现有的系统,它们只能通过相互TLS认证连接进行认证 与其更新所有调用应用程序以获得OAuth承载令牌,不如构建一个网关代理: 接收经过TLS身份验证的连接 使用证书的主题来标识系统参与者 使用客户端凭据或资源所有者授权代表该系统获取令牌 调用底层服务并将结果返回给客户端 本质上,我想隐藏这样一个事实,即OAuth正在对旧客户端使用,并允许它们专门使用Mutal TLS

我有许多使用OAuth承载令牌进行身份验证的服务。我可以使用OAuth客户端凭据授权或资源所有者凭据授权来获取令牌

然而,我有许多现有的系统,它们只能通过相互TLS认证连接进行认证

与其更新所有调用应用程序以获得OAuth承载令牌,不如构建一个网关代理:

  • 接收经过TLS身份验证的连接
  • 使用证书的主题来标识系统参与者
  • 使用客户端凭据或资源所有者授权代表该系统获取令牌
  • 调用底层服务并将结果返回给客户端
  • 本质上,我想隐藏这样一个事实,即OAuth正在对旧客户端使用,并允许它们专门使用Mutal TLS身份验证

    Ngnix、Apache、En特使或类似HTTP反向代理是否存在现有的反向代理或方法或模块,可以在不构建整个代理的情况下实现这一点

    我发现有很多模块可以处理将Apache和Ngnix设置为OAuth中继方或资源服务器的情况,它们使用各种模块,如

    但是找不到它们作为OAuth或Open ID Connect客户端作为相互TLS认证客户端的代理的任何示例

    我尤其希望避免编写代理部分。即使我必须编写实际的OAuth交互脚本。我发现的最接近的东西是这个


    我很难想象这是一种独特的需求,所以我想知道是否有我没有找到的这种模式的标准实现。

    事实证明,使用特使代理很容易实现这一点。特别是通过利用

    通过在侦听器上设置并将
    require\u client\u certificate
    设置为
    true
    ,可以将特使代理配置为执行SSL终止并需要客户端证书

    可以将配置为在向上游服务的请求上设置
    x-forwarded-client-cert
    头。特别设置为
    SANITIZE\u SET
    将导致特使设置标题。标题中包含的内容可以通过设置进行配置

    但要让特使真正进行令牌交换,我们需要配置一个外部授权过滤器。这允许特使调用一个服务,提供请求的详细信息(包括证书),该服务可以决定请求是否被允许。关键的是,如果允许,它能够向向上游服务发出的请求添加头,这允许它添加oauth所需的承载令牌

    外部授权筛选器有网络筛选器和HTTP筛选器版本。如果要向上游请求添加头,必须使用HTTP头

    生成的特使配置如下所示:

    static_resources:
      listeners:
      - name: listener_0
        address:
          socket_address:
            protocol: TCP
            address: 0.0.0.0
            port_value: 10000
        filter_chains:
        - filters:
          - name: envoy.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
              stat_prefix: ingress_http
              forward_client_cert_details: SANITIZE_SET # Include details of the client certificate in the x-forwarded-client-cert header when calling the upstream service
              set_current_client_cert_details:
                subject: True # Include the subject of the certificate in the x-forwarded-client-cert header rather than just the certificate hash.
              route_config:
                name: local_route
                virtual_hosts:
                - name: local_service
                  domains: ["*"]
                  routes:
                  - match:
                      prefix: "/"
                    route:
                      cluster: service_backend
              http_filters:
              - name: envoy.ext_authz # Call an authorization service to do the OAuth token exchange
                config:
                  grpc_service:
                    envoy_grpc:
                      cluster_name: auth_service
                    timeout: 5s # The timeout before envoy will give up waiting for an auth service response and deny access
              - name: envoy.router
          tls_context:
            require_client_certificate: True # Require downstream callers to provide a client certificate
            common_tls_context:
              validation_context:
                trusted_ca:
                  filename: /etc/envoy/certs/ca-chain.cert.pem # CA certificate that client certificate must be signed with to be accepted
              tls_certificates:
              - certificate_chain:
                  filename: /etc/envoy/certs/server-cert.pem
                private_key:
                  filename: /etc/envoy/certs/server-key.pem
                password:
                  inline_string: password
      clusters:
      - name: auth_service
        connect_timeout: 1s # The timeout before envoy will give up trying to make a TCP  connectio to an auth service
        type: LOGICAL_DNS
        dns_lookup_family: V4_ONLY
        lb_policy: ROUND_ROBIN
        http2_protocol_options: {} # GRPC services must be HTTP/2 so force HTTP/2
        load_assignment:
          cluster_name: auth_service
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: localhost
                    port_value: 8080
    

    然后,诀窍是实现一个GRPC服务,该服务实现进行令牌交换,或者拒绝请求,或者提供
    授权
    头以将承载令牌包括在上游请求中。

    如果您仍然需要,我构建了一个使用本地身份验证数据库的授权服务器。很容易将其转换为调用OIDC并接收要注入的令牌。