apache - 使用 Ngnix、Apache、Envoy 或其他反向代理将 Mutal TLS 转换为 OAuth ClientCredentials
问题描述
我有许多使用 OAuth Bearer 令牌进行身份验证的服务。我可以使用 OAuth 客户端凭据授权或资源所有者凭据授权来获取令牌。
但是,我有许多现有系统只能使用 Mutual TLS 身份验证连接进行身份验证。
与其更新所有调用应用程序以获取 OAuth 持有者令牌,不如构建一个网关代理:
- 接收 TLS 认证的连接
- 使用证书的主题来识别系统参与者
- 使用客户端凭据或资源所有者授权代表该系统获取令牌
- 调用底层服务并将结果返回给客户端
本质上,我想隐藏旧客户端正在使用 OAuth 的事实,并允许它们专门使用 Mutal TLS 身份验证。
是否存在用于 Ngnix、Apache、Envoy 或类似 HTTP 反向代理的反向代理或方法或模块,无需构建整个代理即可实现这一目标?
我发现很多模块可以使用各种模块来处理将 Apache 和 Ngnix 设置为 OAuth 中继方或资源服务器的情况,例如
但是找不到它们充当 OAuth 或 Open ID Connect 客户端作为相互 TLS 身份验证客户端的代理的任何示例。
特别是我想避免编写代理部分。即使我必须编写实际的 OAuth 交互脚本。我发现的最接近的是这篇关于在 Envoy lua 脚本中实现 OAuth RP 的博文。
我很难想象这是一个独特的需求,所以我想知道是否有我还没有找到的这种模式的标准实现。
解决方案
事实证明,使用 Envoy Proxy 很容易做到这一点。特别是通过使用外部授权 HTTP 过滤器。
Envoy 代理可以配置为执行 SSL 终止,并通过在侦听器上设置下游 TLS 上下文require_client_certificate
并设置为true
.
可以配置HTTP 连接管理器网络过滤器以将x-forwarded-client-cert
请求的标头设置为上游服务。特别将forward-client-cert-details设置为SANITIZE_SET
将导致 envoy 设置标头。可以通过设置set-current-client-cert-details来配置标头中包含的内容。
但要真正让 Envoy 进行令牌交换,我们需要配置一个外部授权过滤器。这允许特使调用具有请求详细信息(包括证书)的服务,并且该服务可以决定是否允许请求。至关重要的是,当允许时,它能够将标头添加到向上游服务发出的请求中,这允许它添加 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 服务,该服务实现外部授权协议以进行令牌交换,并拒绝请求或提供Authorization
标头以在上游请求中包含不记名令牌。
推荐阅读
- ms-access - 如何在 MS Access 中创建更改条件格式的清单
- vbscript - 对象不支持此方法
- excel - 日期范围内的 Sumproduct
- swift - 更新到 Swift 5 和 iOS 12.2 SDK 后运行 ARFaceTrackingConfiguration 会导致会话运行非常缓慢
- javascript - 有没有办法剥离原型方法并使其作为函数工作?
- mysql - 有效日期的 MySQL 不正确的日期时间值错误
- angular - 以理智的方式在 NGXS 中声明状态
- pandas - 如何使用 seaborn 显示多个时间序列图
- ruby-on-rails - 如何配置 docker 以使用 byebug?
- javascript - TestCafe runner.video 不是 createTestCafe.then.then.remoteConnection 中的函数