728x90
반응형
등록되고 인증된 사용자만 S3 버킷에 파일을 직접 업로드하는 방법을 구현해 보겠습니다.
(본 실습에서는 2번과 3번의 JWT 토큰 전달 및 검증은 포함하지 않습니다.)
#1 S3 버킷에 파일을 업로드 권한을 가진 사용자를 생성
upload-s3 사용자를 추가합니다.
upload-s3 사용자에게 버킷 조회 권한과 객체 생성 권한을 부여합니다.
액세스 키와 비밀 액세스 키를 보관합니다.
#2 정책을 생성하는 람다 함수를 생성합니다.
작업 디렉터리를 생성합니다.
모듈을 설치합니다.
package.json에 람다 함수 생성 스크립트 추가
C:\serverless\get-upload-policy\index.js 람다 함수 작성
'use strict';
var async = require('async');
var crypto = require("crypto-js");
const C_ACL = 'private';
const C_NOW = new Date().toISOString();
const C_DATE_STAMP = C_NOW.slice(0,10).replace(/-/g,'');
const C_REGION_NAME = 'us-east-1';
const C_SERVICE_NAME = 's3';
const C_X_AMZ_DATE = C_NOW.replace(/[-:\.]/g,'');
const C_X_AMZ_ALGORITHM = 'AWS4-HMAC-SHA256';
const C_X_AMZ_CREDENTIAL = `${process.env.ACCESS_KEY}/${C_DATE_STAMP}/${C_REGION_NAME}/${C_SERVICE_NAME}/aws4_request`;
// 오류 메시지를 반환
function createErrorResponse(errCode, errMessage) {
var response = {
'statusCode': errCode,
'headers': { 'Access-Control-Allow-Origin': '*' },
'body': JSON.stringify({ 'error': errMessage })
};
return response;
}
// 성공
function createSuccessResponse(message) {
var response = {
'statusCode': 200,
'headers': { 'Access-Control-Allow-Origin': '*' },
'body': JSON.stringify(message)
};
return response;
}
// expiration(정책 유효 기간)을 계산해서 반환
function generateExpirationDate() {
var currentDate = new Date();
currentDate = currentDate.setDate(currentDate.getDate() + 1);
return new Date(currentDate).toISOString();
}
// 보안정책을 생성
// https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
function generatePolicyDocument(filename, next) {
var expiration = generateExpirationDate();
var dir = Math.floor(Math.random()*10**16).toString(16);
var key = dir + '/' + filename;
var policy = {
'expiration': expiration,
'conditions': [
{ acl: `${C_ACL}` },
{ bucket: process.env.UPLOAD_BUCKET },
[ 'starts-with', '$key', `${dir}/` ],
{ 'x-amz-algorithm': `${C_X_AMZ_ALGORITHM}`},
{ 'x-amz-credential': `${C_X_AMZ_CREDENTIAL}` },
{ 'x-amz-date': `${C_X_AMZ_DATE}` }
]
};
next(null, key, policy);
}
// 보안정책을 BASE64로 인코딩해서 반환
function encode(key, policy, next) {
var json = JSON.stringify(policy).replace('\n', '');
var encodedPolicy = new Buffer(json).toString('base64');
next(null, key, encodedPolicy);
}
// 서명 키(signing key) 생성
// https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html
function getSigningKey() {
var dateKey = crypto.HmacSHA256(C_DATE_STAMP, "AWS4" + process.env.SECRET_ACCESS_KEY);
var dateRegionKey = crypto.HmacSHA256(C_REGION_NAME, dateKey);
var dateRegionServiceKey = crypto.HmacSHA256(C_SERVICE_NAME, dateRegionKey);
var signingKey = crypto.HmacSHA256("aws4_request", dateRegionServiceKey);
return signingKey;
}
// 서명 생성
// https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
// https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
function sign(key, encodedPolicy, next) {
var signingKey = getSigningKey();
var signature = crypto.HmacSHA256(encodedPolicy, signingKey);
next(null, key, encodedPolicy, signature);
}
exports.handler = function(event, context, callback) {
// 파라미터로 전달된 파일명을 추출
var filename = null;
if (event.queryStringParameters && event.queryStringParameters.filename) {
filename = decodeURIComponent(event.queryStringParameters.filename);
} else {
callback(null, createErrorResponse(500, '파일명이 누락되었습니다.'));
return;
}
// 보안정책 생성 -> BASE64 인코딩 -> 서명 생성 => 키(임의폴더/파일명), BASE64로 인코딩된 보안정책, 서명값을 반환
async.waterfall([ async.apply(generatePolicyDocument, filename), encode, sign ], function (err, key, encoded_policy, signature) {
if (err) {
callback(null, createErrorResponse(500, err));
} else {
// POST 요청에서 사용할 값을 JSON 형식으로 반환
var result = {
upload_url: process.env.UPLOAD_URI,
encoded_policy: encoded_policy,
key: key,
acl: `${C_ACL}`,
x_amz_algorithm: `${C_X_AMZ_ALGORITHM}`,
x_amz_credential: `${C_X_AMZ_CREDENTIAL}`,
x_amz_date: `${C_X_AMZ_DATE}`,
x_amz_signature: `${signature}`
};
callback(null, createSuccessResponse(result));
}
});
}
람다 함수 생성 및 배포
람다 함수 환경 변수 설정
람다 함수 테스트
728x90
반응형
'클라우드' 카테고리의 다른 글
Serverless Framework #3 실행 환경 제한 설정 (0) | 2020.11.07 |
---|---|
Serverless Framework #2 (0) | 2020.11.06 |
Serverless Framework #1 (0) | 2020.11.06 |
POST 방식으로 S3 버킷에 파일 업로드 #2 (0) | 2020.11.04 |
GCP OAuth 클라이언트 생성 (0) | 2020.05.20 |
댓글