Bitbucket Pipelines로 Google App Engine에 자동 배포 시 안전하게 환경변수 추가하기
Published in
8 min readOct 20, 2020
Bitbucket Pipelines로 Google App Engine에 자동 배포 시 안전하게 환경변수를 추가하는 방법을 소개합니다.
개발/배포 환경
- 서버 : Google App Engine
- runtime : custom
- env: flex - 소스 관리 : Bitbucket
- CI/CD 툴 : Bitbucket Pipelines
문제점
- 일반적으로 Google App Engine 설정 파일 (
app.yaml
)에 환경 변수를 추가하는 방법은env_varibles
항목에key:value
형태로 평문 그대로 저장하는 방식입니다. app.yaml
파일에 API Key, Auth Token 등의 노출되면 안되는 정보들이 그대로 노출됩니다.app.yaml
파일에 직접 저장하는 방식이 아니라, 배포 시에 동적으로 추가해 주는 방식이 필요합니다.- Bitbucket 또는 GCP에 환경변수를 저장하고 사용하는 방식 중 한가지를 선택해야 합니다.
해결 방법 탐색
- 구글링을 통해서 다양하게 찾아 봤지만, 딱 알맞게 적용할 수 있는 방법은 찾지 못했습니다.
- Google Datastore에 저장하고 소스에서 직접 API를 호출해서 가져오는 방법은 GCP에 너무 종속적인 코드가 되는 것 같아서 제외 했습니다.
- 배포 시에 .env 파일을 만드는 방법은 App Engine이
standard
환경 일 때는 동작하지만flex
환경일 때는 동작하지 않습니다. - App Engine 배포 전 bitbucket pipelines 스크립트 실행 부분에서 수동으로 환경변수를
app.yaml
파일에 추가해 주는 방법이 그나마 괜찮은 방법 같았습니다.
해결 방법
- Bitbucket에 환경변수를 저장
- 저장 된 환경변수 이름을 관리하는 파일을 프로젝트에 추가
- 저장 된 환경변수 이름을 불러와서 app.yaml 파일에 추가하는 스크립트 생성
- Bitbucket pipelines를 통해서 Google App Engine으로 배포하기 직전에 해당 스크립트 실행
Bitbucket에 환경변수 저장
- 기존에
app.yaml
에 평문으로 저장되어 있던 환경변수를 모두 Bitbucket에 저장합니다. - Bitbucket의
Repository settings > PIPELINES > Deployments
페이지로 이동하여 환경변수를 추가합니다. - Secured 옵션을 선택하고 저장 한 값은 다시 확인이 불가능하니 반드시 별도로 저장하시기 바랍니다.
환경변수 목록 파일 추가
- 프로젝트 루트에
.env.array
파일을 생성합니다. - 생성 된 파일에 배포 시 자동으로 추가 할 환경변수 이름을 한 줄에 하나씩 추가합니다.
TEST_ENV1
TEST_ENV2
TEST_ENV3
환경변수 추가 스크립트 추가
- 프로젝트 루트에
add-env-to-gae-conf.sh
파일을 생성합니다. - 아래 스크립트 코드를 복사해 붙여 넣습니다.
#!/bin/bash# Set default file input/output name
FILE_INPUT_NAME=.env.array
FILE_OUTPUT_NAME=app.yaml# Set file input/output name, when user add options
while getopts "i:o:" opt; do
case $opt in
i)
FILE_INPUT_NAME=$OPTARG ;;
o)
FILE_OUTPUT_NAME=$OPTARG ;;
*) echo "usage: $0 [-i] [-o]" >&2
exit 1 ;;
esac
done# Read all environment variables that have to be copied from input file
declare env_array=()while IFS= read -r line || [[ "$line" ]]; do
env_array+=("$line")
done < "${FILE_INPUT_NAME}"# Print all environment variables to output file
if [ "${#env_array[@]}" -eq 0 ]; then
echo "There is no environment variables";
else
{ printf "\n\n"; printf "env_variables:"; printf "\n"; } >> "${FILE_OUTPUT_NAME}";for i in "${env_array[@]}";
do
printf " %s\n" "${i}: ${!i}" >> "${FILE_OUTPUT_NAME}";
done
fi;
- 스크립트 저장소 바로가기
- 기본 입력 파일 (
.env.array
), 기본 출력 파일 (app.yaml
) 이 설정되어 있고,-i, -o
옵션을 통해서 변경 가능합니다. - 입력 파일을 읽어서 해당 파일에 저장 된 환경변수 목록을 읽어
환경변수 이름: 값
형태로 출력 파일 가장 하단에 추가합니다. env_variables
항목을 통째로 추가하는 것이기 때문에 기존에env_variables
항목이 정의되어 있다면 삭제해야 정상적으로 동작합니다.- 실행되는 머신에 저장 된 환경변수를
app.yaml
파일에 유동적으로 추가해 줍니다. app.yaml
파일 하단에 아래와 같이 추가 됩니다.
env_variables:
TEST_ENV1: test string 1
TEST_ENV2: test string 2
TEST_ENV3: test string 3
환경변수 추가 스크립트 확인
- 로컬 머신에서 아래 명령을 실행하면
app.yaml
파일에 환경변수가 추가 되는 것을 확인할 수 있습니다.
export TEST_ENV1='test string 1'
export TEST_ENV2='test string 2'
export TEST_ENV3='test string 3'bash add-env-to-gae-conf.sh
Bitbucket Pipelines 배포 설정에 환경변수 추가 스크립트 실행 추가
bitbucket-pipelines.yml
파일 중 Google App Engine 배포 단계의 스크립트에 환경변수 추가 스크립트를 실행합니다.node:alpine
이미지를 기본으로 사용하여 bash를 별도로 설치해 줍니다.- 스크립트의 실행 권한을 주고, 스크립트를 실행한 후 정상적으로 추가 됐는지 확인하기 위해 출력합니다.
image: node:alpinerun-test: &run-test
step:
name: Run jest unit test
caches:
- node
script:
- yarn
- yarn testdeploy-dev: &deploy-dev
step:
name: Deploy Develop Branch to App Engine
deployment: gcp-dev
script:
- apk add bash
- chmod +x ./add-env-to-gae-conf.sh
- bash ./add-env-to-gae-conf.sh
- cat ./app.yaml
- pipe: atlassian/google-app-engine-deploy:0.7.3
variables:
KEY_FILE: $KEY_FILE
PROJECT: $PROJECT
STOP_PREVIOUS_VERSION: 'true'
DEBUG: 'true'pipelines:
branches:
master:
- <<: *run-test
develop:
- <<: *run-test
- <<: *deploy-dev
코드에서 확인
- 코드에서 확인하기 위해
process.env.TEST_ENV1
,process.env.TEST_ENV2
,process.env.TEST_ENV3
를 console.log에 찍거나 JSON 형태로 반환해 봅니다. - Bitbucket에 저장 한 값이 나온다면 정상적으로 동작하는 것입니다.
보완이 필요한 점
- 위에서도 언급했지만,
app.yaml
파일에env_variables
항목이 이미 있는 경우에는 정상적으로 동작하지 않습니다. - 이미 존재하는 환경변수도 함께 사용할 수 있는 방식으로 보완하면 더 좋을 것 같습니다.