devops

하나의 CodePipeline로 여러 Account의 Codedeploy에 액세스하기 본문

DevOps/AWS

하나의 CodePipeline로 여러 Account의 Codedeploy에 액세스하기

vata500 2022. 10. 29. 11:47
반응형

개발을 위해서 용도와 목적에 따라 여러 Account를 활용해서 AWS 리소스를 사용한다. AWS CodePipeline은 일련의 CI/CD 과정을 통합한 서비스로, 운영 Account에서 여러 Account들의 CI/CD를 관리할 수 있어야 한다. 

이 포스팅에서는 운영 Account에서 소스코드를 받아 빌드하여 Artifact를 S3에 보관하는 것을 진행하고, 나머지 CodeDeploy만 다른 Account에서 배포하는 아키텍처를 구성해봤다.

 

이를 위해 Account, 리소스 간 연결을 위한 Role 생성과 리소스의 데이터 보호에 사용되는 KMS를 통해서 AccountA의 CodePipeline을 중심으로 AccountB, AccountC에 배포할 수 있는 위 아키텍처를 구성한다.

2. 구성방법

2.1 Create an AWS KMS encryption key

KMS는 Account간 서비스들의 데이터를 보호하는 암호화키 서비스다. 여기서 사용되는 Customer-managed key는 CodePipeline이 위치한 동일한 Region에서 생성되어야 한다.

2.1.1 To create a customer managed key

  • AccountA에서 KMS 콘솔에 접속하여 Customer managed key(대칭 유형, Symmetric)를 생성한다.
  • 키 사용자는 AccountA에서 사용하는 CodePipeline의 Role을 지정한다.
  • 다른 Account 계정에는 AccountB와 AccountC의 account ID를 입력한다.

2.2 Set up account policies and roles

2.2.1 Configure S3 policy and role in the account that will create the pipeline

 {
  "Version": "2012-10-17",
  "Id": "SSEAndSSLPolicy",
  "Statement": [
	{
  	"Sid": "DenyUnEncryptedObjectUploads",
	  "Effect": "Deny",
	  "Principal": "*",
	  "Action": "s3:PutObject",
	  "Resource": "arn:aws:s3:::codepipeline-us-east-2-1234567890/*",
	  "Condition": {
		"StringNotEquals": {
		"s3:x-amz-server-side-encryption": "aws:kms"
		}
	   }
	 },
	{
	  "Sid": "DenyInsecureConnections",
	  "Effect": "Deny",
	  "Principal": "*",
	  "Action": "s3:*",
	  "Resource": "arn:aws:s3:::codepipeline-us-east-2-1234567890/*",
	  "Condition": {
		"Bool": {
	  		"aws:SecureTransport": false
			}
		}
	  },
	{
	  "Sid": "",
	  "Effect": "Allow",
	  "Principal": {
		"AWS": "arn:aws:iam::012ID_ACCOUNT_B:root"
		},
	  "Action": [
            "s3:Get*",
            "s3:Put*"
        ],
	  "Resource": "arn:aws:s3:::codepipeline-us-east-2-1234567890/*"
	},
	{
	  "Sid": "",
	  "Effect": "Allow",
	  "Principal": {
	      "AWS": "arn:aws:iam::012ID_ACCOUNT_B:root"
			},
	  "Action": "s3:ListBucket",
  	"Resource": "arn:aws:s3:::codepipeline-us-east-2-1234567890"
	}
   ]
}

다른 Account 계정의 리소스를 사용하는 CodePipeline를 생성하기 위해서 S3 버킷과 관련된 Policy를 생성해야한다. Codepipeline의 artifact를 저장할 S3에 액세스하기 위해서 버킷 권한 설정이 필요하다.

미리 생성해둔 KMS, CodePipeline이 사용할 S3 버킷, s3에 접근할 AccountB와 AccountC를 입력한다.

2.2.2 Create a policy for the service role for CodePipeline

CodePipeline에 사용될 Inline Policy를 생성한다. AccountB와 AccountC의 ARN이 Resource로 지정되어 Role을 수임할 수 있도록 한다.

{
   "Version": "2012-10-17",
   "Statement": {
       "Effect": "Allow",
       "Action": "sts:AssumeRole",
       "Resource": [
           "arn:aws:iam::012ID_ACCOUNT_B:role/*"
       ]
   }
 }

2.2.3 Create a policy for the Amazon EC2 instance role

AccountB와 AccountC의 배포에 사용될 EC2의 Policy를 생성한다. 이 Policy를 통해서 Account의 CodePipeline의 S3에 접근하여 Artifact를 받아올 수 있도록 한다.

{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Effect": "Allow",
       "Action": [
         "s3:Get*"
       ],
       "Resource": [
         "arn:aws:s3:::codepipeline-us-east-2-1234567890/*"
       ]
     },
     {
       "Effect": "Allow",
       "Action": [
         "s3:ListBucket"
       ],
       "Resource": [
         "arn:aws:s3:::codepipeline-us-east-2-1234567890"
       ]
     }
   ]
 }

Inline Policy 하나 더 생성하여 아래와 같이 AWS KMS를 통해서 S3에 접근할 키 권한을 받아온다.

{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
           "kms:DescribeKey",
           "kms:GenerateDataKey*",
           "kms:Encrypt",
           "kms:ReEncrypt*",
           "kms:Decrypt"
          ],
        "Resource": [
           "arn:aws:kms:us-east-1:012ID_ACCOUNT_A:key/2222222-3333333-4444-556677EXAMPLE"
          ]
      }
   ]
}

2.2.4 Configure the cross-account role

AccountB와 AccountC에서 AccountA의 엔티티가 작업을 수행할 수 있는 Role를 생성한다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "codedeploy:CreateDeployment",
        "codedeploy:GetDeployment",
        "codedeploy:GetDeploymentConfig",
        "codedeploy:GetApplicationRevision",
        "codedeploy:RegisterApplicationRevision"
      ],
      "Resource": "*"
    }
  ]
}

위와 같은 Inline Policy를 생성, 연결하여 AccountA가 codedeploy 관련 action을 수행할 수 있도록 허용한다.

{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Effect": "Allow",
       "Action": [
         "s3:GetObject*",
         "s3:PutObject",
         "s3:PutObjectAcl",
         "codecommit:ListBranches",
         "codecommit:ListRepositories"                
       ],
       "Resource": [
         "arn:aws:s3:::codepipeline-us-east-2-1234567890/*"
       ]
     }
   ]
}

추가적으로 위의 Inline Policy를 생성, 연결하여 AccountA의 s3에 접근할 수 있도록 허용한다.

2.3 Edit the CodePipeline

콘솔 상으로 AccountA의 CodePipeline에서 AccountB와 AccountC의 CodeDeploy를 추가하는 것은 제약이 있다. 그래서 AWS CLI를 이용해서 AccountA의 CodePipeline의 JSON 구성 파일을 수정하여 적용해야한다.

$ aws codepipeline get-pipeline --name MyFirstPipeline >pipeline.json

--name 에는 CodePipeline의 이름을 넣어 구성된 json파일을 import한다.

{
  "artifactStore”: {
    "location": "codepipeline-us-east-2-1234567890", 
    "type": "S3",
    "encryptionKey": {
      "id": "arn:aws:kms:us-east-1:012ID_ACCOUNT_A:key/2222222-3333333-4444-556677EXAMPLE",
      "type": "KMS"
    }
  },

위와 같이 ‘encryptionKey’ 블록을 추가하여 미리 생성해둔 KMS ARN값을 넣어준다.

            {
                "name": "Staging",
                "actions": [
                    {
                        "inputArtifacts": [
                            {
                                "name": "MyAppBuild"
                            }
                        ],
                        "name": "ExternalDeploy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "version": "1",
                            "provider": "CodeDeploy"
                        },
                        "outputArtifacts": [],
                        "configuration": {
                            "ApplicationName": "AccountBApplicationName",
                            "DeploymentGroupName": "AccountBApplicationGroupName"
                        },
                        "runOrder": 1,
                        "roleArn": "arn:aws:iam::012ID_ACCOUNT_B:role/CrossAccount_Role"
                    }
                ]
            }

이제 CodePipeline에 새로운 스테이지를 추가하여 AccountB와 AccountC에 생성된 CodeDeploy를 추가한다. roleArn에는 미리 생성해뒀던 AccountA의 신뢰관계 Role의 ARN을 넣는다.

"metadata": {  
  "pipelineArn": "arn:aws:codepipeline:region:account-ID:pipeline-name",
  "created": "date",
  "updated": "date"
  }

마지막으로 ‘metadata’ 블록을 삭제하여 update-pipeline 명령어가 수행될 수 있도록 한다.

$ aws codepipeline update-pipeline --cli-input-json file://pipeline.json

수정된 pipeline.json 파일을 aws codepipeline update-pipeline 명령어를 통해서 apply하면 된다.

https://docs.aws.amazon.com/codepipeline/latest/userguide/pipelines-create-cross-account.html

반응형
Comments