
Envoy Credential Injector 过滤器文件型密钥尾部换行剥离修复解析【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy导读本文围绕 EnvoyCloud-native high-performance edge/middle/service proxy中 credential_injector HTTP 过滤器的一处关键缺陷修复展开当凭证credential从基于文件的 generic secret 加载时文件末尾常见的换行符CR/LF会被原样注入到 HTTP 请求头由于 HTTP 头值不允许包含 CR/LF导致产生非法头并使请求失败。文章将从缺陷根因、修复实现、源码级验证到完整配置实践带你彻底掌握凭证注入过滤器的正确用法与这一修复的工程意义。一、缺陷概述换行符进入 HTTP 头引发的请求失败原文档 credential_injector__strip-trailing-newline.rst 记录了一个典型的文件格式与协议约束冲突类 Bug从文件型 generic secret 中加载的凭证被原样注入请求头包括 secret 文件中常见的尾部换行符。由于 HTTP 头值不能包含 CR/LF这会产生非法头导致请求失败。现在注入前会剥离凭证尾部的 CR/LF 字符且仅由 CR/LF 字符组成的凭证会被视为缺失。这一缺陷的成因链条非常清晰运维实践中密钥token、密码等通常以文件形式挂载如 Kubernetes Secret 卷、配置管理工具生成的文件而绝大多数文本文件都以换行符结尾credential_injector 过滤器读取文件内容后将原样verbatim写入 HTTP 请求头HTTP 协议规范RFC 7230明确禁止头字段值中出现 CR/LF导致下游服务器拒绝请求甚至引发解析错误。修复后的行为分两点剥离尾部 CR/LF注入前将凭证末尾的\r、\n全部移除保证注入到头部的值合法纯换行视为缺失如果剥离后凭证为空字符串即原文件只有换行符则按凭证缺失处理而不是注入空头。二、修复的源码级实现2.1 核心剥离逻辑位于 Generic 凭证注入器该修复的核心代码位于 generic_impl.cc 的GenericCredentialInjector::inject方法absl::Status GenericCredentialInjector::inject(Envoy::Http::RequestHeaderMap headers, bool overwrite) { if (!overwrite !headers.get(header_).empty()) { return absl::AlreadyExistsError(Credential already exists in the header); } // Secret files commonly end with a trailing newline, which is not allowed in HTTP header // values. Strip trailing CR/LF so the injected header is valid. absl::string_view credential secret_reader_-credential(); while (!credential.empty() (credential.back() \n || credential.back() \r)) { credential.remove_suffix(1); } if (credential.empty()) { return absl::NotFoundError(Failed to get credential from secret); } headers.setCopy(header_, absl::StrCat(header_value_prefix_, credential)); return absl::OkStatus(); }逐行解读实现要点循环剥离使用while而非单次if因为文件尾部可能同时存在\r\nWindows 风格或多个换行循环保证全部剥离先判空再注入剥离后若为空返回absl::NotFoundError即凭证缺失语义不会注入空头值剥离发生在注入前header_value_prefix_如Basic 拼接之前就已完成清洗因此Authorization头最终值为Basic dXNlcjpwYXNz这种干净格式只改尾部凭证中间若存在换行不会被处理那属于非法凭证本身修复目标是文件格式带来的尾部换行。2.2 调用链从过滤器到注入器从 config.cc 的工厂代码可以看到完整装配流程createFilterFactoryFromProtoHelper通过Envoy::Config::Utility::getFactoryNamedCredentialInjectorConfigFactory按TypedExtensionConfig查找注册的注入器工厂类别为envoy.http.injected_credentials见 factory.h调用createCredentialInjectorFromProto创建注入器实例构造FilterConfig持有injector_、overwrite_、allow_request_without_credential_返回过滤器工厂回调将CredentialInjectorFilter注册为流解码过滤器stream decoder filter。请求处理路径在 credential_injector_filter.cc 的decodeHeaders中触发注入Envoy::Http::FilterHeadersStatus CredentialInjectorFilter::decodeHeaders(Envoy::Http::RequestHeaderMap headers, bool) { bool succeed config_-injectCredential(headers); if (!succeed) { decoder_callbacks_-sendLocalReply(Envoy::Http::Code::Unauthorized, Failed to inject credential., nullptr, std::nullopt, failed_to_inject_credential); return Envoy::Http::FilterHeadersStatus::StopIteration; } return Envoy::Http::FilterHeadersStatus::Continue; }FilterConfig::injectCredential对injector_-inject()的三种返回状态分别处理状态场景行为AlreadyExistsError头部已有凭证且overwritefalse增加already_exists计数放行其他错误含NotFoundError注入失败或凭证缺失增加failed计数默认返回 401若allow_request_without_credentialtrue则放行OkStatus注入成功增加injected计数继续处理注意剥离后凭证为空产生的NotFoundError正是上文所述的纯换行视为缺失最终在过滤器层表现为 401除非配置允许无凭证请求。2.3 凭据来源SDS 文件型 generic secretGeneric 注入器通过 SDSSecret Discovery Service读取凭证。credential字段配置sds_config的path_config_source即指向本地 YAML 文件其中声明envoy.extensions.transport_sockets.tls.v3.Secret类型的generic_secret。正是这种从文件读取的模式让尾部换行成为高频问题。三、测试验证集成测试如何证明修复有效仓库在 credential_injector_integration_test.cc 中新增了专门的集成测试用例InjectCredentialStripsTrailingNewline测试文件第 300–348 行完整模拟了生产场景// A trailing newline in the secret (common in file-based secrets) is stripped before the // credential is injected, so the resulting header is valid. TEST_P(CredentialInjectorIntegrationTestAllProtocols, InjectCredentialStripsTrailingNewline) { TestEnvironment::writeStringToFileForTest(credential_newline.yaml, REOF( resources: - type: type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret name: credential_newline generic_secret: secret: inline_string: dXNlcjpwYXNz\n)EOF, false); ...测试验证链路将包含显式尾部换行\n的 base64 凭证dXNlcjpwYXNz即user:pass写入临时 secret 文件配置envoy.filters.http.credential_injector过滤器通过header_value_prefix: Basic 注入Authorization头发起请求并断言上游实际收到的头值为Basic dXNlcjpwYXNz——没有任何换行断言http.config_test.credential_injector.injected计数器为 1证明注入路径成功执行。该测试说明修复不仅是静态代码改动而是有端到端集成测试兜底的可靠行为变更。四、完整配置实践Basic Auth 与 Bearer Token原文档对应的 API 定义位于 credential_injector.proto过滤器类型名为envoy.filters.http.credential_injector。配置项如下字段类型默认值说明overwriteboolfalse目标头已存在时是否覆盖allow_request_without_credentialboolfalse凭证缺失或注入失败时是返回 401 还是放行至上游credentialTypedExtensionConfig必填凭证注入器扩展类别envoy.http.injected_credentials如 generic、oauth24.1 HTTP Basic Auth 场景过滤器配置generic 注入器 文件型 SDS 凭证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: Authorizationcredential.yamlBasic Auth 凭证注意带尾部换行——这正是本次修复处理的场景resources: - type: type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret name: credential generic_secret: secret: inline_string: Basic base64EncodedUsernamePassword修复前注入的Authorization值为Basic base64EncodedUsernamePassword\n非法 修复后剥离尾部换行值为Basic base64EncodedUsernamePassword合法。4.2 Bearer Token 场景resources: - type: type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret name: credential generic_secret: secret: inline_string: Bearer myToken同样即使文件末尾带换行注入后也会得到干净的Bearer myToken头值。4.3 关于 401 与放行语义根据 proto 注释与源码行为默认情况下若凭证缺失或注入失败请求会以401 Unauthorized失败本地回复Failed to inject credential.reason 为failed_to_inject_credential只有显式设置allow_request_without_credential: true请求才会不带凭证转发到上游。此过滤器用于工作负载身份认证workload authentication典型如 sidecar 部署不处理终端用户认证设计初衷是代表其背后的工作负载完成身份声明。五、修复的价值与使用建议5.1 为什么这个修复重要消除隐性故障此前用户按常规方式echo 写入密钥文件几乎必然以换行结尾导致注入的请求头非法、请求静默失败且排障时很难联想到换行符对齐协议约束HTTP/1.1RFC 7230与 HTTP/2 均不允许头值携带 CR/LF修复让注入器在源头保证头值合法性统一空凭证语义纯换行文件被等价于空凭证触发与缺失凭证一致的 401/放行逻辑行为可预期。5.2 使用建议凭证文件由系统工具echo、printf、Kubernetes Secret 卷生成时不必再手动tr -d \n预处理Envoy 会在注入前自动清洗尾部换行若希望凭证中不允许出现任何空白可在上游做二次校验本次修复聚焦尾部 CR/LF不影响凭证中间内容升级到包含此修复的版本后原先生效但带换行的配置会自动获得合法头值属于向后兼容的行为修复bug fix详见 changelogs/current 目录下的修复记录归档方式。六、小结本次修复以极小的代码量一次循环剥尾 判空解决了文件型密钥场景下HTTP 头非法导致请求失败的典型痛点并配套了端到端集成测试与 changelog 记录。理解这一修复不仅让你在使用 credential_injector 时少踩坑也展示了 Envoy 在处理协议约束与文件格式差异时的工程化思路源头清洗、语义归一、测试兜底。完整 API 定义与示例可继续阅读 credential_injector.proto 与 credential_injector_filter.rst。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考