[CloudFront] One-time URL

홍준·2021년 12월 6일
2
post-thumbnail

서론

저번 시간에 작업했던 내용은 S3에 파일을 업로드하는 경우 Presigned URL을 생성하여, 업로드를 할 수 있도록 작업해 보았다.
이번 작업은 CloudFront Signed URL을 생성하여 사용자에게 One-time URL 제공하는 방법을 작업해 보려고 한다.


Signed-URL 아키텍처

💡 Signed URL이란?

CloudFront로 배포되는 파일의 사용을 제한하는 기능이다.
즉, 특정 날짜가 지나면 파일을 받지 못하게 하거나, 특정 날짜가 지나야만 받게 하거나, 특정 IP만 파일을 볼 수 있게 하는 등의 용도로 사용한다.


Signed-URL 요청을 위한 키 생성하기

Signed URL을 생성하려면 서명자가 필요하다. 서명자는 CloudFront에서 생성한 신뢰할 수 있는 키 그룹이거나, CloudFront 키 페어가 포함된 AWS 계정이다. 이번 작업에선 신뢰할 수 있는 키 그룹을 생성하여 작업해 보려고 한다.

1. 키 페어 생성하기

터미널에서 아래 두가지 명령어를 실행한다.


1.  openssl genrsa -out private_key.pem 2048
2.  openssl rsa -pubout -in private_key.pem -out public_key.pem

첫 번째는 open SSL을 통해 RSA private key를 생성하는 명령어이고, 두 번째는 private key에서 public key를 추출하는 명령어이다.

실행이 완료되면 아래와 같이 private_key.pem / public_key.pem 두 파일이 생성된 것을 확인이 가능하다.

2. 키 그룹 생성하기

위에서 만든 키페어를 이용하여 Public keys / Key Group 을 생성을 해야한다.
먼저 Public keys 생성은 아래의 단계를 통해 생성이 가능하다.

1. AWS Management Console을 통해 [CloudFront]로 접속한다.
2. 좌측 탭에서 Public keys 탭에 접속한다.
3. [Add public key] 버튼을 클릭한다.
4. Key name으로는 signed-public 를 입력하고 Key value에는 방금 생성한 public key를 복사해 넣는다.  

다음으로 Key Group 생성해보자

1. 좌측 탭에서 Key Group 버튼을 클릭한다.
2. Key group name으로 signed-key-group을 입력하고 Public keys 항목에서는 
  방금 생성한 signed-public을 선택하고 Add를 클릭한다. Create Key group 버튼을 클릭해 key group을 생성한다.

3. 키 그룹 적용하기

등록된 CloudFront 혹은 CloudFront 생성시 Restrict Viewer Access 를 yes로 바꾼후
Trusted Key Groups을 선택 후 방금 생성한 Group을 Add 한다.

4. CloudFront 호출하기

키 그룹을 적용한 CloudFront 도메인을 호출하면 아래와 같이 접속하면 Missing Key 에러가 리턴됨을 확인할 수 있다.


Signed-URL 생성 및 테스트 해보자

앞서 만들어 둔 private key를 가지고 Signed-URL을 생성하고 정상적인 도메인으로 호출 될 수 있는지 테스트를 해보자.

Lambda를 이용하여 Signed-URL 생성하기

const AWS = require('aws-sdk');
const keyPairId = process.env.PUBLIC_KEY_ID

const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA1A8uG0pHonQIXIraKaL6303tMf5CNVnQqn18USD/OAI9P5l5
35Vxtbs1ZUOFILxXXEilFENndRksEIfahzvGGv74KWlWedkPy/bu49vpz081tv66
LYvBQ4t4znzcPJsgyqTi4wbyNU1TwuQHdRy7yiTzTryX7bJkaegTlon47vOKfcLp
UVK+or8troHflnqgd2so9mnWtSnzshJkhl4EgYcv8GVDPdx5OImLFzvNh2YYdkdO
YEtwVvF9L2YGtfstY+DT/gip38NpEr8K3AAD/L1HcajwOHWpGqaq+HDR+3zstwrW
KSZizBmTXv/OTGm0aXIdlGv2TTjIPADBAjc5tQIDAQABAoIBAQDSsZ5y2POhsj3Y
jNFECz3NfuSMBn8L+Qf9TR6mkO1jXb4zIa9YeWh4UuAzk8mDA/6cn0T9hBcX3oHM
jt6N/NLRYcF5i8Ky3/r1AYzLcmW1Z5MMFb0voarNDJdkOeSshskm7nrLbMxcL09o
1R2fu4PNzba85V7ieZuRKlfD+6QM7LgElZyBhB9p5cmIazpY8yGKpJ4S2hPu507S
Aurw6wtHCrtweymzrmNAsVhSgzK+IWlCn3W/Ms9mYs1qzaLUYjUdoRmLFP1FtIE9
QLLC/JASVy3MuycMQ/HRF95J5jVgMTZVf9Wfro7qGcTuPR+deEO1ZUrGSfvqxFjK
3b0mY7SBAoGBAOwMjOZeCndqJziZjhExWYcb4Hl0ehG/9SFdQKlX06wpcYUzOXsx
v3SYqZC2qIPF8XxNhdqB45RFb59FHSJjkqSb7/zELiwD2wwh4d+sDXBJGtc3A43J
AdZ/VZE1x67BwS5L3YcKaE8C8N3pzpGrbxMjXDeaNb+0nUV0a4mfi3BVAoGBAOX7
juYJm1ztROIIa29cqrQpWPsMstDu6z2Z6Jzb1lok9ZR9XkDd9geSpJ6/Bxjz3lyu
VGYoMqf5pGrulelZqGtXsQcca44Q3a1sdn5R+jc0nk5K7TTE72jEOK85sWSGuMP+
oqPzvCsMwjHWu5dNgHgy4E6szynsA2kWHdYLdoPhAoGBAK76OrRF/9I3cW2GfoaG
I4yBAKxnyFlCB289FkKx5SoY6prHtxN4dCj1RbUNget0nyb6vH+Wi2IM+sqAzDEC
yOCW65Zewq9ECGt87lgEzU1wE6J3mH3RBDjB2Wc0C5qi7BXqjQOelmYDkxOdTtAy
2brBGonpGXDLbU3gGBtDlnSlAoGAHHTE2KfFpnjhNgqOqIfRw1r+XInUsk9togCi
LI5y9lJuZIIioGoWYBd/8Ph3+1lpYRRc8wr0QZ58/pIo0Ge8lBOUnumgUUK6+xNZ
kgW4rQ4ArHVO5mGbsd3dmajMz0BwKigenaSx2q3IdXw5V95KEBVTdciiFXDTdzQ6
WtquPmECgYB3Si+Tfrm9BtYqu50YXHwxjmWXqX2mjtegiEFcig/79eX0J9IVPR6v
med0DnYT8EdioPZUTqVYPDyam+6gLJhe3SgzdIvjvF7H9HEK+A9RdqHLL+ZnhkT2
sgR0SIXNfox9Aj2y2CrAH1QGgje4gdqKb7Lt+v/p/P3hMjZRO+5SXw==
-----END RSA PRIVATE KEY-----`;

const signer = new AWS.CloudFront.Signer(keyPairId, privateKey);


exports.handler = async (event) => {
  
    const expTime = 60 * 60 * 1000;    
    const signedUrl = signer.getSignedUrl({
            url: 'https://d97tkfsglhe4u.cloudfront.net/URL.jpg',
            expires: Math.floor((Date.now() + expTime) / 1000)
        });
    
    console.log("signedUrl : " + signedUrl);
        
};

💡 예제를 위하여 키 노출하였지만, 🔑 노출은 절대 금지 🙅
실습 후 키 삭제 완료

Signed-URL 호출하기

Lambda를 실행 후 CloudWatch를 통해 Signed-URL를 확인한다.

CloudWatch 통해 확인된 Signed-URL를 브라우저에서 호출해보자.

확인 완료 🙌

정리

이번 작업을 통해 CloudFront로 배포되는 파일의 사용을 제한하는 기능 확인해보았다.
Signed-URL 활용한다면 컨텐츠를 특정 유저에게만 공유하거나 정해진 시간 동안만 공유하기 등 Private 하게 사용할 수 있는 좋은 기능이 될 것 같다.😊

profile
어제의 나를 이기자 🔥

0개의 댓글