news 2026/9/12 13:59:27

Envoy GCP 认证过滤器新增 token_metadata_key:将 GCP 认证令牌写入动态元数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Envoy GCP 认证过滤器新增 token_metadata_key:将 GCP 认证令牌写入动态元数据

Envoy GCP 认证过滤器新增 token_metadata_key:将 GCP 认证令牌写入动态元数据

【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy

导读

Envoy 的 GCP 认证过滤器(envoy.filters.http.gcp_authn)负责从 GCE Metadata Server 获取 GCP 认证令牌并注入到请求中。当前开发版本(见 changelogs/current/new_features/gcp_authn__token-metadata-key.rst)新增了token_metadata_key配置字段:不再局限于把令牌写入 HTTP 请求头,而是可以将令牌保存到以过滤器配置名为命名空间的**动态元数据(dynamic metadata)**中,供过滤器链中的下游过滤器、路由动作或上层控制面消费。阅读完本文,你将掌握该字段的配置方法、优先级语义、底层源码实现,以及如何在iam_access_token等依赖动态元数据的场景中利用这一新能力。

一、特性背景:GCP 认证过滤器的令牌注入方式

GCP 认证过滤器用于服务到服务(service-to-service)认证场景。当多个私有服务需要互相通信时,Envoy 作为代理在请求转发前,从 GCE Metadata Server 获取认证令牌(identity token / access token),并把它注入到发往目标服务的请求中,避免请求因缺少凭据而被目标服务拒绝。其整体行为在 GCP Authentication Filter 文档 中有完整描述。

在引入token_metadata_key之前,令牌的注入位置完全由请求头决定,共有两种方式(对应 proto 中token_header字段与默认行为):

  1. 默认行为:写入Authorization请求头,格式为Authorization: Bearer <token>
  2. 自定义请求头:通过token_header.name指定头名、token_header.value_prefix指定前缀(格式为value_prefix<token>,例如Bearer带一个尾随空格),此时令牌写入自定义头。

上述逻辑完整体现在过滤器实现 gcp_authn_filter.cc 的addTokenToRequest方法中(第 253-270 行),这也是token_metadata_key特性落地的位置。

二、token_metadata_key 配置项详解

token_metadata_key定义在过滤器配置 proto 中,见 gcp_authn.proto(第 52-54 行):

// Optional dynamic metadata key to save the token. The metadata uses the filter config name as the namespace. // Takes precedence over ``token_header``. string token_metadata_key = 7;

关键语义如下:

要点说明
字段类型string,可选字段;配置过滤器配置名空间下的动态元数据键名
命名空间以**过滤器配置名(filter config name)**作为动态元数据命名空间,即envoy.filters.http.gcp_authn
优先级一旦设置,token_header不再生效;未设置时回退到token_header/ 默认Authorization: Bearer <token>
数据形态令牌以字符串值写入动态元数据的 Struct 字段中

从 proto 注释可以确认,该字段位于GcpAuthnFilterConfig的第 7 号字段(当前结构[#next-free-field: 9]),与token_header(字段 4)、cluster(字段 5)、timeout(字段 6)、audience(字段 8)并列。

与 token_header 的优先级关系

配置字段之间遵循明确的优先级:token_metadata_key>token_header> 默认Authorization。proto 中token_header字段(第 46-50 行)的注释也印证了这一点:

默认情况下(未指定该字段),令牌写入Authorization头,格式为Authorization: Bearer <token>。若设置了token_metadata_key,该字段不生效。

三、完整配置示例

官方配置示例文件 gcp-authn-filter-configuration.yaml 给出了过滤器与集群的完整配置。在 HTTP 过滤器链中启用该过滤器并配置token_metadata_key的写法如下:

static_resources: listeners: - address: socket_address: address: 0.0.0.0 port_value: 8000 filter_chains: - filters: - name: "http" typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager codec_type: HTTP2 stat_prefix: "config_test" route_config: name: "route_config_0" virtual_hosts: - name: "integration" domains: ["*"] routes: - match: prefix: "/" route: cluster: "cluster_0" http_filters: - name: "envoy.filters.http.gcp_authn" typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig http_uri: uri: "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=[AUDIENCE]" cluster: "gcp_authn" timeout: 10s # 新增:将获取到的令牌保存到动态元数据中, # 命名空间为 "envoy.filters.http.gcp_authn",键名为 "token" token_metadata_key: "token" - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: cluster_0 # Cluster for fake destination service which has typed metadata that contains the audience information. load_assignment: cluster_name: cluster_0 endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 0.0.0.0 port_value: 8000 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: {} metadata: typed_filter_metadata: envoy.filters.http.gcp_authn: "@type": type.googleapis.com/envoy.extensions.filters.http.gcp_authn.v3.Audience url: http://test.com # Cluster for GCE metadata server - name: gcp_authn type: STRICT_DNS connect_timeout: 5s dns_lookup_family: V4_ONLY load_assignment: cluster_name: "gcp_authn" endpoints: - lb_endpoints: - endpoint: address: socket_address: address: "metadata.google.internal" port_value: 80

需要注意http_uri字段在 proto 中已被标记为 deprecated(计划在 3.0 版本废弃),控制面应优先使用新增的clustertimeout字段来配置元数据服务器访问,http_uri仅作向后兼容兜底(见 gcp_authn.proto 第 28-37 行)。

四、源码级实现原理

1. 核心写入逻辑:addTokenToRequest

token_metadata_key的实现位于 gcp_authn_filter.cc 的GcpAuthnFilter::addTokenToRequest(第 253-270 行):

void GcpAuthnFilter::addTokenToRequest(Http::RequestHeaderMap& hdrs, absl::string_view token_str) { const FilterConfigProto proto = filter_config_->config(); if (!proto.token_metadata_key().empty()) { Protobuf::Struct metadata; (*metadata.mutable_fields())[proto.token_metadata_key()].set_string_value(token_str); decoder_callbacks_->streamInfo().setDynamicMetadata( std::string(decoder_callbacks_->filterConfigName()), metadata); return; } const envoy::extensions::filters::http::gcp_authn::v3::TokenHeader& header = proto.token_header(); if (header.ByteSizeLong() == 0) { std::string id_token = absl::StrCat("Bearer ", token_str); hdrs.setCopy(authorizationHeaderKey(), id_token); } else { std::string id_token = absl::StrCat(header.value_prefix(), token_str); hdrs.setCopy(Http::LowerCaseString(header.name()), id_token); } }

实现要点:

  • 分支优先级在代码层面固化:只要token_metadata_key非空,函数立即构造Protobuf::Struct并将令牌以字符串值放入metadata[token_metadata_key],随后调用streamInfo().setDynamicMetadata(filterConfigName(), metadata)写入动态元数据并return,完全跳过请求头写入逻辑;
  • 命名空间取自过滤器配置名decoder_callbacks_->filterConfigName()返回的是配置中该过滤器的名字(如envoy.filters.http.gcp_authn),这正是 proto 注释所述"以过滤器配置名为命名空间"的由来;
  • 令牌原文写入:写入动态元数据的是令牌原始字符串(JWT 或 access token),不带Bearer前缀。

2. 调用链

addTokenToRequest在两条路径上被调用(见 gcp_authn_filter.cc):

  • 缓存命中路径decodeHeaders中先查TokenCache,命中时直接调用addTokenToRequest(hdrs, token.value())Continue(第 188-196 行),不发起对元数据服务器的异步请求;
  • 异步获取完成路径onComplete回调中在continueDecoding()之前调用addTokenToRequest将令牌写入(第 223-244 行)。

因此无论令牌来自缓存还是新获取,写入动态元数据的路径是统一的。

五、下游如何消费动态元数据中的令牌

写入动态元数据后,过滤器链中排在gcp_authn之后的过滤器、路由动作等都可以按filter_metadata["envoy.filters.http.gcp_authn"]["token"]的形态读取该令牌。仓库内一个典型的下游消费场景是iam_access_token(见 gcp_authn__iam-access-token.rst 与 gcp_authn.proto 第 88-100 行):它的authorization字段是 substitution formatter 模板,官方注释给出的示例为:

Bearer %DYNAMIC_METADATA(gcp_authn:token)%

也就是说,先由 gcp_authn 过滤器用token_metadata_key把 GCE 令牌写入gcp_authn命名空间,再通过%DYNAMIC_METADATA(gcp_authn:token)%模板在 IAM 令牌请求中复用它作为授权头(底层格式化逻辑见 gcp_authn_filter.cc 第 72-82 行构造的account_formatter_/auth_formatter_)。这从仓库证据上说明了token_metadata_key的实际价值:让令牌不落入 HTTP 请求头,而是在请求处理管道内部以结构化方式流转,供其他基于动态元数据的组件复用

六、测试验证

仓库测试 gcp_authn_filter_test.cc 为token_metadata_key提供了三组针对性用例,可作为行为契约:

测试用例验证内容
SaveTokenToDynamicMetadata(第 993 行)配置token_metadata_key: custom_token_key后,令牌以该键写入setDynamicMetadata("envoy.filters.http.gcp_authn", ...),且Authorization保持为空
SaveTokenToDynamicMetadataCacheHit(第 1025 行)缓存命中时同样走动态元数据写入路径(缓存令牌值为cached_token),不触发异步客户端调用
TokenMetadataKeyPrecedenceOverTokenHeader(第 1060 行)同时配置token_metadata_keytoken_header时,token_metadata_key优先,自定义请求头custom-headerAuthorization均未被写入

测试代码还展示了预期的元数据结构:expected_metadata.fields["custom_token_key"]为字符串值(第 1006-1010 行),与实现中Protobuf::Struct的写入方式一一对应。测试中的过滤器配置名 mock 为envoy.filters.http.gcp_authn(第 999-1000 行),印证了命名空间语义。

七、使用注意事项

结合 proto 注释与实现,使用token_metadata_key时有几点需要留意:

  1. 优先级的明确性:设置该字段后,令牌不再出现在任何请求头中。若下游依赖Authorization头透传令牌,需评估是否受影响;
  2. 命名空间一致性:写入位置是streamInfo的动态元数据,命名空间为过滤器配置名。消费方读取时必须使用相同的命名空间与键名,例如%DYNAMIC_METADATA(gcp_authn:token)%
  3. 数据形态:动态元数据中保存的是令牌原文(无Bearer前缀),消费方若需要组装标准认证头需自行添加前缀;
  4. 适用范围token_metadata_keytoken_headeraudiencecache_config等字段一样,proto 注释标注"并非所有 data plane 都支持",跨实现使用时需确认目标 data plane 的能力(见 gcp_authn.proto 相关字段注释);
  5. 当前状态:该字段属于changelogs/current中的新特性,即当前开发分支引入的能力,适用于使用最新版本代码构建的 Envoy。

总结

token_metadata_key是 gcp_authn 过滤器令牌传递方式的补充通道:它以过滤器配置名为命名空间,将获取到的 GCP 认证令牌写入动态元数据,优先级高于token_header与默认Authorization头。从 proto 定义 到 过滤器实现 再到 单元测试,该特性的语义清晰、行为有测试保障,为基于动态元数据令牌流转的复杂认证编排(如iam_access_token的 substitution formatter 消费)提供了基础能力。

【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 13:54:53

动态环境下无人机协同路径规划与防撞算法实践

1. 项目概述&#xff1a;动态环境下的无人机协同挑战 在物流配送、农业植保、城市安防等领域&#xff0c;多无人机协同作业正成为行业新趋势。但动态环境中的路径规划问题就像高峰期的空中交通管制——每架无人机既要到达目标位置&#xff0c;又要实时避开移动障碍物和其他无人…

作者头像 李华
网站建设 2026/9/12 13:54:34

LangChain Tools:大语言模型的外部交互组件解析

1. LangChain Tools核心概念解析 LangChain Tools是构建智能代理(Agent)的核心组件&#xff0c;它允许大语言模型(LLM)与外部工具和系统进行交互。简单来说&#xff0c;Tools就是LLM的"手"和"眼睛"——让模型不仅能思考&#xff0c;还能执行具体操作。 在…

作者头像 李华
网站建设 2026/9/12 13:53:03

Prometheus监控临时任务的Pushgateway解决方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 13:51:35

Reflex 接入 Databricks 完全指南:从凭据获取到数据驱动应用落地

Reflex 接入 Databricks 完全指南&#xff1a;从凭据获取到数据驱动应用落地 【免费下载链接】reflex &#x1f578;️ Web apps in pure Python &#x1f40d; 项目地址: https://gitcode.com/GitHub_Trending/re/reflex 导读 本指南讲解如何在 Reflex 应用中接入 Dat…

作者头像 李华
网站建设 2026/9/12 13:48:47

三相AC-DC-AC PWM变换器仿真建模核心原理与工程验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华