资讯详情

Envoy Injected Credentials 深入指南:向代理请求注入 Basic Auth、Bearer Token 与 OAuth2 访问令牌

📅 2026/9/12 16:15:10 | 华诺云谱 👁 阅读
Envoy Injected Credentials 深入指南:向代理请求注入 Basic Auth、Bearer Token 与 OAuth2 访问令牌
Envoy Injected Credentials 深入指南向代理请求注入 Basic Auth、Bearer Token 与 OAuth2 访问令牌【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy导读Envoy 的 Injected Credentials注入凭证扩展体系为代理转发路径提供了一套标准化的凭据注入能力它允许你通过 HTTP 过滤器把从 SDSSecret Discovery Service读取的静态凭证如 HTTP Basic Auth、Bearer Token 或任意自定义令牌或从授权服务器动态获取的 OAuth2 access token自动注入到发往上游的 HTTP 请求头中。本文以 docs/root/api-v3/config/injected_credentials/injected_credentials.rst 为索引主线结合api/envoy/extensions/http/injected_credentials/下的 proto 定义与source/extensions/http/injected_credentials/下的 C 实现完整讲解 Generic 与 OAuth2 两类凭证注入器的配置字段、工作流程、错误处理与统计指标并给出可直接落地的配置示例。读完本文你将掌握如何把 Envoy 侧车sidecar配置成自动携带工作负载身份凭证的代理而无需修改业务应用的请求代码。一、Injected Credentials 是什么定位与适用场景Injected Credentials 并不是一个独立的过滤器而是一组可被其他 HTTP 过滤器按需装配的凭证注入扩展注册在envoy.http.injected_credentials扩展类别下。当前仓库中该类别包含两个实现envoy.http.injected_credentials.generic注入任意静态凭证Basic Auth、Bearer Token 等定义见 generic.protoenvoy.http.injected_credentials.oauth2通过 OAuth2 Client Credentials Grant 流程动态获取 access token 并注入定义见 oauth2.proto。两者的 proto 均标记为package_version_status ACTIVE其中 oauth2.proto 在 xds 状态注解中额外标有work_in_progress true从 oauth2.proto 可见说明该能力已进入正式 API 版本管理。承载注入动作的是 HTTP 过滤器envoy.filters.http.credential_injector其配置定义在 credential_injector.proto 中。proto 文档明确了两点重要定位面向工作负载认证workload authentication被注入凭证所代表的身份被视为 Envoy 代理后面那个工作负载的身份典型部署形态是 Envoy 作为 sidecar 与业务进程同舱运行不处理终端用户认证end user authentication该过滤器的唯一目的是认证工作负载本身而不是登录态的最终用户。相关文档索引作为 API 导航页injected_credentials.rst 通过toctree通配符../../extensions/http/injected_credentials/*/v3/*将两类凭证的 proto 文档聚合到同一目录树即上文两个 proto 文件对应的 API 参考文档。二、整体架构与调用链从源码结构看凭证注入能力由三层构成HTTP Filtercredential_injector │ 在 decodeHeaders 阶段调用 ▼ CredentialInjector 抽象接口Common::CredentialInjector │ 按 TypedExtensionConfig 选择实现 ├── GenericCredentialInjectorgeneric └── OAuth2ClientCredentialTokenInjectoroauth2 └── TokenProvider异步拉取/缓存 token抽象接口source/extensions/http/injected_credentials/common/credential.h定义了CredentialInjector::inject(RequestHeaderMap headers, bool overwrite)返回absl::Status表示注入是否成功凭证读取source/extensions/http/injected_credentials/common/secret_reader.h中的SDSSecretReader基于ThreadLocalGenericSecretProvider从 SDS 读取 Generic Secret并把凭证缓存在线程本地槽位中过滤器入口source/extensions/filters/http/credential_injector/credential_injector_filter.cc在decodeHeaders阶段调用注入器注入失败时通过sendLocalReply返回401 Unauthorized响应体代码为failed_to_inject_credential否则返回Continue继续转发。工厂类方面generic 与 oauth2 的config.cc均实现了NamedCredentialInjectorConfigFactory并在REGISTER_FACTORY中静态注册见 generic/config.cc、oauth2/config.cc因此可以在任意TypedExtensionConfig中通过type直接引用。三、Generic 凭证注入任意凭证的头注入3.1 配置字段generic.proto 中Generic消息仅含三个字段字段类型必填说明credentialSdsSecretConfig是要注入的凭证必须是 Generic Secretgeneric_secret类型可走 SDS 动态下发也可引用静态 secretheaderstring否注入的目标请求头名留空时默认Authorization取值须符合 HTTP header name 校验规则HTTP_HEADER_NAME允许为空header_value_prefixstring否注入前的值前缀用于拼上 scheme如Bearer、Basic不设置则注入原始凭证值header_value_prefix的语义在 proto 注释中有明确示例若凭证值为xyz123、前缀为Bearer最终头值为Bearer xyz123。3.2 配置示例Basic Auth / Bearer Tokencredential_injector.proto 内嵌了完整可运行的示例。过滤器配置overwrite: true credential: name: generic_credential typed_config: type: type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic credential: name: credential sds_config: path_config_source: path: credential.yaml header: Authorization配套的 SDS 文件credential.yamlBasic Auth 场景resources: - type: type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret name: credential generic_secret: secret: inline_string: Basic base64EncodedUsernamePasswordBearer Token 场景只需把inline_string换成Bearer myToken即可此时无需配置header_value_prefix因为前缀已写在凭证值里。注意header_value_prefix与把 scheme 写进凭证值是两种等价做法。前者让凭证与 scheme 分离管理凭证文件只存令牌本身更利于凭证轮换时不动 scheme。3.3 底层实现要点从 generic_impl.cc 可以看到GenericCredentialInjector::inject的三个关键行为覆盖策略overwritefalse且目标头已存在时返回AlreadyExistsError不覆盖已有值由过滤器层决定放行还是拒绝尾随换行剥离凭证文件末尾常见的\n/\r不是合法的 HTTP 头值字符实现会循环剥离尾部 CR/LF 后再注入空凭证兜底剥离后凭证为空SDS 尚未就绪或 secret 缺失时返回NotFoundError由过滤器按配置决定是否放行。在 generic/config.cc 中工厂根据SdsSecretConfig是否携带sds_config走两条路径有则findOrCreateGenericSecretProviderSDS 动态下发无则findStaticGenericSecretProvider静态 secretheader为空时在工厂内兜底为Authorization。四、OAuth2 凭证注入动态获取并注入 Access Token4.1 支持的流程与认证方式oauth2.proto 中的OAuth2消息目前仅支持 Client Credentials Grantflow_typeoneof 中只有client_credentials分支且为validate.required即授权服务器直接为客户端签发令牌、不涉及用户授权码的机器对机器场景。令牌以 Bearer 形式注入Authorization头。AuthType枚举控制客户端向授权服务器出示client_id/client_secret的方式BASIC_AUTH 0使用 HTTP Basic 认证 scheme 发送默认推荐URL_ENCODED_BODY 1将凭据放在 URL 编码的请求体中发送仅当授权服务器不支持 Basic 认证时才应使用。4.2 配置字段总览字段类型必填/默认说明token_endpointHttpUri是授权服务器上获取 access token 的端点HttpUri内含cluster走哪个上游集群与timeout请求超时见 oauth_client.cc 的setTimeout用法scopesrepeated string否请求的 OAuth scope不填时按默认空 scope 处理见下client_credentials.client_idstring是min_len 1Client IDclient_credentials.client_secretSdsSecretConfig是Client Secret同样必须是 Generic Secretclient_credentials.auth_typeAuthType否默认 BASIC_AUTH凭据发送方式token_fetch_retry_intervalDuration否默认 2s两次 token 拉取失败重试的间隔校验规则为不小于 1 秒gte {seconds: 1}endpoint_paramsrepeated EndpointParameter否附加到 token 请求体中的自定义参数URL 编码后追加关于scopes的默认行为token_provider.cc 中的oauthScopesList显示scopes 为空时也会注入一个默认空 scope 字符串DEFAULT_AUTH_SCOPE 最终以空格连接后放入请求体。4.3 Token 请求与响应处理oauth_client.cc 展示了 token 请求的完整构造过程请求体格式为grant_typeclient_credentialsclient_id{0}client_secret{1}有 scope 时追加scope{2}L25-L28client_id、client_secret、scope及自定义endpoint_params均通过PercentEncoding::encode(..., :/?)做 URL 编码防止特殊字符破坏请求体请求通过clusterManager().getThreadLocalCluster(uri_.cluster())定位集群并用httpAsyncClient().send(...)异步发送成功回调onSuccess要求响应码必须为200响应体必须是包含access_token与expires_in的 JSON如{access_token:...,expires_in:3600}解析失败或字段缺失一律按失败处理若集群不存在或请求流被重置分别对应NotDispatchedClusterNotFound与StreamReset失败路径。4.4 Token 缓存、过期与重试机制token_provider.cc 与 token_provider.h 共同实现了完整的令牌生命周期管理启动即拉取TokenProvider构造时立即调用asyncGetAccessToken()线程本地缓存成功获取的 token 以Bearer access_token形式写入ThreadLocalOauth2ClientCredentialsToken所有工作线程通过 TLS 槽位读取避免每次请求都触发网络调用定时刷新onGetAccessTokenSuccess记录token_expiry_time_并在expires_in / 2时间后通过dispatcher_-createTimer触发预刷新确保 token 在过期前就被替换失败重试onGetAccessTokenFailure按失败原因分桶统计BadToken响应解析失败不重试其余原因按token_fetch_retry_interval默认 2s重试token 已过期时还会清空缓存的过期 token避免上游收到陈旧凭证空 secret 保护asyncGetAccessToken开头检测到 client secret 为空SDS 未就绪时不发请求直接等待重试间隔。对应的统计指标见 token_provider.htoken_requested、token_fetched、token_fetch_failed_on_client_secret、token_fetch_failed_on_cluster_not_found、token_fetch_failed_on_stream_reset、token_fetch_failed_on_bad_token、token_fetch_failed_on_bad_response_code可用于监控令牌拉取的成败与原因分布。4.5 注入行为client_credentials_impl.cc 中的OAuth2ClientCredentialTokenInjector::inject逻辑与 Generic 类似overwritefalse且Authorization已存在时返回AlreadyExistsErrortoken 为空尚未获取成功或已过期被清空时返回NotFoundError成功则以setReferenceKey写入Authorization头值为缓存好的Bearer token。五、CredentialInjector HTTP 过滤器装配与行为控制5.1 过滤器配置字段credential_injector.proto 中CredentialInjector消息字段类型默认值说明overwriteboolfalse目标头已存在时是否覆盖。为false且头已存在时注入器返回AlreadyExists过滤器统计already_exists并继续转发不覆盖原值allow_request_without_credentialboolfalse凭证缺失或注入失败时是否仍把请求发给上游。默认情况下返回401 Unauthorized为true时不带凭证直接放行credentialTypedExtensionConfig必填凭证注入器本体type指向envoy.http.injected_credentials.generic或envoy.http.injected_credentials.oauth2之一5.2 过滤器行为细节credential_injector_filter.cc 的实现要点过滤器继承PassThroughDecoderFilter只重写decodeHeaders对请求体与响应路径零侵入FilterConfig::injectCredential按absl::Status分类处理AlreadyExists→ 记already_exists并放行其他失败 → 记failed并按allow_request_without_credential决定放行与否成功 → 记injected失败且不允许无凭证转发时sendLocalReply(401 Unauthorized, Failed to inject credential., ..., failed_to_inject_credential)并StopIteration请求被本地拒绝过滤器级统计指标共三个injected、failed、already_exists定义见 credential_injector_filter.h。5.3 完整装配示例Basic Auth 场景http_filters: - name: envoy.filters.http.credential_injector typed_config: type: type.googleapis.com/envoy.extensions.filters.http.credential_injector.v3.CredentialInjector overwrite: true allow_request_without_credential: false credential: name: generic_credential typed_config: type: type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic credential: name: credential sds_config: path_config_source: path: /etc/envoy/credential.yaml header: Authorization在过滤器链中应把credential_injector放在需要携带凭证的转发路径之前如router过滤器之前并在 HTTP 连接管理器中引用该过滤器链。六、OAuth2 场景的完整配置示例结合 oauth2.proto 的字段一个使用 Client Credentials Grant 的典型配置如下http_filters: - name: envoy.filters.http.credential_injector typed_config: type: type.googleapis.com/envoy.extensions.filters.http.credential_injector.v3.CredentialInjector overwrite: true allow_request_without_credential: false credential: name: oauth2_credential typed_config: type: type.googleapis.com/envoy.extensions.http.injected_credentials.oauth2.v3.OAuth2 token_endpoint: cluster: auth_server_cluster uri: https://auth.example.com/oauth2/token timeout: 3s scopes: - read:data - write:data client_credentials: client_id: my-workload client_secret: name: oauth2_client_secret sds_config: path_config_source: path: /etc/envoy/client_secret.yaml auth_type: BASIC_AUTH token_fetch_retry_interval: 2s endpoint_params: - name: audience value: internal-api配套的client_secret.yamlGeneric Secret 形式resources: - type: type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret name: oauth2_client_secret generic_secret: secret: inline_string: s3cr3t-value该配置下Envoy 会在启动时立即向auth_server_cluster对应的授权服务器发起 Client Credentials Grant 请求成功后把Bearer access_token缓存在线程本地并在每个请求的Authorization头中注入token 过期前一半时间自动预刷新拉取失败则按 2 秒间隔重试BadToken类解析错误除外。七、测试与验证仓库为两个注入器提供了完整的单元测试与集成测试可作为行为契约参考Generic 注入器集成测试credential_injector_integration_test.cc、credential_injector_upstream_integration_test.ccOAuth2 相关测试config_test.cc配置解析与工厂装配、token_provider_test.cc令牌拉取/缓存/重试逻辑、credential_injector_oauth_integration_test.cc端到端令牌注入过滤器行为测试filter_test.cc 覆盖了 overwrite、401 拒绝、无凭证放行等分支。这些测试同时印证了本文所述的关键行为凭证已存在且不覆盖时放行、注入失败返回 401、SDS 未就绪时进入重试等待等。八、注意事项与使用限制仅 Client Credentials GrantOAuth2 注入器当前不支持授权码、隐式等流程只面向机器身份service-to-service场景工作负载身份而非用户身份被注入凭证标识的是代理背后的工作负载不要把该过滤器当作终端用户认证方案credential_injector.proto 中有明确声明凭证必须是 Generic SecretSdsSecretConfig引用的 secret 类型必须是generic_secret且建议优先走 SDS 动态下发以支持无重启轮换静态 secret 仅按名称引用凭证值合法性从文件读取的凭证末尾换行会被自动剥离但凭证值本身不应包含其他非法头字符换行等空凭证会被视为注入失败401 语义默认情况下SDS 未就绪或令牌获取失败都会导致请求直接以 401 失败请结合allow_request_without_credential谨慎决定生产环境的降级策略并利用injected/failed/token_fetch_failed_*等指标监控凭证链路的健康度超时与集群依赖OAuth2 的token_endpoint.cluster必须指向可用的上游集群HttpUri.timeout决定 token 请求超时令牌刷新完全在 Envoy 内部异步进行不影响业务请求的数据面性能。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。