AWS

타 계정간 S3 버킷 객체 복사시 유의할 점

여기서 다루는 내용

· 타계정간 S3 객체를 복사하려면
· 복제의 나쁜 예
· 복제의 좋은 예
· 마치며


타 계정간 S3 객체를 복사하는 여러가지 방법


안녕하십니까, GS네오텍 최준승입니다.

오늘은 크게 어렵거나 중요한 내용은 아니지만 막상 당하면 매우 짜증이 나는
그래서 미리 알고 피하면 좋은 꿀팁 하나를 소개해 드리려고 합니다.

내용은 심플합니다. 두개의 서로 다른 AWS 계정이 있다고 가정해 봅시다.
A 계정에는 “Bucket-Source” 라는 S3 버킷이 하나 있고, B 계정에는 “Bucket-Target” 이라는 버킷이 있습니다.

Bucket-Source에 있는 객체를 Bucket-Target에 복사하려고 합니다. 방법은 두가지가 있습니다.

# Case1

  • A 계정의 IAM User/Role을 사용합니다
  • 해당 IAM User/Role에 붙는 IAM Policy에 Bucket-Source 버킷 읽기 권한을 부여합니다
  • 해당 IAM User/Role에 붙는 IAM Policy에 Bucket-Target 버킷 쓰기 권한을 부여합니다
  • B 계정에 존재하는 Bucket-Target의 Bucket Policy에 A 계정의 쓰기 권한을 부여합니다

# Case2

  • B 계정의 IAM User/Role을 사용합니다
  • 해당 IAM User/Role에 붙는 IAM Policy에 Bucket-Source 버킷 읽기 권한을 부여합니다
  • 해당 IAM User/Role에 붙는 IAM Policy에 Bucket-Target 버킷 쓰기 권한을 부여합니다
  • A 계정에 존재하는 Bucket-Source의 Bucket Policy에 B 계정의 읽기 권한을 부여합니다

뭐가 다르냐구요? 잘 보면 뭔가 다릅니다. 이해를 위해 그림 그려 드립니다.


※ 한참 뚫어져라 보면.. 2개 방법의 차이를 알 수 있습니다

IAM 권한을 어느 계정에서 부여하는지가. 아무래도 좀 다른것 같긴 한데.
결국 객체를 복사한다는 측면에서 엎어치나 메치나 뭐가 다르냐라고 생각할 수 있습니다.

하지만 결론부터 말씀드리면. Case1은 복제의 나쁜 예 / Case2는 복제의 좋은 예가 됩니다.

왜일까요?


복제의 나쁜 예


Case1이 복제의 나쁜 예라고 하는데, 정말 그런지 실제로 한번 해봅시다.

우선 A 계정에 IAM Role을 하나 만들고 AWSCLI가 설치된 EC2에 매핑해 보겠습니다.
해당 IAM Role에는 아래와 같은 IAM Policy를 Inline 형태로 붙여 줍니다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::Bucket-Source",
        "arn:aws:s3:::Bucket-Source/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": [
        "arn:aws:s3:::Bucket-Target",
        "arn:aws:s3:::Bucket-Target/*"
      ]
    }
  ]
}

그리고 B 계정에 있는 Bucket-Target의 Bucket Policy에 다음과 같은 권한을 설정합니다.
잘 보시면 Principal 항목에 A 계정 ID가 들어가 있고, Action 항목에 객체 쓰기 권한을 포함한 몇몇 권한이 들어가 있습니다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DelegateS3Access",
      "Effect": "Allow",
      "Principal": {
        "AWS": "Account A's AccountID"
      },
      "Action": [
        "s3:ListBucket",
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": [
        "arn:aws:s3:::Bucket-Target/*",
        "arn:aws:s3:::Bucket-Target"
      ]
    }
  ]
}

이제 A 계정의 IAM Role 권한을 들고
다음과 같이 복사를 수행해 보겠습니다.

$ aws s3 ls s3://Bucket-Source
2018-09-06 05:04:16      38973 chart_c4.png
2018-09-06 05:04:17      39080 chart_c5.png

$ aws s3 sync s3://Bucket-Source s3://Bucket-Target
copy: s3://jschoi.source/chart_c5.png to s3://jschoi.target.test/chart_c5.png
copy: s3://jschoi.source/chart_c4.png to s3://jschoi.target.test/chart_c4.png

복사 성공!

이제 B 계정에 들어가 복사가 되었는지 확인해 봅니다. 객체 목록은 잘 뜹니다.
하나를 골라 읽기를 시도했습니다.

안되네요? 읽기도 안되고 삭제도 안되고. 객체의 권한(Object ACL)을 수정할 수도 없습니다.
분명히 객체가 보이긴 하는데. 무엇도 할 수 없는 ‘그림의 떡’ 상태가 되었습니다.

이렇게 된 이유는 마지막에 알려드립니다.


복제의 좋은 예


Case2도 동일하게 따라가 봅시다.

우선 B 계정에 IAM Role을 하나 만들고 AWSCLI가 설치된 EC2에 매핑합니다.
해당 IAM Role에는 아래와 같은 IAM Policy를 Inline 형태로 붙여 줍니다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::Bucket-Source",
        "arn:aws:s3:::Bucket-Source/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": [
        "arn:aws:s3:::Bucket-Target",
        "arn:aws:s3:::Bucket-Target/*"
      ]
    }
  ]
}

그리고 A 계정에 있는 Bucket-Source의 Bucket Policy에 다음과 같은 권한을 설정합니다.
Principal 항목에 B 계정 ID가 들어가 있고, Action 항목에 객체 읽기 권한을 포함한 몇몇 권한이 들어가 있습니다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DelegateS3Access",
      "Effect": "Allow",
      "Principal": {
        "AWS": "Account B's AccountID"
      },
      "Action": [
        "s3:ListBucket",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::Bucket-Source/*",
        "arn:aws:s3:::Bucket-Source"
      ]
    }
  ]
}

이제 B 계정의 IAM Role 권한을 들고
다음과 같이 복사를 수행해 보겠습니다.

$ aws s3 ls s3://Bucket-Source
2018-09-06 05:04:16      38973 chart_c4.png
2018-09-06 05:04:17      39080 chart_c5.png

$ aws s3 sync s3://Bucket-Source s3://Bucket-Target
copy: s3://jschoi.source/chart_c5.png to s3://jschoi.target.test/chart_c5.png
copy: s3://jschoi.source/chart_c4.png to s3://jschoi.target.test/chart_c4.png

똑같이 복사 성공!

읽어보면? 잘됩니다.
삭제해보면? 잘됩니다.
Object ACL을 바꿔보면? 잘됩니다. 역시 좋은 예.

나쁜 예와 좋은 예는 어디에서 차이가 발생했을까요?

복사된 객체의 Object ACL을 살펴보면 다음과 같습니다.

# Case1

# Case2

차이가 보이시나요?

Case1의 경우 복사를 수행한 주체가 A 계정입니다. 따라서 B 계정 버킷에 복사한 객체의 Object ACL 권한이 B 계정에겐 없습니다.
Case2의 경우 복사를 수행한 주체가 B 계정입니다. 따라서 B 계정 버킷에 복사한 객체의 Object ACL 권한이 B 계정에게 있습니다.

물론 Case1에서도 파라미터로 통해 명시적으로 권한을 부여하면 가능은 합니다만.. 여기서는 언급하지 않겠습니다.


마치며


요즘은 한 회사 내에서도 여러개의 AWS 계정을 사용하곤 합니다.
개발/운영 환경을 나누기도 하고. 게임사에서는 게임별로 계정을 나누기도 하지요.

이때 다른 계정간에 S3 객체를 복사할 일은 빈번하게 생기게 됩니다.
꼭 같은 회사가 아니더라도 다른 회사 계정에 있는 S3 객체를 가져와야 하는 경우도 종종 있습니다.

이런 시점에 만일 내가 복사를 받아와야 하는 입장인데
1) 내 계정에서 IAM 객체를 만들고 해당 키값을 써야 하는지
2) 아님 원본 계정에서 IAM 객체를 만들고 해당 키값을 달라고 해야 하는지 애매할 때가 있습니다.

오늘 예를 보시면. 내 계정에서 IAM 객체를 만들고 해당 키값을 쓰는게 맞습니다.
원본 계정에서는 Bucket Policy만 수정해주면 되니까 더욱 깔끔하겠죠?

그럼 마치겠습니다.

읽어주셔서 감사합니다.

끝!

Related Post

태그 : , ,

필자: 최준승

GS네오텍에서 일하고 있습니다. 정리하는 것을 좋아합니다

전체 게시물수 : 65

전체 조회수 : 1083

게시물 공유하기