这是对我有用的解决方案(感谢 Marcin 提供正确方向的提示)。
- 我有两个 IAM 用户:
deploy-staging 和 deploy-production。
- 我有一个 EC2 实例,可以部署到暂存环境或生产环境,具体取决于它所承担的 IAM 角色。
-
deploy-staging IAM 用户附加了以下 IAM 策略。此策略将允许此用户启动/停止用于将代码部署到 staging 的 EC2 实例,并将正确的 IAM 角色 (deploy-role-staging) 附加/分离到该 EC2 实例,以便它可以拥有部署到登台的正确权限。 这是此用户能够附加到此 EC2 实例的唯一 IAM 角色。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:DisassociateIamInstanceProfile",
"ec2:ModifySecurityGroupRules",
"ec2:StopInstances",
"ec2:AssociateIamInstanceProfile",
"ec2:ReplaceIamInstanceProfileAssociation"
],
"Resource": [
"arn:aws:ec2:*:account-id:security-group/sg-xxxxxxxxxxxxxx",
"arn:aws:ec2:us-east-1:account-id:instance/i-xxxxxxxxxxxxxx",
"arn:aws:ec2:*:account-id:security-group-rule/sgr-xxxxxxxxxxxxxx"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeIamInstanceProfileAssociations"
],
"Resource": "*"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::account-id:role/deploy-role-staging"
}
]
}
-
deploy-production IAM 用户附加了以下 IAM 策略。此策略将允许此用户启动/停止用于将代码部署到 生产 的 EC2 实例,并将正确的 IAM 角色 (deploy-role-production) 附加/分离到该 EC2 实例,以便它可以拥有部署到生产的正确权限。 这是此用户能够附加到此 EC2 实例的唯一 IAM 角色。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:DisassociateIamInstanceProfile",
"ec2:ModifySecurityGroupRules",
"ec2:StopInstances",
"ec2:AssociateIamInstanceProfile",
"ec2:ReplaceIamInstanceProfileAssociation"
],
"Resource": [
"arn:aws:ec2:*:account-id:security-group/sg-xxxxxxxxxxxxxx",
"arn:aws:ec2:us-east-1:account-id:instance/i-xxxxxxxxxxxxxx",
"arn:aws:ec2:*:account-id:security-group-rule/sgr-xxxxxxxxxxxxxx"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeIamInstanceProfileAssociations"
],
"Resource": "*"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::account-id:role/deploy-role-production"
}
]
}
-
deploy-role-staging IAM 角色附加了策略,允许它更新 S3 存储桶以进行暂存,并更新 Cloudfront 分发以进行暂存。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"cloudfront:GetInvalidation",
"cloudfront:CreateInvalidation"
],
"Resource": [
"arn:aws:cloudfront::account-id:distribution/XXXXXXXXXXXXX"
]
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:ListBucket",
"s3:DeleteObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::stagingXXX.example.com",
"arn:aws:s3:::stagingXXX.example.com/*"
]
}
]
}
-
deploy-role-production IAM 角色附加了策略,允许它更新用于生产的 S3 存储桶和用于生产的 Cloudfront 分发。
They're the same as for staging, except the ID of Cloudfront distribution and the S3 bucket names are different.
总结:每个用户只能让 EC2 实例担任特定角色,从而使该 EC2 实例能够访问不同的资源。
不要忘记编写代码以实际启动/停止 EC2 实例,使用这些 CLI 命令示例(通过 /bin/bash)附加/分离 IAM 角色:
# Get the current IAM role association for the EC2 instance.
EC2_IAM_ROLE_ASSOCIATION_ID=`aws ec2 describe-iam-instance-profile-associations --filters Name=instance-id,Values=XXXXXXXXXXXX --query 'IamInstanceProfileAssociations[*].AssociationId' --output text --profile XXXX`
# Only disassociate an IAM role if one is attached to the EC2 instance.
if [ "$EC2_IAM_ROLE_ASSOCIATION_ID" ]; then
# Disassociate any IAM role from the EC2 instance.
aws ec2 disassociate-iam-instance-profile --association-id $EC2_IAM_ROLE_ASSOCIATION_ID --profile XXXX
fi
# Attach the correct IAM Role to the EC2 instance.
EC2_IAM_ROLE_ASSOCIATION_ID=`aws ec2 associate-iam-instance-profile --instance-id XXXXXXXXXXXX --iam-instance-profile Name="$IAM_ROLE" --query 'IamInstanceProfileAssociation.AssociationId' --output text --profile XXXX`
# Disassociate any IAM Role from the EC2 instance.
aws ec2 disassociate-iam-instance-profile --association-id $EC2_IAM_ROLE_ASSOCIATION_ID --query 'IamInstanceProfileAssociation.State' --output text --profile XXXX