Serverless Framework
serverless.yml
파일의 중요 설정값을 감춰보자!
지난 9월에 참여한 Planet Hackathon 에서 Serverless Framework를 활용하여 백엔드 API를 만들었었습니다!
해커톤 종료 후 코드 공개를 위해 공개된 레파지토리에 코드를 올렸어야 했는데,
이 때 민감 정보(그냥 내가 감추고 싶은 값)를 어떻게 감출 수 있을까 찾아보다 적용한 방법을 공유합니다.
참고 링크
Serverless Framework에서 serverless.yml
파일의 변수의 값으로 설정할 수 있는 방법들은 꽤 많습니다
목록 중에서 다양한 환경에 따라 동적으로 값을 설정할 수 있는건
자바스크립트 파일 읽어오기(Properties from Javascript files
) 기능일 것 같습니다
이 기능을 이용한 실제 적용 방법을 설명하겠습니다.
(물론 serverless.yml
파일 내에서 custom을 이용하여 분기처리도 가능합니다!)
- 데이터베이스 연결 정보 환경변수로 설정함
- 데이터베이스 연결 정보를 `serverless.yml` 에서 노출하지 않음
- stage에 따라 데이터베이스 연결 정보를 다르게 제공함
$ mkdir slsTest && cd slsTest
$ yarn init -y && yarn add -D serverless
$ yarn sls create --template aws-nodejs-ecma-script -n slsTest -p tmp
$ mv ./tmp/* .
$ rm -rf ./tmp
$ yarn # 프로젝트 생성되고 추가적인 패키지 설치를 위함
$ mkdir src && mv first.js second.js ./src # src 하위로 소스 코드 이동
$ mkdir config && touch ./config/config.js
service:
name: slsTest
# Add the serverless-webpack plugin
plugins:
- serverless-webpack
custom:
STAGE: ${self:provider.stage} # 현재 스테이지 별로 데이터베이스 접속 정보를 달리하기 위함
DB_CONFIG: ${file(./config/config.js):DB_CONFIG} # config.js 에서 가져올 데이터 베이스 접속정보
provider:
name: aws
runtime: nodejs8.10 # 현재 AWS Lambda node.js 런타임 v8.10 까지 지원, 기본값은 6.10
stage: ${opt:stage, 'dev'} # -s 옵션을 받으면 사용하고, 그렇지 않으면 기본 dev 스테이지 사용
region: ap-northeast-2
environment:
STAGE: ${self:provider.stage}
# custom 항목 중 DB_CONFIG를 읽어서 스테이지 별로 해당하는 값을 불러옴
DB_HOST: ${self:custom.DB_CONFIG.${self:custom.STAGE}.DB_HOST}
DB_USER: ${self:custom.DB_CONFIG.${self:custom.STAGE}.DB_USER}
DB_PASSWORD: ${self:custom.DB_CONFIG.${self:custom.STAGE}.DB_PASSWORD}
functions:
first:
handler: src/first.hello # 디렉토리 내의 파일을 실행시킬때의 경로 설정
second:
handler: src/second.hello
events:
- http:
method: get
path: second
/config/config.js
파일을 생성하고, 아래와 같이 작성합니다module.exports.DATABASE_CONFIG = (serverless) => ({
dev: {
DB_HOST: 'localhost',
DB_USER: 'scott',
DB_PASSWORD: 'tiger'
},
prod: {
DB_HOST: 'fake.database.com',
DB_USER: 'scott2',
DB_PASSWORD: 'tiger2'
}
});
1. commonJS 형태로 작성합니다
2. 반드시 함수로 작성되어야 합니다!
3. 암시적으로 serverless 인자를 받을 수 있습니다 (serverless API 기능을 사용할 수 있습니다)
- `node_modules/serverless/lib/Serverless.js` 코드를 참고하세요
- `serverless.cli.consoleLog()` 와 같은 명령어가 사용 가능 합니다.
src/first.js
파일을 조금 수정합니다// eslint-disable-next-line import/prefer-default-export
export const hello = (event, context, callback) => {
// 환경 변수에서 데이터 베이스 접속 정보를 가져옴
const {DB_HOST, DB_USER, DB_PASSWORD} = process.env;
const p = new Promise((resolve) => {
resolve('success');
});
p
.then(() => callback(null, {DB_HOST, DB_USER, DB_PASSWORD})) // 출력
.catch(e => callback(e));
};
config.js
파일이 공유되지 않도록.gitignore
에 추가합니다
config.js
파일의 존재와 어떤 항목을 사용하는지 알 수 있도록 config.sample.js
파일을 작성합니다// 이 파일은 샘플입니다. 파일을 config.js 로 변경 후 사용해 주세요
// 필요한 항목을 기입해야 정상적으로 실행됩니다
module.exports.DB_CONFIG = (serverless) => ({
dev: {
DB_HOST: '<Please fill in this information>',
DB_USER: '<Please fill in this information>',
DB_PASSWORD: '<Please fill in this information>'
},
prod: {
DB_HOST: '<Please fill in this information>',
DB_USER: '<Please fill in this information>',
DB_PASSWORD: '<Please fill in this information>'
}
});
설정 끗!
Promise.resolve
값을 반환하면 가능합니다config.sample.js
파일은 공유되지만, 유심히 읽지 않을 수 있기 때문에 ㅠㅠ.env
파일로 관리하더라도 마찬가지일듯 싶습니다! 👻환경 변수를 자바스크립트 코드로 작성해 동적으로 관리할 수 있다는 건 장점이라고 생각합니다!
(dotenv를 추가로 설치 하지 않아도 되고)
어찌되었건 serverless.yml
파일은 무심코 공개 레파지토리에 올릴 경우, 중요한 정보가 많이 노출될 수 있으므로 이러한 방법이 아니더라도, 중요한 정보는 잘 숨겨서 관리하도록 해야겠습니다!
내용 중 잘못된 부분은 언제든 지적해주세요!
읽어주셔서 감사합니당 😀
저도 .json 에 관리를 했었는데
CircleCI 에서 환경변수를 사용해야 됐어서..
${env:SECRET_KEY} 이런식으로 사용하고
만약에 로컬에서 배포 할 수 밖에 없는 상황엔
https://github.com/velopert/velog/blob/master/velog-backend/scripts/loadenv
이런 스크립트를 사용해서 .env.production 파일에 있는 변수들을 불러오게했어요.
https://www.npmjs.com/package/serverless-dotenv-plugin
이런 솔루션도 있네요..!
아.. 그리고 벨로그 댓글에 링크 있으면 a 태그로 변환 시켜야겠네요 ㅋㅋ
좋은 정보 감사합니다!