使用Terraform在AWS OpenSearch注册快照仓库的CI认证问题排查
我正在使用Terraform OpenSearch Provider 1.0在AWS OpenSearch 1.3上注册快照仓库,代码如下:
Provider配置
provider "opensearch" { alias = "manager" url = local.opensearch_endpoint_url aws_region = var.region aws_assume_role_arn = local.opensearch_snapshot_manager_role_arn }
快照仓库资源
resource "opensearch_snapshot_repository" "this" { provider = opensearch.manager name = "main_s3" type = "s3" settings = { bucket = var.snapshot_bucket_name region = var.region role_arn = var.snapshot_role_arn } }
这段代码在本地使用个人AWS凭证运行时可成功执行,但在EKS中运行的GitLab CI Runner使用Runner凭证执行时失败,报错如下:
╷ │ Error: NoCredentialProviders: no valid providers in chain. Deprecated. │ For verbose messaging see aws.Config.CredentialsChainVerboseErrors │ │ with module.opensearch_config[0].opensearch_snapshot_repository.this[0], │ on modules/terraform-opensearch-config/main.tf line 60, in resource "opensearch_snapshot_repository" "this": │ 60: resource "opensearch_snapshot_repository" "this" { │ ╵
该CI Runner可正常使用Terraform AWS Provider创建AWS资源,说明Runner配置无误,问题仅存在于CI Runner与Terraform OpenSearch Provider的组合使用场景中。请问Terraform OpenSearch Provider是如何解析AWS凭证的?该如何调试此认证问题?
Terraform OpenSearch Provider(1.0版本)基于AWS SDK for Go实现凭证解析,遵循以下优先级顺序:
- 显式配置凭证:优先使用
provider "opensearch"块中直接设置的aws_access_key、aws_secret_key、aws_session_token参数
- 显式配置凭证:优先使用
- 环境变量:读取
AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKEN这三个环境变量
- 环境变量:读取
- AWS配置文件:默认读取
~/.aws/credentials和~/.aws/config文件,支持通过AWS_PROFILE环境变量切换配置文件
- AWS配置文件:默认读取
- 实例元数据服务(IMDS):如果运行在EKS Pod或EC2实例中,自动从IMDS获取绑定的IAM角色凭证
- 假定角色:如果配置了
aws_assume_role_arn,会先通过上述凭证链获取基础凭证,再调用sts:AssumeRole获取目标角色的临时凭证
- 假定角色:如果配置了
注意:当配置aws_assume_role_arn时,Provider必须先拿到有效的基础凭证才能执行角色假定操作,这一步失败就会抛出NoCredentialProviders错误。
1. 验证Runner的基础凭证有效性
在CI Runner的执行步骤中添加以下命令,测试基础凭证是否能被AWS SDK正常识别:
# 验证当前身份 aws sts get-caller-identity # 开启凭证链详细错误日志,排查具体缺失环节 export AWS_SDK_LOAD_CONFIG=1 export AWS_CREDENTIALS_CHAIN_VERBOSE_ERRORS=1 aws sts get-caller-identity
如果这一步报错,说明Runner的基础凭证本身存在问题;如果成功,说明问题出在OpenSearch Provider对凭证的处理逻辑上。
2. 开启OpenSearch Provider的调试日志
在Provider配置中添加日志参数,输出详细的凭证链调试信息:
provider "opensearch" { alias = "manager" url = local.opensearch_endpoint_url aws_region = var.region aws_assume_role_arn = local.opensearch_snapshot_manager_role_arn # 开启调试日志 log_path = "/tmp/opensearch-provider.log" log_level = "debug" }
运行Terraform后,查看/tmp/opensearch-provider.log,日志中会记录凭证链的每一步尝试过程,可明确哪一步未找到有效凭证。
3. 显式指定凭证来源(临时调试用)
在CI环境中通过以下方式强制指定凭证来源,验证是否能正常工作:
- 方法1:直接从IMDS获取Pod角色凭证并设置为环境变量
ROLE_NAME=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/) export AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME/AccessKeyId) export AWS_SECRET_ACCESS_KEY=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME/SecretAccessKey) export AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME/Token) - 方法2:在Provider块中强制启用IMDS凭证获取
provider "opensearch" { alias = "manager" url = local.opensearch_endpoint_url aws_region = var.region aws_assume_role_arn = local.opensearch_snapshot_manager_role_arn use_aws_metadata_service = true }
4. 检查假定角色的权限配置
确保Runner使用的基础IAM角色(EKS Pod绑定的角色)拥有sts:AssumeRole权限,同时目标角色(local.opensearch_snapshot_manager_role_arn)的信任策略允许该基础角色的ARN:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<账号ID>:role/<EKS-Pod角色名>" }, "Action": "sts:AssumeRole" } ] }
5. 对比本地与CI环境的差异
- 本地可能使用了指定的
AWS_PROFILE,但CI环境中未设置该变量,导致Provider读取默认配置失败 - 检查CI环境中是否存在
AWS_CONFIG_FILE或AWS_SHARED_CREDENTIALS_FILE环境变量,是否指向了不存在的配置文件
内容的提问来源于stack exchange,提问作者G Quintana

