资讯动态

Envoy AWS 请求签名扩展架构:凭证提供链、SigV4 签名与异步凭证获取深度解析

发布时间:2026/9/15 17:20:46 来源:尧图企业网站定制
Envoy AWS 请求签名扩展架构凭证提供链、SigV4 签名与异步凭证获取深度解析【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy导读Envoy 通过aws_request_signing与aws_lambda两个扩展在代理层直接完成对 AWS API 的请求签名让下游服务无需感知 AWS SDK 即可安全访问 S3、Lambda、SQS 等云资源。本文以 source/extensions/common/aws/README.md 为骨架结合source/extensions/common/aws/下的源码实现系统讲解 AWS 公共组件的六大核心机制凭证提供器Credentials Provider、默认凭证提供链、基于元数据服务的异步凭证提供器、AWS 集群管理器、SigV4/SigV4A 签名器以及支撑签名流程不中断的异步凭证获取订阅通知模型。读完本文你将理解 Envoy 内部如何像 AWS SDK 一样定位并刷新凭证、如何复用内部集群完成元数据抓取、如何在凭证尚未就绪时暂停上游请求以及 IAM Roles Anywhere 基于 X509 证书的新式签名如何落地。一、整体架构概览AWS 公共组件Envoy::Extensions::Common::Aws位于 source/extensions/common/aws是aws_request_signing与aws_lambda两个扩展共用的底层库。整体架构可分为四层凭证层CredentialsCredentials容器AccessKeyId / SecretAccessKey / SessionToken与各类CredentialsProvider负责从不同来源获取凭证编排层Chain Cluster ManagerCredentialsProviderChain按优先级串联多个提供器AwsClusterManager统一管理用于抓取元数据的内部集群元数据抓取层MetadataFetcher以异步 HTTP 请求方式从 IMDS、ECS/EKS 容器代理或 STS 服务抓取临时凭证签名层Signer基于凭证对 HTTP 请求执行 SigV4 / SigV4A 签名并暴露“凭证未就绪则暂停”的异步回调接口。各核心类型的继承关系可从源码直接印证所有凭证提供器继承自CredentialsProvidercredentials_provider.h元数据类提供器继承自MetadataCredentialsProviderBasemetadata_credentials_provider_base.h签名器统一实现Signer接口signer.h。二、凭证提供器Credential Providers2.1 设计思想与 AWS SDK 对齐Credential ProvidersEnvoy::Extensions::Common::Aws::CredentialsProvider的实现方式与 AWS SDK 高度类似每个提供器专职从一种特定来源获取凭证彼此职责单一、可插拔。接口定义见 credentials_provider.h核心方法有三个providerName()返回提供器名称用于日志与统计getCredentials()同步返回当前可用凭证credentialsPending()返回是否仍处于凭证获取中异步提供器专用。Credentials是一个不可变容器构造时要求 access key 与 secret key 同时非空才认为是有效凭证并提供hasCredentials()判断方法所有组件在环境中找不到时返回std::nullopt且空字符串同样视为未找到。2.2 静态凭证提供器最简单的两类是静态来源提供器EnvironmentCredentialsProvider从环境变量AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKEN读取凭证ConfigCredentialsProvider从 Envoy 静态配置内嵌的凭证读取对应inline_credential配置。这两类不需要任何网络交互因此也不参与异步刷新机制是“同步即得”的最快路径。2.3 元数据类提供器其余提供器均属于元数据类需要向 AWS 的元数据/STS 端点发起 HTTP 请求提供器凭证来源集群类型InstanceProfileCredentialsProviderEC2 实例元数据服务 IMDS169.254.169.254STATICContainerCredentialsProviderECS/EKS 容器代理AWS_CONTAINER_CREDENTIALS_RELATIVE_URI/AWS_CONTAINER_CREDENTIALS_FULL_URISTATICWebIdentityCredentialsProviderSTS AssumeRoleWithWebIdentitytoken 来自文件或环境LOGICAL_DNSAssumeRoleCredentialsProviderSTS AssumeRoleLOGICAL_DNSIAMRolesAnywhereCredentialsProviderIAM Roles Anywhere基于 X509 证书LOGICAL_DNSCredentialsFileCredentialsProvider本地~/.aws/credentials文件静态全部实现位于 credential_providers 目录。2.4 刷新节奏与统计元数据提供器在 metadata_credentials_provider_base.h 中统一定义了统计项credential_refreshes_performedCounter执行刷新次数credential_refreshes_failedCounter刷新失败次数credential_refreshes_succeededCounter刷新成功次数metadata_refresh_stateGauge当前刷新状态。凭证缓存的默认刷新策略定义在 credentials_provider.hREFRESH_INTERVAL 1h正常状态下凭证的缓存刷新周期REFRESH_GRACE_PERIOD 60s到期前的宽限期避免临界时刻使用过期凭证MAX_CACHE_JITTER 30s最大刷新抖动用于打散大规模实例同时刷新的峰值。三、凭证提供链Credential Provider Chain3.1 链式降级模型CredentialsProviderChaincredentials_provider.h是一个有序的凭证提供器列表。核心逻辑add(provider)追加提供器chainGetCredentials()从头到尾遍历返回第一个能给出凭证的提供器的结果一旦前序提供器通过getCredentials()返回了凭证后续提供器不再被检查这与 AWS SDK 的AWSCredentialsProviderChain语义一致源码注释也明确引用了 aws-sdk-cpp 的参考实现。因此链的顺序即凭证解析的优先级顺序。3.2 默认凭证提供链通过Extensions::Common::Aws::CommonCredentialsProviderChain::defaultCredentialsProviderChain可一键创建默认链其定义在 credential_provider_chains.cc。README 明确给出的链顺序如下EnvironmentCredentialsProvider环境变量CredentialsFileCredentialsProvider本地凭证文件IAMRolesAnywhereCredentialsProviderRoles AnywhereWebIdentityCredentialsProviderWeb Identity / STSContainerCredentialsProviderECS/EKS 容器代理InstanceProfileCredentialsProviderEC2 实例元数据从 credential_provider_chains.cc 的实现可以看到默认链的构建细节无自定义配置时代码依次构造environment、credentials_file、container、instance_profile、assume_role_with_web_identity五类提供器此时 Roles Anywhere 仅在用户显式提供其配置时才被合并进链若用户提供了部分提供器的自定义配置如 Web Identity 的 token 文件路径、凭证文件的 profile 等则通过MergeFrom合并覆盖。该顺序体现了“越靠近本地、越廉价的方式越优先”环境变量与文件解析零网络开销其次是容器/实例元数据这类内网端点最后才是需要额外网络跳转的 STS 类服务。3.3 自定义凭证提供链除了默认链credential_provider_chains.h 还提供了customCredentialsProviderChain完全由用户在配置中指定提供器集合与顺序。其校验逻辑在 credential_provider_chains.cc自定义链至少需要包含一个凭证提供器否则返回InvalidArgumentError。同时源码对 AssumeRole 提供器做了一层防护——若 AssumeRole 内部再嵌套 AssumeRole会记录 warning 并忽略内层配置credential_provider_chains.cc避免无限递归。3.4 默认环境变量约定Web Identity 与 Container 提供器在无显式配置时依赖标准 AWS 环境变量credential_provider_chains.ccAWS_WEB_IDENTITY_TOKEN_FILEWeb Identity token 文件路径AWS_ROLE_ARN目标角色 ARNAWS_ROLE_SESSION_NAME会话名未设置时源码会用纳秒级时间戳生成见 credential_provider_chains.hAWS_CONTAINER_CREDENTIALS_RELATIVE_URI容器凭证相对 URI优先使用AWS_CONTAINER_CREDENTIALS_FULL_URI容器凭证完整 URI备选AWS_CONTAINER_AUTHORIZATION_TOKEN访问容器凭证端点时的授权 tokenAWS_EC2_METADATA_DISABLED设为true时跳过 InstanceProfile 提供器credential_provider_chains.cc。一个值得注意的细节Web Identity 的 token 若来自文件源码会自动为其配置watched_directorycredential_provider_chains.cc从而在 Kubernetes 等场景下 token 文件被自动轮换时能实时感知并加载新 token。四、元数据凭证提供器Metadata Credential Providers4.1 异步 HTTP 抓取模型元数据凭证提供器Envoy::Extensions::Common::Aws::MetadataCredentialsProviderBase是凭证提供器的异步子类它通过异步 HTTP 请求从远端抓取凭证。为此它依赖两样基础设施上游集群由 AWS 集群管理器AWS Cluster Manager创建用于发起 HTTP 请求MetadataFetcher负责单次元数据抓取其接口定义在 metadata_fetcher.h设计上“一个实例同一时刻只抓取一次”实现思路与 JwksFetcher 类似。抓取失败被归类为三种原因MetadataReceiver::FailureNetwork网络错误、InvalidMetadata解析失败、MissingConfig缺少配置。4.2 FirstRefresh 退避策略元数据提供器的首次刷新采用指数退避metadata_fetcher.h初始状态为FirstRefresh首次刷新失败后以2 秒为起点重试每次翻倍最大退避到 30 秒直到首次成功首次成功后进入Ready状态之后按正常的缓存时长1 小时 宽限期 抖动周期性刷新。4.3 线程本地缓存与单例凭证在多个工作线程间共享因此MetadataCredentialsProviderBase使用 ThreadLocal 槽位保存每个线程的凭证副本metadata_credentials_provider_base.h并通过setCredentialsToAllThreads在主线程写入后广播到各线程。由于同一主机上 IMDS 只有一份实例InstanceProfileCredentialsProvider被注册为单例SINGLETON_MANAGER_REGISTRATION(instance_profile_credentials_provider)见 credential_provider_chains.ccContainerCredentialsProvider同样如此。这样即使存在多个凭证提供链例如 per-route 配置下每个路由都有一条链也不会对 IMDS 产生多轮重复抓取。五、AWS 集群管理器AWS Cluster Manager5.1 动机集群去重与上线通知当多个扩展aws_request_signing、aws_lambda同时配置时若各自创建指向同一目标的集群会白白浪费资源。AWS Cluster ManagerAwsClusterManagerImplaws_cluster_manager.h解决两个问题集群去重多个元数据凭证提供器如果目标地址相同共享同一个内部集群只有不存在时才会新建上线订阅通知提供器订阅“集群已就绪”事件集群 online 后才开始凭证刷新周期避免在集群尚未创建完成时盲目发请求。5.2 关键接口addManagedCluster(cluster_name, cluster_type, uri)申请集群。存在同名同目标集群则复用否则创建addManagedClusterUpdateCallbacks(cluster_name, cb)注册集群更新回调返回 RAII 句柄AwsManagedClusterUpdateCallbacksHandlePtr销毁句柄即自动退订aws_cluster_manager.hgetUriFromClusterName(cluster_name)按名取回 URI。从 credential_provider_chains.cc 可看到具体用法STS 类提供器以LOGICAL_DNS类型创建指向sts.region.amazonaws.com:443的集群Container / InstanceProfile 则以STATIC类型创建指向元数据端点的集群。5.3 集群按目标去重的具体表现aws_cluster_manager.h 注释明确了各类提供器的去重粒度InstanceProfile只需一个指向 IMDS 的集群任意数量的aws_request_signing扩展实例共用Container只需一个指向容器代理的集群任意扩展实例共用WebIdentity / IAM Roles Anywhere按 regionRoles Anywhere 按 trust anchor 推导出的主机维护每 region 一个集群同一 region 下不同 role ARN 或 session name 的多个提供器共享集群并各自收到集群就绪通知。5.4 固定单例Pinned SingletonAwsClusterManagerImpl以固定单例pinned singleton方式注册SINGLETON_MANAGER_REGISTRATION(aws_cluster_manager)见 credential_provider_chains.cc并通过singletonManager().getTyped(..., true)固定。这意味着它一旦实例化将存活到服务器进程结束。由此带来的收益是即使aws_request_signing或aws_lambda扩展被替换/重建指向 IMDS 或 STS 的集群也不会被重新创建避免了重建集群带来的额外延迟。源码中addManagedCluster在集群管理器初始化阶段无法实时创建时会把集群请求排队createQueuedClusters待集群管理器就绪后再补建保证不丢失任何提供器的请求。六、请求签名Signing6.1 SigV4 与 SigV4AAWS 公共组件同时支持AWS SigV4与AWS SigV4A两种签名协议。签名实现位于 signers 目录SigV4SignerImpl标准 SigV4x-amz-date、x-amz-content-sha256等头部SigV4ASignerImplSigV4A基于 ECDSA、支持多 region 签名的变体头部使用x-amz-region-setIAMRolesAnywhereSigV4SignerIAM Roles Anywhere 专用签名器。签名器的行为验证直接复用 aws-c-auth 的官方签名测试语料aws-signing-test-suite确保 Envoy 生成的签名与 AWS SDK 输出完全一致。6.2 签名流程与头部SignerBaseImplsigner_base_impl.h实现了标准 SigV4 过程并定义了签名相关的头部与查询参数常量签名头部x-amz-content-sha256、x-amz-date、x-amz-security-token默认排除签名头部x-forwarded-for、x-forwarded-proto、x-amzn-trace-id避免代理链路附加头污染签名可通过配置的 exclude/include matcher 扩展预签名查询参数query string 模式X-Amz-Algorithm、X-Amz-Credential、X-Amz-Date、X-Amz-Region-Set、X-Amz-Security-Token、X-Amz-Signature、X-Amz-SignedHeaders、X-Amz-Expires默认过期时间 5 秒空 body 的内容哈希使用空字符串的 SHA-256 常量e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855也支持UNSIGNED-PAYLOAD字面量作为 content hash。Signer接口signer.h提供四种签名入口sign(message, sign_body)对完整请求签名可选择是否把 body 纳入签名纳入时 body 必须被完整缓冲signEmptyPayload(headers)按空 body 签名signUnsignedPayload(headers)以UNSIGNED-PAYLOAD签名sign(headers, content_hash)调用方预计算好 body 的 SHA-256 十六进制值后签名。当凭证尚在异步获取中时以上签名方法返回absl::NotFoundError调用方应通过addCallbackIfCredentialsPending等待凭证就绪。6.3 IAM Roles Anywhere基于 X509 的签名变体IAM Roles Anywhere 引入了一种新的 SigV4 签名变体基于 X509 证书身份而不是传统的 access key。其实现为IAMRolesAnywhereSignerBaseImpl是使用X509Credential凭证类型的 SigV4 特化实现X509Credentialscredentials_provider.h承载证书base64 DER、私钥 PEM、证书链、证书序列号、过期时间以及签名算法RSA / ECDSAIAMRolesAnywhereX509CredentialsProvider从配置加载证书与私钥并完成初始化校验credential_provider_chains.cc初始化失败时该提供器会被整体禁用并记录 error 日志随后由IAMRolesAnywhereSigV4Signer使用 X509 私钥对向 Roles Anywhere 服务rolesanywhere服务名发起的调用签名换取临时 AK/SK 凭证。从源码看该提供器的集群名由 trust anchor ARN 推导出的主机名中的.替换为_生成credential_provider_chains.cc从而保证同一 trust anchor 复用同一集群。七、异步凭证获取Asynchronous Credential Retrieval7.1 为什么需要异步aws_lambda与aws_request_signing扩展都支持异步凭证获取当凭证尚在抓取时上游请求会被暂停paused待凭证返回后再继续。这是冷启动场景下的关键能力——例如刚启动的 EC2/ECS 实例首次请求时 IMDS 尚未返回临时凭证若直接签名会失败。7.2 订阅/通知模型整套机制建立在订阅/通知subscription/notification模型之上核心流程如下订阅阶段凭证提供链在初始化时对链内每个元数据提供器调用subscribeToCredentialUpdates见 credential_provider_chains.cc 的setupSubscriptions通知阶段元数据提供器成功或失败获取凭证后通过onCredentialUpdate回调通知已订阅的凭证提供链CredentialSubscriberCallbacks接口定义在 credentials_provider.h。订阅句柄使用 RAII weak_ptr管理保证提供器可能是单例比链存活更久时也不会悬挂等待阶段签名器在签名请求时调用凭证链的addCallbackIfCredentialsPending(cb)若凭证当前不可用则把回调存入队列并返回true当链收到onCredentialUpdate通知后会依次触发所有等待回调对应 credentials_provider.h 中credential_pending_callbacks_列表恢复阶段回调触发后暂停的请求继续执行签名并放行。7.3 各扩展的接入方式每个使用签名异步能力的扩展都通过addCallbackIfCredentialsPending在凭证未就绪时暂停自身执行流。Signer接口的注释signer.h明确约定返回true表示凭证 pending 且回调已入队返回false表示凭证已就绪可以立即签名。这一约定让上层扩展无需关心凭证细节只需遵循“先检查 pending、再签名”的两步式流程。八、从配置到运行一次完整的签名请求旅程结合上述机制可以串起一次典型的签名请求完整链路扩展如aws_request_signing启动时调用defaultCredentialsProviderChain或customCredentialsProviderChain构建凭证提供链credential_provider_chains.cc链构造期间元数据类提供器通过AwsClusterManager申请内部集群并注册上线回调集群管理器按目标去重必要时创建 STATIC/LOGICAL_DNS 集群aws_cluster_manager.h集群上线后通知提供器提供器通过MetadataFetcher异步抓取凭证首刷采用 2 秒起、最大 30 秒的指数退避凭证抓取期间签名器调用addCallbackIfCredentialsPending挂起等待凭证就绪后经setCredentialsToAllThreads广播到所有线程并通知订阅链metadata_credentials_provider_base.h凭证就绪后签名器按 SigV4/SigV4A 计算规范请求、生成Authorization头或预签名查询参数并放行请求之后按 1 小时刷新周期含 60 秒宽限期与最多 30 秒抖动在后台静默续期保证代理长期运行不掉线。九、进一步探索指引组件根目录与架构说明source/extensions/common/aws/README.md凭证提供链的实现与默认链构建credential_provider_chains.cc、credential_provider_chains.h各类凭证提供器credential_providers元数据提供器基类与抓取器metadata_credentials_provider_base.h、metadata_fetcher.h集群管理器aws_cluster_manager.h、aws_cluster_manager.cc签名器接口与实现signer.h、signer_base_impl.h、signers凭证与订阅模型定义credentials_provider.h结语Envoy 的 AWS 公共组件用一套与 AWS SDK 对齐、但面向代理场景重构的设计解决了代理层签名的三大难点凭证来源多样化环境、文件、容器、实例元数据、STS、Roles Anywhere 六类来源通过链式降级统一、凭证获取的异步化订阅通知 回调暂停保证请求在凭证就绪前不失败、集群资源的去重复用固定单例集群管理器按目标共享集群并广播就绪事件。理解这四层机制是深入定制aws_request_signing与aws_lambda扩展、排查“请求签名失败/凭证过期”类问题的基础。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价