-
aws cloudfront를 이용해서 s3에 있는 나의 컨텐츠 보호하기(feat. signed url)Infra/AWS 2023. 8. 23. 18:26
aws에서 동영상 서비스를 구축중에 있다.
그런 와중에 영상 유출 방지를 위한 대책이 필요했다.
기본적으로 public에서 url 접근을 허용해 서비스를 개발하였고,
이제 컨텐츠 보호를 위해 인프라 내부 환경에서만 접근 가능하도록 한다.
첫 번째 방법
vpc를 기준으로 외부에서 접근 못하도록 한다.
그렇게 되면 서버에서는 접근이 되지만, 외부에서 url을 통해 접근을 못하게 된다.
우선 vpc endpoint를 생성해 s3 policy 정책을 수정 했다.
기존 정책에서 vpce를 확인하는 정책을 추가했다.
{ "Version": "2012-10-17", "Id": "Access-to-bucket-using-specific-endpoint", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "s3:ListBucketMultipartUploads", "s3:GetBucketLocation", "s3:ListBucket" ], "Resource": "arn:aws:s3:::버킷명" }, { "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "s3:PutObject", "s3:AbortMultipartUpload", "s3:DeleteObject", "s3:GetObject", "s3:ListMultipartUploadParts" ], "Resource": "arn:aws:s3:::버킷명/*" }, // 추가 { "Sid": "Access-to-specific-VPCE-only", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": ["arn:aws:s3:::버킷명", "arn:aws:s3:::버킷명/*"], "Condition": { "StringNotEquals": { "aws:sourceVpce": "VPCE아이디" } } } ] }
VPC Endpoint는 무료이며, 쉽게 만들 수 있다.
이름은 적당하게 짓고, AWS services를 클릭해주자.
services type을 gateway로 해주고 s3를 체크한다.
마지막으로 사용할 vpc를 선택해준다.
서버에 접속해서 curl로 컨텐츠를 다운로드하니 잘된다.
외부에서는 당연히 안된다.
그런데 문제는 서비스 웹페이지에서 컨텐츠 접근을 할 수 없다...
웹을 이용하는 사용자의 위치가 vpc 밖이라 그런 것 같다.
얼마전 알리바바 클라우드에서는 vpc로 제한을 둬도 웹에서 재생이 잘 됐었다.
cdn과 관련된 차이 같다.
그래서 다른 방법을 시도했다.
두번째 방법
signed url을 만들어서 접근을 제어하는 방법이다.
그러기 위해선 cloudfront 서비스를 이용해야한다.
결국 cdn 서비스를 사용하게 되었다.
CloudFront 서비스 페이지로 이동한다.
먼저 public 키를 등록해야 한다.
그럴려면 키를 생성해야한다.
$ openssl genrsa -out private_key.pem 2048 $ openssl rsa -pubout -in private_key.pem -out public_key.pem
생성이 되었다면 public_key.pem의 내용을 아래 key란에 복붙해주자.
이제 키 그룹을 생성해 앞서 만든 퍼블릭 키를 등록해주자.
이제 사전 준비는 끝났고, 본격적인 작업을 들어간다.
Dstributions 탭에 들어와서 생성 버튼을 누른다.
Origin domain을 연결할 s3로 선택해주고, 옵션은 원하는데로 설정하면 된다.
Restrict viewer access를 yes로 해서 아래 이미지와 같이 설정을 해주면,
키를 통해 접근을 제한 할 수 있다.그리고 cache policy는 추천해주는걸로 선택했다.
나머지 설정은 그대로 두고 생성 했다.
생성하고 나면 status와 last Last modified 컬럼이 deploying 상태일 것이다.
아래 이미지처럼 되길 기다리자.
마지막으로 s3 policy를 추가한다.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": [ "s3:ListBucket", "s3:GetObject" ], "Resource": [ "arn:aws:s3:::버킷명/*", ], "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::AWS어카운트아이디(숫자):distribution/디스트리뷰션아이디" } } } ] }
생성된 distribution을 클릭해서 들어가서 domain을 확인하자.
복사를 해서 접근해보자.
도메인 주소 뒤에 s3 경로를 붙이면 된다.
키가 없어서 접근을 못한다는 에러 메시지를 확인 할 수 있다.
자 이제 aws 콘솔에서의 작업은 끝났다.
그렇다면, 실제로 signd url을 통해 접근이 되는지 확인을 해야한다.
node.js로 코드 작업을 했다.
npm install @aws-sdk/cloudfront-signer yarn add @aws-sdk/cloudfront-signer pnpm install @aws-sdk/cloudfront-signer
import { getSignedUrl } from "@aws-sdk/cloudfront-signer"; // ESM const cloudfrontDistributionDomain = "https://abcdefg.cloudfront.net"; const s3ObjectKey = "private-content/private.jpeg"; const url = `${cloudfrontDistributionDomain}/${s3ObjectKey}`; const privateKey = provess.env.PRIVATE_KEY; const keyPairId = "cloudfront > public keys > id"; const dateLessThan = "2024-01-01"; // 만료 날짜 const signedUrl = getSignedUrl({ url, keyPairId, dateLessThan, privateKey, });
양식은 이렇다.
URL/Expires=값&Key-Pair-Id=값&Signature=값
접속 해보면 잘된다.
https://aws.amazon.com/blogs/developer/creating-amazon-cloudfront-signed-urls-in-node-js/
https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_cloudfront_signer.html
https://github.com/aws/aws-sdk-js-v3
'Infra > AWS' 카테고리의 다른 글