https://preparingfor.tistory.com/7
저번 글에 이어서 서버를 거쳐 이미지를 aws s3에 저장하는 방식이 아닌
presigned-url을 통해 프론트에서 직접 s3 업로드 하는 방식을 알아보겠습니다.
Presigned-URL
Presigned-url은 AWS의 S3(Simple Storage Serivce)가 지원하는 기능 중에 하나인데요
지정한 기간 동한 url을 가진 사람이 특별한 AWS 인증 없이도 해당 객체에 엑세스할 수 있게 해주는 기능입니다.
Presigned-url은 다음과 같은 특징을 가진다고 할 수 있습니다.
보안
특정 객체에 대한 임시 액세스를 제공하기 때문에 S3 버킷 전체에 대한 엑세스 권한을 제공하지 않고도 필요한 객체를 안전하게 공유할 수 있습니다.
반면에, URL이 의도치 않게 유출되는 경우 민감한 데이터가 노출되거나 이상한 파일이 업로드될 수 있습니다.
유연성
액세스 기간, HTTP 메소드 (GET, PUT 등)을 포함시켜 필요한 시간, 방법에 따라 맞춤형 URL을 생성할 수 있습니다.
간편함
사용자가 AWS 인증 정보를 가지고 있지 않아도 URL을 통해 객체에 액세스할 수 있으므로, 외부 사용자와의 객체 공유가 편리합니다.
요청, 응답 흐름도
- 클라이언트가 백서버에 이미지를 업로드할 URL을 요청합니다.
- 백서버가 aws s3에게 presigned url 발급을 요청합니다.
- s3는 백에게 presigned url을 발급합니다.
- 백서버는 발급받은 url을 클라이언트한테 전달합니다.
- 클라이언트는 해당 url을 통해 파일(이미지)를 s3에 직접 업로드합니다.
- 파일 업로드가 끝나면 클라이언트는 백서버에게 업로드 완료 요청을 보냅니다.
- 백서버는 완료 요청을 받으면 image 파일이름을 DB에 저장합니다
이제 구조도 알았으니 실제 프로젝트를 구현을 위한 aws s3 설정을 해봅시다.
AWS S3 설정
1. 버킷 이름 설정
버킷 이름은 원하는 걸로 형식에 맞춰 아무렇게나 설정하면 됩니다.
2. 객체 소유권 설정과 퍼블릭 엑세스 차단 설정
이 단계가 제대로 알지 못하고 설정하면 나중에 꽤나 애먹으실 수 있는 구간인데요
실제로 s3 persigend url을 구글링하면 잘 알지 못하고 작성한 글이 많아 무작정 따라하면 403과 400 에러에 며칠을 쓰실수도 있습니다.. 항상 공식 문서를 읽읍시다..!
저도 삽질하고 싶지 않았습니다,,
해당 단계를 액세스 정책 옵션을 설정하는 구간입니다.
액세스 정책 옵션에는 크게 3가지가 있습니다.
- ACL (리소스 기반 정책)
- 버킷 정책 (리소스 기반 정책)
- IAM을 통한 사용자 기반 정책
버킷을 생성할 때 할 수 있는 것은 1번과 2번에 대한 엑세스 차단 설정입니다.
ACL부터 알아보죠
1. ACL (Access Control List)
공식 문서를 들어가면 시작부터 최신 사용 사례 대부분에서는 ACL을 사용할 필요가 없으며 각 개체에 대한 엑세스를 개별적으로 제어해야하는 특수한 상황을 제외하고는 ACL 사용하지 말라고 합니다.
(그럼 바로 비활성화를..)
하기 전에 ACL이 무엇이고 왜 웬만하면 사용하지 말라는지 한번 봐봅시다.
ACL은 console 창에서 보면 위와 같이 생겼고 버킷 혹은 버킷 내 객체 별로 3개의 피부여자(grantee)의 엑세스 권한을 설정할 수 있습니다.
리소스에 대한 요청을 제출하면 Aws S3는 해당 ACL을 확인하여 해당 요청이 필요한 엑세스 권한이 있는지 확인하죠.
즉, ACL을 어떻게 설정하느냐에 따라서 해당 리소스 하나에 대한 접근 권한을 바꿀 수 있다는 것 입니다.
위 사진의 설정은
객체 소유자인 제 aws 계정은 해당 리소스에 접근해서 데이터를 읽을 수 있고 ACL을 수정 및 읽기가 가능하지만
퍼블릭 엑세스 즉, 객체 url를 통한 일반 유저 같은 임의의 사용자는 접근할 수 없습니다.
프론트엔드에서 객체 url을 통해 들어가 해당 사진을 보려면 Public Access를 허용하거나 presigned url로 제한시간을 걸어두고 확인할 수 있는데요
ACL을 이용하면 해당 이미지 리소스를 GET 혹은 PUT 할 때 Public Access를 읽기 가능 상태로 바꿀 수 있습니다.
객체 소유권 설정에서 ACL 활성화됨을 선택하시면 ACL을 사용하실 수 있습니다.
하지만 실제 프로젝트를 할 때는 건드리지 않는 것을 권장합니다.
다른 요청에 의해서 버킷 내 객체에 대한 권한이 나도 모르게 수정되는 것보다 모든 권한을 중앙집권적으로 관리하는 것이 좋아보입니다.
버킷 설정 중 위 2가지가 ACL에 관한 설정인데요.
첫번째 설정을 하면 이제부터 새롭게 들어오는 ACL 정책은 아래처럼 모두 403 에러가 뜹니다.
두번째 설정을 하면 기존에 있는 ACL 설정들도 사용하지 않게됩니다.
ㅁㄴㅇㄹ.png의 ACL을 통해 퍼블릭 엑세스를 읽기로 변경해주었는데요
두번째 설정을 해놓으면 기존의 있는 ACL 설정이 아래와 같이 막히는 것을 볼 수 있습니다.
마지막으로 위 2개 설정 켜고있든 끄고 있든 상관없이
ACL을 비활성화 해둔다면 ACL을 원격으로든 console로든 수정할 수 없으며
ACL 설정을 추가로 하는 요청들은 모두 아래와 같이 400 에러가 뜨게 됩니다.
2. Bucket Policy (버킷 정책)
버킷 정책은 bucket과 bucket 안 하위 모든 객체에 대한 엑세스 권한 설정을 한번에 그리고 허용할 메서드를 자세하게 설정 할 수 있습니다.
ACL와 같이 bucket 자체 혹은 bucket내 객체 별로 대한 엑세스 권한 설정을 할 수 있는 것과는 차이가 있습니다.
(참고로 ACL은 Bucket Policy처럼 메서드 별로 자세하게 권한 설정을 할 수 없습니다.)
자세한 내용은 document를 참고해주세요
https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html
버킷 정책은 아래와 같이 JSON으로 설정할 수 있는데요
보통 Presigned Url을 검새하면 해당 bucket policy가 나오지만 사실 모든 퍼블릭 엑세스를 차단할 것이라면 해당 버킷 설정은 의미가 없습니다.
실제로 IAM을 생성하여 S3를 관리하는 계정을 따로 만들 것이기 때문에 ACL과 Bucket Policy 같은 리소스 기반 정책은 필요 없다고 할 수 있죠
그래도 간단하게 설명하자면
Principal : 누구에게
Action : 어떤 행동을
Resource : 어떤 리소스 자원에
Effect : allow 할 것인지 deny 할것인지
입니다.
해당 내용은 "모두에게(public하게) s3 버킷과 하위 모든 객체에 Put과 Get을 허용하겠습니다." 라는 내용입니다.
다시 bucket policy와 관련된 퍼블릭 엑세스 설정을 봅시다.
4개 중 아래 2개가 bucket policy와 관련된 내용인데요
첫번째를 하면 기존에 설정된 버킷 설정은 유효하나 이제 새로 들어오는건 안된다는 말입니다.
두번째를 하면 기존 설정까지 무시하고 public access를 막겠다는 것 입니다.
실제로 4번째 설정을 하면 위 사진처럼 기존 bucket policy의 public access가 무시됩니다.
(Principal은 *로 열어두지말고 이후 나오는 IAM 설정을 하고 다시 bucket policy를 설정합시다)
설정으로 돌아와서...
저는 IAM을 통한 사용자 기반 정책으로 해당 bucket을 관리할 것이기 때문에
위 사진 처럼 ACL을 비활성화 하고 모든 퍼블릭 엑세스를 차단하였습니다.
나머지는 위와 같이 기본으로 해두고 설정을 마무리 하시면 bucket 설정은 마무리입니다..!
CORS 설정
만약 react와 같은 프론트엔드나 백에서 테스트를 하신다면 CORS 에러가 뜨는데요
위와 같이 설정해서 모든 Origins에서 GET과 PUT을 할 수 있게 열어주면 해결됩니다.
IAM (Identity and Access Management) 생성
이제 S3 버킷에 접근을 해서 리소스를 PUT GET DELETE 할 수 있는 계정을 만들 것 인데요
IAM은 해당 계정의 권한을 필요한 만큼만 제한하여 AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 서비스입니다.
IAM을 설정하는 이유는 root 계정은 너무 많은 권한을 가지고 있어서 유출이 되었을 때
EC2를 생성해서 코인을 채굴한다던지 ㅋㅋ.. 정신 건강에 좋지 않은 짓을 많이 할 수 있습니다.
실제로 저는 100만원 가량 털린 경험이 있는데요..
그 이후부터는 꼭 새로운 기술을 쓰면 공식 document을 잘 읽어보고 보안을 최우선으로 공부하는 습관이 생겼습니다..
document를 보면 ec2에 배포하였을 IAM에서 사용자가 아닌 역할을 생성하면
access key와 secret key를 서버에 저장하지 않아도 임시 자격 증명을 통해 S3에 접근할 수 있다고 나오는데요.
저는 따로 돌아다니는 컴퓨터에 linux를 깔아 서버 컴퓨터로 사용하기 때문에.. IAM 사용자를 통해 S3와 연결해보겠습니다.
설정
사용자 이름은 아무거나 설정하고
저는 aws console 로그인은 필요 없기 때문에 체크하지 않고 넘어가겠습니다.
이제 IAM에 권한을 설정해야하는데요
저는 Put, Get, Delete만 설정할 것이기 때문에 직접 정책을 만들도록 하겠습니다.
정책 생성을 누르시면 해당 화면이 나오는데 제 s3에 PUT, GET, Delete만 허용하도록 하겠습니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::fullaccel-s3/*"
}
]
}
그 다음 이름과 설명을 달고 정책을 생성해주시면 됩니다.
그럼 위와 같이 제가 만든 "s3_get_put_delete_only"라는 정책이 검색이 되고 check하시고 넘어가면 되겠습니다.
그런 다음 생성을 누르면 완료입니다.
그리고 'IAM > 사용자 > 방금 만든 사용자 > 보안 자격 증명' 에 가시면
액세스 키를 생성할 수 있는데 한번 생성하면 secret key는 다시 볼 수 없으니 csv를 다운받거나 기록해두길 바랍니다.
마지막으로 bucket 권한 설정으로 돌아와서
버킷 권한을 방금 생성한 IAM 유저만 Put, Get, Delete 할 수 있게 설정해주면 됩니다.
이제 S3 버킷 설정 끝!!
'spring' 카테고리의 다른 글
[스프링] service 인터페이스 도입과 접근제한자 (1) | 2024.09.20 |
---|---|
[spring security] 왜 500번 에러도 401(Unauthorized)에러가 될까? (0) | 2024.04.07 |
이미지 저장/조회 서버 만들기(2) - 이미지 파일 어떻게 받아오지? (0) | 2024.02.12 |
이미지 저장/조회 서버 만들기(1) - 저장 어디에..? (0) | 2024.02.11 |
SpringBoot + JPA + postgreSQL 프로젝트를 docker를 이용해 fly.io로 배포해보자 - 1부 (0) | 2023.01.20 |