React/Next.js

[Next.js] AWS S3 ACL Private 특정 유저만 접근 허용

bonevillain 2024. 3. 28. 20:29

Next.js AWS S3 이미지 업로드 테스트 소스코드

https://github.com/kimfame/next-s3

 

S3 버킷 설정을 직접 테스트하면서 겪었던 내용을 정리

 

목표 : 한 IAM 계정으로만 S3 버킷 내 이미지 Read, Write 권한 얻기 && 그 외 버킷 접근은 모두 차단

 

Next.js S3 파일 업로드 유튜브 강의들을 보면서 공부하는데 권한을 기본적으로 public access를 허용하여 교육 진행하는 것을 보았다. 다른 presigned URL(제한된 시간 안에만 해당 URL을 통해 파일 접근 가능) 유튜브 강의도 그렇고 대부분 편의상 그렇게 하는 것 같다.

 

아무래도 업로드할 파일명을 생성할 때, 적당히 긴 랜덤 문자열이라서 다른 이미지 파일에 접근하기 힘들기도하고 유튜브 교육용으로 프로젝트를 진행하면서 관련 이미지들이 그렇게 중요한 정보들이 아니기에 문제는 없어보였다.

 

그래도 S3 버킷을 공개적으로 완전 접근 허용하게되면 각 이미지 URL 주소를 복붙하여 언제 어디서든지 누구나 데이터를 가져다가 쓸 수 있다. 그런 부분을 막기 위해서 public access를 막고 제한된 계정을 통해서만 접근하도록 설정 삽질을 하였다.

 

 

S3 Bucket 생성

일단 버킷 생성할 때, 초기 설정 셋팅은 아래와 같이 하였다.

 

Object Ownership - ACLs disabled (recommended)

Object Ownership - ACLs disabled (recommended)

 

 

Block Public Access settings for this bucket - Block all public access 체크

Block Public Access settings for this bucket - Block all public access

 

나머지는 설정은 기본값

 

 

이제 계정 생성할 차례인데

계정에 권한 정책을 부여하는 방식은 두 가지 방식으로 가능했다.

 

S3 버킷 자체 Policy 설정에서 특정 유저에 Read, Write 권한 부여

또는

IAM에서 특정 계정에 권한 적용할 때, S3 사용 버켓의 Read, Write 권한 부여 

쉽게 말하면 S3 버킷에서 권한 지정하거나 IAM에서 유저에 권한 지정하면 이상없이 동작하였다.

 

계정 생성

여기서는 설명하는 부분은 계정 생성과 동시에 권한 정책까지 만들어 붙이는 방식이다.

(S3 버킷에서는 아무 정책도 적용하지 않음)

 

IAM에서 신규 계정을 생성하면 위와 같이 권한 부여 옵션이 3개가 있다.

직접 테스트해본 것은 첫 번째 것(Add user to group)과 마지막 세 번째 것(Attach policies directly)이다.

 

첫 번째 것은 정책이 부여된 그룹을 만들어서 거기에 신규 유저를 끼워넣으면 해당 유저는 관련 권한을 부여받을 수 있다. 여러 계정에 동일한 권한을 부여해줘야할 때 유용할 것으로 보인다.

세 번째 것은 계정 자체에 바로 정책을 붙이는 것이다. 권한 테스트할 때 주로 사용했었다. 아무래도 한 계정 가지고 권한 조정을 이거저거 하다보니 그렇게 된 것 같다. 이 방식으로 진행할 예정이다.

 

S3 Full Access 권한 부여

권한을 부여할 때, 기존에 AWS에서 만들어놓은 정책을 가지고 검색해서 부여할 수도 있고 내가 직접 만들 수도 있다. 오른쪽 상단에 'Create policy'를 통해 만들 수 있다. 

처음에 테스트하였을 때는 아마존에서 만들어놓은 AmazonS3FullAccess 정책을 사용했었었다. 왜냐하면 AmazonS3FullAccess 내에서도 세부권한이 겁나 많아서 괜히 처음부터 빡쎄게 좁게 권한 부여하면 원인 모를 문제가 생겼을 때, 내 어플리케이션이 문제인건지 아마존 서비스 설정이 잘못된건지 판단 불가능하기 때문이다. 다른 유튜브 강의에서도 해당 정책을 사용하면서 교육했던 것으로 기억한다.

 

 

여기서는 직접 정책을 만들어볼 것이니 Create policy 클릭.

 

정책을 만드는 방식은 두 가지가 있다. 오른쪽 상단에 보면 'Visual'과 'JSON'이 있는데 Visual 부분은 체크박스 같은 UI를 통해 권한 선택하면 되고 JSON은 JSON 형식으로 직접 작성할 수 있다.

 

Visual 탭에서 권한 선택한다면 아래와 같다.

 

Choose a service에서 S3 선택하면 아래와 같은 화면이 된다.

 

위의 Read 권한 안에 GetObject, Write 권한 안에 PutObject 권한만 있으면 단 건으로 업로드, 다운로드가 가능하다. 두 부분 체크

Read 권한 안에 GetObject 권한
Write 권한 안에 PutObject 권한

 

 

권한을 선택하면 그 아래 Resources 파트에서 권한에 영향받을 버킷과 객체(파일들)을 지정할 수 있다.

AWS 유저에 따라서 버킷을 여러 개 가지고 있을 수 있으니 버킷을 지정해줘야한다.

 

중간에 'Add ARNs'를 눌러준다.

 

 

설명은 위 그림과 같다. 만약에 버킷 이름이 bonevillain이고 그 버킷 안의 모든 객체에 대한 Read, Write이라면 아래와 같이 써주면 된다.

오른쪽 하단에 Add ARNs 버튼 눌러준다.

 

이 상태에서 잊고 있었던 오른쪽 상단의 JSON 탭을 눌러주면 JSON 형식의 자동생성된 권한 스크립트를 볼 수 있다.

 

 

대충 눈치껏 파악해보면

Sid : 정책 이름 (S3 버킷 내에서도 JSON 형식으로 기입할 수 있는데 해당 값은 필수값이 아니다)

Effect : Action에 나열된 권한을 허용할 것인가 거절할 것인가

Action : 어떤 권한이 필요한가 자네

Resource : 이러한 권한을 어느 버켓, 어느 객체에 지정할 것인가

 

오른쪽 하단의 Next 버튼을 눌러 넘어간다.

내가 만든 정책의 이름을 정해줄 시간이다. 아무거나 넣으면 된다. (예를 들어, bonevillain-policy)

오른쪽 하단의 Create policy를 눌러주면 정책은 만들어진다.

 

잊으면 안되는게 나는 IAM 계정을 생성하러 들어왔다가 권한 Policy를 만들어주었다. 망각하면 안된다.

정책 만들고나니 뭔가 허전한 느낌이 들어서 내가 뭐하다가 정책을 만들었지?라는 생각이 들었다. 

 

브라우저 상의 새 탭에서 신규 정책을 만들어줬으니 기존 탭 중에 유저 생성하다가 말았던 탭이 있을 것이다.

 

IAM 계정 생성 페이지에 다시 돌아와 내가 만든 정책 이름을 검색해주면 해당 정책이 나올 것이다.

혹시 검색했는데 안나오면 'Create policy' 버튼 바로 왼쪽에 꼬리를 물고 있는 화살표(새로고침 버튼)를 눌러주면 검색 결과가 뜰 것이다.

검색된 정책을 체크해주고 Next 클릭

 

내가 만든 정책 리뷰하는 타임인데 그냥 오른쪽 하단 'Create user' 누르면 내가 만든 정책이 반영된 계정이 생성된다.

 

성공적으로 만들어졌다고 한다.

프로젝트에서 쓰려면 접근키가 필요하다. 생성된 User name을 클릭하면 (여기서는 'bonevillain-s3-user')

 

오른쪽에 'Create access key'가 보인다. 누르면 키 만드는 절차에 착수한다.

 

 

키 만드는 옵션이 다양하게 있는데 주로 Application running outside AWS를 선택했었다.

실제로 AWS 밖에서 돌아가는 사실이니 눌러주자.

 

다른 유튜버하는 거보니 첫 번째 거 Command Line Interface로 해서 키를 만들던데 각 생성된 키 차이는 모르겠다.

 

다음 화면에 태그 값 추가하는 옵션이 있는데 바로 'Create access key' 눌러준다.

 

아름다운 키가 만들어졌다.

 

 

이것으로 가지고 .env.local 파일을 만들어 S3 파일 업로드, 다운로드 프로젝트를 수행하면 된다.

 

 

S3 버킷에서 정책 설정

위에서 실컷 얘기했던 부분은 IAM 신규 계정에 권한 정책을 부여했던 부분이다.

 

이번엔 S3 버킷에서 정책을 설정할 것이다.

 

IAM에 있는 Users 목록 중에 방금 만든 계정 이름을 클릭하여 들어가서 Permissions 탭 클릭

계정에 붙어있는 정책 삭제 (삭제할 대상 정책 체크박스 클릭 후 오른쪽 상단 Remove 버튼 클릭)

 

 

내가 만든 S3 버킷 페이지로 이동

버킷 이름을 클릭

 

Permissions 탭으로 이동

 

페이지 내려가다보면 중간에 Bucket policy 보임.

Edit 버튼을 눌러 수정.

 

 

여기서 policy를 작성할 수 있는데 이전에 JSON 형식으로 자동생성된 스크립트를 그대로 가져다 써도 된다.

 

 

방금 전에 Visual 탭에서 세부 권한을 선택했을 때, 위와 같이 나왔다.

 

참고로 S3 관한 모든 권한을 부여하고 싶으면 Action에 아래와 같이 넣어주면 된다.

"Action": "s3:*",

 

해당 부분을 복붙해서 넣으면

Principal이 빠져있다고 나온다. 찾아보니 대충 이 정책에 해당하는 당사자가 빠져있다는 내용이다. 누구한테 이 정책을 부여할 것인지 빠졌다 이말이다.

그래서 Principal 부분을 아래와 같은 형식으로 넣어준다.

(현재 버킷 정책이 Public이 아닌 상황에서 해당 버킷 정책 반영 대상이 필요하다. 마치 계정 권한 생성할 때, 타겟 버켓이 필요한 것처럼) 

{
	"Version": "2012-10-17",
	"Statement": [
		{
		    "Sid": "VisualEditor0",
			"Effect": "Allow",
			"Principal": {
				"AWS": "arn:aws:iam::계정번호:user/IAM에서 만든 계정 이름"
			},
			"Action": [
				"s3:GetObject",
				"s3:PutObject"
			],
			"Resource": [
				"arn:aws:s3:::버킷 이름/*"
			]
		}
	]
}

방금 전에 만든 유저에게 권한을 주어야하기에 해당 유저의 ARN을 복붙하여 넣어준다.

ARN을 알 수 있는 방법은 IAM 페이지 내 Users에 보면 내가 만든 계정이 보인다. 해당 계정 이름을 클릭해서 보면 상단 summary 부분에 ARN을 볼 수 있다.

 

JSON 형식의 정책에 문제가 없다면 우측 하단의 Save changes 버튼을 누르면 정책이 바로 반영된다.

그러면 IAM 유저 페이지에서 보면 권한이 아무것도 없어도 Access Key를 이용해서 S3 업로드 다운로드가 가능하다.

 

끝.

 

 

참고로

https://github.com/kimfame/next-s3

직접 만들어놓은 Next.js S3 테스트 프로젝트에서 .env.template를 통해서 .env.local 파일 만들 때

AWS_S3_ACL 값은 private로 설정하여야한다. S3 버킷 설정이 공개 접근 허용의 경우, public으로해야 동작한다.

(AWS SDK 사용할 때, 들어가는 파라미터이다.)

 

예시)

AWS_REGION=ap-northeast-2

AWS_S3_ACL=private

AWS_S3_SIGNED_URL_EXPIRE_TIME=60 <- 60초 동안만 S3 이미지 URL 확인 가능 

 

 

 

[출처]

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/command/PutObjectCommand/

https://linux.systemv.pe.kr/2021/10/aws-s3-presigned-url-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0/

https://www.youtube.com/watch?v=nGoSP3MBV2E

https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-bucket-user-policy-specifying-principal-intro.html