본문 바로가기
개발/NestJS

[NestJS] AWS S3 Pre-signed URL 발급

by coking 2022. 12. 18.

현재 회사에서는 프론트에서 직접 s3에 이미지를 업로드하고 업로드한 url을 서버에 보내 DB에 저장하는 형식으로 진행되고 있었다. 근데 확인해보니 프론트에서 s3에 직접 업로드하는 과정에서 aws key값이 브라우저에 그대로 노출되고 있었고 이로 인해 해킹까지 이어질 수 있는 위험한 상황이었다.  그리하여 방법을 찾다가 Pre-signed URL을 알게 되었고 NestJS 서버에서 발급받는 방법을 정리하려고 한다. 

 

Pre-signed URL이란 무엇인가?

직역하자면 미리 서명된 URL이다. 쉽게 설명하자면 인증된 사용자가 s3에 접근해 인증된 url을 발급받고 이 url을 통해 객체에 접근해서 읽거나 수정하는 작업이 가능해지는 것이다.  주의할 점은 Pre-signed URL은 url을 아는 모두에게 Amazon S3 버킷에 대한 액세스 권한을 부여하므로 사용에 주의해야 한다.

 

Pre-signed URL을 프론트에서 사용할 시 프론트에서 직접 aws에 인증받을 일이 없어지므로 key값이 노출될 위험이 사라진다. 또한 파일이 직접 서버를 거치지 않기 때문에 파일 용량으로 인해서 서버 부하가 생기는 일도 방지된다.

사용법

여기서는 사용자가 IAM 계정 key발급과 또 그 key에 s3 접근 권한이 있다는 가정에 진행된다.

 

현재 내가 알아본 바로는 url을 발급받는 방법은 두 가지가 있다. 한 가지는 서버에서 바로 s3에서 url형식을 받아 그 url로 업로드하는 방식과 s3에서 url과 field형식을 받아서 합쳐서 url로 만든 다음에 업로드하는 방식, 나는 바로 url을 발급받는 방식을 사용하였다.  

 

일단 이 글에 오신 분들은 코드가 제일 궁금할 것이니 내가 사용한 코드 먼저 보여 공개하겠다.

$ npm install aws-sdk
import AWS from "aws-sdk";

async createPresignedUrl({ filePath }: CreateAwsDto) {
    const s3 = new AWS.S3({
        accessKeyId: process.env.AWS_S3_ACCESS_KEY_ID, // 사용할 aws iam 계정의 access key
        secretAccessKey: process.env.AWS_S3_SECRET_KEY, // 사용할 aws iam 계정의 secret key
        region: process.env.AWS_S3_REGION // s3 bucket이 사용하고 있는 region
    });
    
    interface IparmsType {
		[key: string]: string | number;
	}

    const params: IparmsType = {
        Bucket: process.env.AWS_S3_BUCKET, // 사용할 s3 butket 이름
        Key: filePath, // 여기서 결정한 key가 s3 bucket의 경로가 된다. 
        Expires: 3600 // 3600초를 뜻하며 사용에 맞게 변경해서 사용해야 한다.  
        // ACL: 'public-read', 이렇게 권한 지정도 가능, 지정하지 않을 시 defalut private
    };

    return s3.getSignedUrlPromise("putObject", params);
}

이렇게 return 한 url에는 모든 정보가 담겨있기에 프론트에서 바로 사용해주면 된다.

 

ACL 권한 관련된 aws 공식문서

https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/acl-overview.html#CannedACL

 

ACL(액세스 제어 목록) 개요 - Amazon Simple Storage Service

전체 사용자 그룹(All Users group) WRITE, WRITE_ACP 또는 FULL_CONTROL 권한을 부여하지 않는 것이 좋습니다. 예를 들어, WRITE 권한은 비소유자가 기존 객체를 덮어쓰거나 삭제하도록 허용하지 않지만, 여전

docs.aws.amazon.com

 

이렇게 이제 발급받은 url을 사용할 때 만날 수 있는 에러는 바로 403 Forbiddend 에러이며 The AWS Access Key Id you provided does not exist in our records.이라는 에러 메시지를 받을 것이다. 이때 확인할 것은 딱 두 가지인데 첫 번째로 aws key값을 코드상에 넣을 때 띄어쓰기나 특수문자, 콤마 같은 게 들어가서 형식이 바뀌었는지 보는 것 두 번째로 여기서 사용하는 key IAM 계정에 s3 접근 권한이 있는지 이 두 가지를 해결하면 잘 해결될 것이다. 

 

 

 

내가 사용하지 않은 다른 Pre-signed URL을 발급받는 방법

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_s3_presigned_post.html#createpresignedpost

 

@aws-sdk/s3-presigned-post | AWS SDK for JavaScript v3

 

docs.aws.amazon.com

 

Pre-signed URL 관련 공식문서 

https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html

 

미리 서명된 URL을 사용하여 객체 공유 - Amazon Simple Storage Service

미리 서명된 URL을 사용하여 객체 공유 기본적으로 모든 S3 객체는 비공개입니다. 객체 소유자만 액세스할 수 있습니다. 그러나 객체 소유자는 필요할 경우 자신의 보안 자격 증명을 사용하여 일

docs.aws.amazon.com

 

댓글