S3 버킷의 Permission에 대해 알아보자

1. 읽기 전에

최근에 사내에서 진행한 해커톤에서 백엔드 개발을 담당할 일이 있었습니다.

간략하게 설명하면 웹페이지를 통해 사용자가 업로드한 반려견의 이미지에서 감정을 분석하여 이목구비에 귀여운 스티커를 붙여주는 프로젝트였는데, 이 과정에서 AWS의 S3 버킷의 접근 권한을 깊게 들여다봐야할 필요가 생겼습니다.

평소에는 공식 다큐먼트에서 추천하는 세팅대로 진행한지라 깊은 이해를 하지는 못했었는데요, 이번 글을 통해 S3 버킷에 접근 권한을 어떤 방식으로 부여할 수 있는지 AWS 콘솔의 Permissions 탭을 중심으로 간단히 정리해보고자 합니다.

👨‍👩‍👧‍👦 예상 독자 : AWS S3 버킷의 Permissions 탭의 존재를 알고, 설정도 해보았지만 모든 설정에 대해서는 ‘다음에 기회되면 공부해야지’ 하셨던 분들


2. S3 버킷의 Permissions

Permissions 탭에는 어떤 설정들이 있나요?

S3의 Object는 기본적으로 해당 버킷을 생성한 AWS 계정만 접근이 가능합니다.

하지만 해당 버킷을 다른 사용자도 접근하게 하고싶게 할 수도 있고, 아니면 쿨하게(?) 모두가 접근 가능하게 오픈해야할 수도 있겠죠? 버킷의 use case에 따라 세부적인 접근 권한은 모두 다를텐데요, 이를 위해 S3 버킷에서 지원하는 세부 설정에는 다음과 같은 옵션들이 있습니다.

(1) Access control list(ACL)

(2) Object Ownership

(3) Block public access

(4) Bucket policy

(5) Cross-origin resource sharing(CORS)

아래에서 설명할 옵션들은 실제 콘솔에서 보이는 순서와 다를 수 있는데요, 각 옵션들의 이해를 돕기 위해 먼저 설명이 필요한 개념들이 자연스럽게 이해되도록 일부 순서를 조정해보았습니다.

📌 2.1 Access Control List(ACL)

S3 버킷을 다루다보면 ACL이라는 키워드를 한 번쯤은 보셨을겁니다.

비교적 최근 S3를 사용하게된 제 입장에서는 낯선 개념이기도 하고, ‘실제로 사용하지는 않는 것 같은데 도대체 언제 사용하는 거지?’ 라고 생각도 했었습니다.

자극적인 썸네일… 시청하지 않을 수 없다.


실제로 검색을 해보니, S3가 처음 세상에 나온 2006년(IAM Policy라는 개념이 존재하지도 않았던)에 접근 제어를 위한 개념으로 ACL이 사용되었다고 합니다. 다음과 같이요.

  • 버킷과 object에는 각각 ACL을 가지고 있음. 이 ACL을 통해 어느 AWS account, 그룹이 어떤 유형의 접근 권한을 가질 수 있는지를 정의할 수 있음. 해당 버킷이나 object에 접근 요청이 발생하면, S3는 ACL을 체크함.
  • default로 만약 내가 소유한 버킷에 다른 계정이 object를 업로드하면 해당 object는 업로드를 한 계정이 소유하게 됨. 다른 사용자에게 사용 권한을 주고싶다면 ACL을 통해 부여할 수 있음.

S3를 실제로 사용하셨던 분들이라면 위와 같은 내용들은 Bucket Policy나 IAM을 통해 정의해보셨을 겁니다.

Permissions 탭의 다른 설정들의 설명에도 나와있지만, object에 대한 접근을 개별적으로 제어해야하는 use case가 아니라면 Object Ownership 설정에서 ACL 사용을 disabled로 놓고 사용하는 것을 추천한다고 합니다.

현재는 Policy(IAM Policy나 Bucket Policy, VPC endpoint policy, AWS Organization SCP)를 통한 접근 관리가 가능하기 때문이죠!

참고 : Access control list (ACL) overview

📌 2.2 Object Ownership

2.1의 내용에서 설명했듯이, 해당 옵션은 ACL 설정을 disabled할 것인지를 설정할 수 있는 옵션이라고 생각하면 좋을 것 같습니다.

ACL 설정을 disabled로 설정하면 자동으로 버킷 소유자가 자동으로 모든 object에 대한 권한을 가지게 됩니다.

object를 업로드한 다른 계정의 소유자들에 대한 접근 권한 설정은 policy를 통해서만 할 수 있게 되므로 접근 관리가 복잡해지는 경우를 방지할 수 있겠죠?

참고 : Controlling ownership of objects and disabling ACLs for your bucket

📌 2.3 Block public access

기본적으로 S3의 버킷과 하위의 Object들은 private하지만, 해당 메뉴에서 S3 리소스들에 대한 public한 접근을 세부적으로 세팅할 수 있습니다.

  • access point :
    S3 버킷에 접근할 수 있도록 Bucket Policy에 application에 따라 서로 다른 접근 권한 수준을 설정하는 것은 매우 번거롭죠… application이 좀만 더 많아져도 관리하는 것도 힘들어질 것이구요. 이런 불편함을 줄이고자 S3에서는 access point라는 기능을 제공합니다.

S3에 대한 접근 요청이 발생하면, 우선은 block public access 설정이 적용되었는지를 확인하는데요.

예를들어 만약 access point를 통한 접근 요청이 발생하는 경우, access point에 대한 block public access 설정을 확인하고, 접근을 거부하는 설정이 되어있다면 해당 요청을 거부합니다.

Block public access에는 4가지 설정 있습니다.

(1) 해당 옵션이 활성화 된 이후에 버킷에 ACL 설정이 public인 이벤트들은 모두 fail처리합니다. 하지만 기존의 policy와 ACL은 설정을 유지합니다.

(2) 버킷과 내부의 object들에 설정된 모든 public ACL을 fail 처리합니다. 하지만 ACL 설정이 public인 PUT 요청은 가능합니다.

(3) 기존의 액세스 포인트나 bucket policy를 제외한 것들에 대한 public 접근을 막습니다. 해당 설정을 통해 온전히 Bucket policy와 access point를 통한 접근 제어가 가능해지죠.

(4) public 또는 cross-account(다른 AWS 계정)에서 접근하는 것을 막습니다. 버킷 소유 계정의 user만 접근할 수 있게 됩니다.

📌 2.4 Bucket Policy

IAM에서의 policy와 비슷하게, 해당 버킷에 접근할 수 있는 조건을 json 형식으로 정의할 수 있습니다. S3 버킷의 콘솔 내부에서 정의할 수 있으며, 친절하게(?) generator까지 제공하고있습니다.

Bucket Policy를 정의하는 json 파일 내에서 반드시 알아야할 값들을 간단하게 설명하자면 다음과 같습니다.

  • Resources : Action에 정의된 내용들을 allow/deny할 S3의 리소스들(버킷, object 등)을 명시합니다. 리소스의 ARN값을 사용합니다.
  • Actions : S3의 Resource에 대해 allow/deny할 작업을 명시합니다.
  • Effect : Resource에 대한 Action을 allow할지 deny할지 명시합니다. 기본적으로 아무것도 명시하지 않으면 policy는 접근을 막는 방향으로 설정되기 때문에, allow하고 싶은 action이 있다면 allow를 명시해야합니다.
  • Principal : 위에서 정의한 것들을 누구에게 해당시킬 것인지를 명시합니다. AWS 계정이나 IAM user, 다른 AWS 리소소(Lambda, SQS 등) 등을 명시합니다.
  • Condition : 해당 Bucket policy의 효과가 어떤 조건을 만족해야 발휘되게 할 것인지를 명시합니다.

    한 번 예시를 통해 정리해볼까요?
    {
      "Version": "2012-10-17",
      "Id": "ExamplePolicy01",
      "Statement": [
          {
              "Sid": "ExampleStatement01",
              "Effect": "Allow",
              "Principal": {
                  "AWS": "arn:aws:iam::123456789012:user/Dave"
              },
              "Action": [
                  "s3:GetObject",
                  "s3:GetBucketLocation",
                  "s3:ListBucket"
              ],
              "Resource": [
                  "arn:aws:s3:::awsexamplebucket1/*",
                  "arn:aws:s3:::awsexamplebucket1"
              ]
          }
      ]
    }
    

위에서 설명한 것들을 대입해서 생각해보면, IAM user인 Dave에게 awsexamplebucket1 버킷에 대해 GetObject, GetBucketLocation, ListBucket 를 Allow하는 policy라고 이해할 수 있겠죠?

참고 : Policies and Permissions in Amazon S3

📌 2.5 Cross-origin resource sharing(CORS) (내용 정정, 2022-06-06)

S3를 파일 보관용으로 사용하는 경우가 대부분이지만, 이외에도 정적 웹 사이트를 호스팅하기위한 용도로도 사용되곤 합니다.

이렇게 호스팅한 웹페이지가 다른 도메인의 리소스와 상호작용을 하기 위해서는 보안을 위한 CORS 설정이 필수인데요, 이 옵션을 통해 호스팅하는 웹페이지가 다른 도메인의 리소스에 접근할 수 있게 됩니다.브라우저를 통해 접속한 특정 오리진이 나의 S3 리소스에 접근할 수 있게 됩니다.

다시 말해 버킷이나 object에 대한 접근 제어라기보다는, 브라우저를 통해 접속한 특정 오리진에서 보낸 리소스 요청을 허락할 때 사용됩니다.

📝 정적 웹사이트 : 이미 저장된 HTML 문서를 클라이언트에게 전송하는 웹페이지, 내용이 자주 바뀌지 않는 정적 컨텐츠를 보여줄 때 사용됩니다.

참고 : MDN Web Docs


3. 글을 마치며

이번 글을 기록하며 S3의 Permission 관련 옵션들을 알아보았는데요,

가장 중요한 내용만 요약해보면 ‘ACL 관련된 옵션은 설정하지 말고, Bucket Policy 또는 IAM(User, Role, Policy)을 사용하자!’ 라고 말할 수 있을 것 같습니다.

AWS의 리소스들을 공부하다보면 여러 키워드들 간의 관계를 기억하는 게 중요한데, 이번 글에서 끝나는 게 아니라 이후의 글에서도 다뤄봐야겠습니다.

만약 본 글에서 잘못된 부분이나 오해의 소지가 있는 내용이 있다면 언제든 댓글 달아주세요. 감사합니다.