開発環境のCodeCommitでソースコードを管理し、同じ開発環境のアカウント内にあるEC2で開発者は動作確認をする。ステージングとプロダクション用のアカウントは別アカウントで運用しているときに、開発環境で検証されたコードへクロスアカウントアクセスしソースコードを取得しCodePipelineを使ってステージング、プロダクションへデプロイする。
■本番環境(ステージング、プロダクション)用アカウント
CodePipelineで必要なロールはすでに定義してありパイプラインも作成済みと仮定する。
CodePipelineのRoleに開発環境のクロスアカウントアクセス用ロールの引き受けを許可するAuumeRoleをインラインポリシーで追加する。
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": [
"arn:aws:iam::[開発環境のアカウントID]:role/クロスアカウントアクセス用サービスロール名"
]
}
}
CodeBuild、CodeDeploy用にデフォルトで作成されたロールは特に編集しない。
[CodePipeline用のIAMロール]
※上記のインラインポリシーは含まれていない
{
"Statement": [
{
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions"
],
"Resource": "[S3バケットのARN]",
"Effect": "Allow"
},
{
"Action": [
"s3:GetObjectVersion",
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"[S3バケットのARN]/*"
],
"Effect": "Allow"
},
{
"Action": [
"codecommit:CancelUploadArchive",
"codecommit:GetBranch",
"codecommit:GetCommit",
"codecommit:GetUploadArchiveStatus",
"codecommit:UploadArchive"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"codebuild:BatchGetBuilds",
"codebuild:StartBuild"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"codedeploy:CreateDeployment",
"codedeploy:GetApplication",
"codedeploy:GetApplicationRevision",
"codedeploy:GetDeployment",
"codedeploy:GetDeploymentConfig",
"codedeploy:RegisterApplicationRevision"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"elasticbeanstalk:CreateApplicationVersion",
"elasticbeanstalk:DescribeApplicationVersions",
"elasticbeanstalk:DescribeEnvironments",
"elasticbeanstalk:DescribeEvents",
"elasticbeanstalk:UpdateEnvironment",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeScalingActivities",
"autoscaling:ResumeProcesses",
"autoscaling:SuspendProcesses",
"cloudformation:GetTemplate",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResources",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeStacks",
"cloudformation:UpdateStack",
"ec2:DescribeInstances",
"ec2:DescribeImages",
"ec2:DescribeAddresses",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"ec2:DescribeSecurityGroups",
"ec2:DescribeKeyPairs",
"elasticloadbalancing:DescribeLoadBalancers",
"rds:DescribeDBInstances",
"rds:DescribeOrderableDBInstanceOptions"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"lambda:invokefunction",
"lambda:listfunctions"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"sns:*"
],
"Resource": "*",
"Effect": "Allow"
}
],
"Version": "2012-10-17"
}
[CodeDeploy用のIAMロール]
※AWSでデフォルトのAWSCodeDeployRole をアタッチ
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:CompleteLifecycleAction",
"autoscaling:DeleteLifecycleHook",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeLifecycleHooks",
"autoscaling:PutLifecycleHook",
"autoscaling:RecordLifecycleActionHeartbeat",
"autoscaling:CreateAutoScalingGroup",
"autoscaling:UpdateAutoScalingGroup",
"autoscaling:EnableMetricsCollection",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribePolicies",
"autoscaling:DescribeScheduledActions",
"autoscaling:DescribeNotificationConfigurations",
"autoscaling:DescribeLifecycleHooks",
"autoscaling:SuspendProcesses",
"autoscaling:ResumeProcesses",
"autoscaling:AttachLoadBalancers",
"autoscaling:PutScalingPolicy",
"autoscaling:PutScheduledUpdateGroupAction",
"autoscaling:PutNotificationConfiguration",
"autoscaling:PutLifecycleHook",
"autoscaling:DescribeScalingActivities",
"autoscaling:DeleteAutoScalingGroup",
"ec2:DescribeInstances",
"ec2:DescribeInstanceStatus",
"ec2:TerminateInstances",
"tag:GetTags",
"tag:GetResources",
"sns:Publish",
"cloudwatch:DescribeAlarms",
"cloudwatch:PutMetricAlarm",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeInstanceHealth",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
],
"Resource": "*"
}
]
}
[CodeBuild用のIAMロール]
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
"arn:aws:logs:ap-northeast-1:[本番環境のアカウントID]:log-group:[ロググループの場所]",
"arn:aws:logs:ap-northeast-1:[本番環境のアカウントID]:log-group:[ロググループの場所]:*"
],
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
},
{
"Effect": "Allow",
"Resource": [
"[CodeCommitのARN]"
],
"Action": [
"codecommit:GitPull"
]
},
{
"Effect": "Allow",
"Resource": [
"[S3バケットのARN]",
"[S3バケットのARN]/*"
],
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:GetBucketAcl",
"s3:GetBucketLocation"
]
}
]
}
次にアーティファクト保管用のS3バケットにバケットポリシーを適用する。
{
"Version": "2012-10-17",
"Id": "SSEAndSSLPolicy",
"Statement": [
{
"Sid": "DenyUnEncryptedObjectUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::[バケットの名前]/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "aws:kms"
}
}
},
{
"Sid": "DenyInsecureConnections",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::[バケットの名前]/*",
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[開発環境のアカウントID]:root"
},
"Action": [
"s3:Get*",
"s3:Put*"
],
"Resource": "arn:aws:s3:::[バケットの名前]/*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[開発環境のアカウントID]:root"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::[バケットの名前]"
}
]
}
次にKMSを使ってカスタマー管理Keyを作成する。
{
"Version": "2012-10-17",
"Id": "key-name",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[本番環境のアカウントID]:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[本番環境のアカウントID]:user/[アカウント名]"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::[本番環境のアカウントID]:role/[CodeBuild用のIAMロール]",
"arn:aws:iam::[開発環境のアカウントID]:root",
"arn:aws:iam::[本番環境のアカウントID]:role/[CodeDeploy用のIAMロール]",
"arn:aws:iam::[本番環境のアカウントID]:role/[CodePipeline用のIAMロール]"
]
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::[本番環境のアカウントID]:role/[CodeBuild用のIAMロール]",
"arn:aws:iam::[開発環境のアカウントID]:root",
"arn:aws:iam::[本番環境のアカウントID]:role/[CodeDeploy用のIAMロール]",
"arn:aws:iam::[本番環境のアカウントID]:role/[CodePipeline用のIAMロール]"
]
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}
EC2へ割り当てているロールにKMSへのアクセスを許可するインラインポリシーを追加
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": [
"kms:*"
],
"Resource": [
"[KeyのARN]"
]
}
}
AWS CLIでCodepipelineの設定をJSON形式でダウンロードし編集
aws codepipeline get-pipeline --profile [本番環境のアカウントID] --name [パイプラインの名前] > pipeline.json
{
"pipeline": {
"version": 8,
"roleArn": "CodePipeline用のIAMロール",
"stages": [
{
"name": "Source",
"actions": [
{
"inputArtifacts": [],
"name": "Source",
"roleArn": "[開発環境のアカウントID]:[クロスアカウントアクセス用のポリシー]",
"actionTypeId": {
"category": "Source",
"owner": "AWS",
"version": "1",
"provider": "CodeCommit"
},
"outputArtifacts": [
{
"name": "SourceArtifact"
}
],
"configuration": {
"PollForSourceChanges": "false",
"BranchName": "master",
"RepositoryName": "リポジトリ名"
},
"region": "ap-northeast-1",
"runOrder": 1
}
]
},
{
"name": "Build",
"actions": [
{
"inputArtifacts": [
{
"name": "SourceArtifact"
}
],
"name": "Build",
"region": "ap-northeast-1",
"actionTypeId": {
"category": "Build",
"owner": "AWS",
"version": "1",
"provider": "CodeBuild"
},
"outputArtifacts": [
{
"name": "BuildArtifact"
}
],
"configuration": {
"ProjectName": "プロジェクト名"
},
"runOrder": 1
}
]
},
{
"name": "Approval",
"actions": [
{
"inputArtifacts": [],
"name": "Approval",
"region": "ap-northeast-1",
"actionTypeId": {
"category": "Approval",
"owner": "AWS",
"version": "1",
"provider": "Manual"
},
"outputArtifacts": [],
"configuration": {
"NotificationArn": "[NortificationのARN]"
},
"runOrder": 1
}
]
},
{
"name": "Deploy",
"actions": [
{
"inputArtifacts": [
{
"name": "BuildArtifact"
}
],
"name": "Deploy",
"region": "ap-northeast-1",
"actionTypeId": {
"category": "Deploy",
"owner": "AWS",
"version": "1",
"provider": "CodeDeploy"
},
"outputArtifacts": [],
"configuration": {
"ApplicationName": "アプリケーション名",
"DeploymentGroupName": "デプロイグループ名"
},
"runOrder": 1
}
]
}
],
"name": "[パイプライン名]",
"artifactStores": {
"ap-northeast-1": {
"type": "S3",
"location": "[S3バケット名]",
"encryptionKey": {
"type": "KMS",
"id": "[KeyのARN]"
}
}
}
}
}
CodePipelineの設定をUpdateする。
aws codepipeline update-pipeline --profile [本番環境のアカウントID] --cli-input-json file://pipeline.json
■開発環境用アカウント
本番環境のCodeCommitアクセス用ロールにS3バケットおよびKMSへのアクセスを許可したクロスアカウントアクセス用のポリシーを定義し、本番環境のアカウントIDに対してAssumeRoleを許可する。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "UploadArtifactPolicy",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::[S3バケット名]/*"
]
},
{
"Sid": "KMSAccessPolicy",
"Effect": "Allow",
"Action": [
"kms:DescribeKey",
"kms:GenerateDataKey*",
"kms:Encrypt",
"kms:ReEncrypt*",
"kms:Decrypt"
],
"Resource": [
"[KeyのARN]"
]
},
{
"Sid": "CodeCommitAccessPolicy",
"Effect": "Allow",
"Action": [
"codecommit:GetBranch",
"codecommit:GetCommit",
"codecommit:UploadArchive",
"codecommit:GetUploadArchiveStatus",
"codecommit:CancelUploadArchive"
],
"Resource": [
"[CodeCommitリポジトリのARN]"
]
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[本番環境のアカウントID]:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}