如何通过Terraform在EC2上安全配置AWS CLI(GitLab流水线场景)
解决方案:通过Terraform安全配置EC2上的AWS CLI
核心结论
绝对不建议手动传递AWS密钥,AWS官方最佳实践是使用IAM实例角色——EC2启动后会自动获取临时凭证,无需aws configure或硬编码密钥,完全规避密钥泄露风险。如果有特殊场景需要使用固定密钥,可通过SSM Parameter Store安全存储并读取,但仍优先推荐IAM角色方案。
方案1:IAM实例角色(推荐)
通过Terraform创建IAM角色并关联到EC2实例,EC2会自动从元数据服务获取临时AWS凭证,AWS CLI默认会使用这些凭证,无需任何手动配置。
1. Terraform配置IAM角色与权限
# 创建允许EC2扮演的IAM角色 resource "aws_iam_role" "s3_scanner_role" { name = "s3-scanner-ec2-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } } ] }) } # 附加S3操作所需的最小权限(按需缩小资源范围) resource "aws_iam_role_policy" "s3_scanner_policy" { name = "s3-scanner-policy" role = aws_iam_role.s3_scanner_role.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "s3:ListAllMyBuckets", "s3:ListBucket", "s3:GetObject", "s3:PutObject" ] Resource = [ "arn:aws:s3:::your-script-bucket/*", # 脚本所在桶 "arn:aws:s3:::your-result-bucket/*", # 结果存储桶 "arn:aws:s3:::*" # 扫描所有桶的权限(可按需限制) ] } ] }) } # 创建实例配置文件(关联IAM角色到EC2) resource "aws_iam_instance_profile" "s3_scanner_profile" { name = "s3-scanner-instance-profile" role = aws_iam_role.s3_scanner_role.name }
2. Terraform配置EC2实例(自动执行脚本)
通过user_data自动完成脚本下载、执行、结果上传,无需手动操作:
resource "aws_instance" "s3_scanner" { ami = "ami-0c55b159cbfafe1f0" # 替换为你所在区域的Amazon Linux 2 AMI instance_type = "t2.micro" iam_instance_profile = aws_iam_instance_profile.s3_scanner_profile.name user_data = <<-EOF #!/bin/bash # Amazon Linux 2默认已预装AWS CLI,若用其他系统需自行安装 # yum install -y aws-cli # 从S3复制脚本到本地 aws s3 cp s3://your-script-bucket/path/to/scan-s3.sh /tmp/scan-s3.sh chmod +x /tmp/scan-s3.sh # 执行脚本并保存结果到S3 /tmp/scan-s3.sh > /tmp/s3-scan-result.txt aws s3 cp /tmp/s3-scan-result.txt s3://your-result-bucket/results/s3-scan-$(date +%Y%m%d%H%M).txt # 执行完成后自动关机,方便Terraform销毁 shutdown -h now EOF tags = { Name = "s3-scanner-instance" } }
3. GitLab流水线集成
在GitLab CI/CD配置中,按以下流程执行:
- 初始化Terraform并执行
terraform apply启动EC2及相关资源 - 等待EC2执行完脚本并关机(可通过
aws ec2 wait instance-stopped命令等待) - 执行
terraform destroy销毁所有资源,节约成本
方案2:SSM Parameter Store(特殊场景备用)
如果必须使用固定AWS密钥,可将密钥存储在SSM Parameter Store的加密参数中,通过IAM权限让EC2读取并配置CLI。
1. 预配置SSM参数
在AWS控制台创建两个SecureString类型的参数:
/s3-scanner/aws_access_key_id:存储你的AWS Access Key ID/s3-scanner/aws_secret_access_key:存储你的AWS Secret Access Key
2. Terraform配置权限与EC2
给IAM角色添加SSM参数读取权限,并在user_data中配置CLI:
# 新增SSM参数读取权限到IAM角色 resource "aws_iam_role_policy" "ssm_parameter_access" { name = "ssm-parameter-access" role = aws_iam_role.s3_scanner_role.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = ["ssm:GetParameter"] Resource = [ "arn:aws:ssm:${var.aws_region}:${var.aws_account_id}:parameter/s3-scanner/*" ] } ] }) } # EC2实例的user_data修改为以下内容 user_data = <<-EOF #!/bin/bash yum install -y aws-cli # 从SSM读取密钥并配置AWS CLI export AWS_ACCESS_KEY_ID=$(aws ssm get-parameter --name "/s3-scanner/aws_access_key_id" --with-decryption --query "Parameter.Value" --output text) export AWS_SECRET_ACCESS_KEY=$(aws ssm get-parameter --name "/s3-scanner/aws_secret_access_key" --with-decryption --query "Parameter.Value" --output text) aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY aws configure set region ${var.aws_region} # 后续脚本下载、执行、结果上传步骤同方案1 EOF
内容的提问来源于stack exchange,提问作者Krystian junior DevOps
相关产品推荐
相关产品推荐

