ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 프로젝트 실행 시 환경변수 안전하게 주입하기 | AWS Secrets Manager로 환경변수 관리하기
    Project 2024. 8. 2. 22:49

     

     

    프로젝트 진행 시 발생하는 보안 문제 중 가장 흔한 것은 설정파일에서의 민감정보 노출일 것이다. 

    spring boot 프로젝트에선 application.yml 등의 설정파일에 데이터베이스 설정 정보 및 API 키 등을 작성해 놓는데, 이번 포스팅에서는 배포환경에서 어떻게 안전하게 민감정보들을 저장할 수 있는지 알아보자. 

     

     

     

    먼저 소스코드를 Github에 퍼블릭하게 올려놓을 때 업로드 전 properties파일에 민감정보가 없는지 꼭 확인하고 업로드 해야한다.

    뒤늦게 확인하고 수정하더라도 이미 히스토리로 확인이 가능하기 때문에 보안 취약점이 노출될 수 있다. 

     

     

    로컬에서 작업시 프로젝트 IDE에서는 시스템 환경변수를 다음과 같이 설정했었다. 

     

    Run - Edit Configuration의 Build and Run 항목에 modify options을 선택하면 Environment variables 옵션이 있다.

     

     

    클릭해 다음과 같이 key-value형태로 저장하고, 이를 application.yml에서 placeholder로 key 네임을 작성해 준다. 

     

     

    실행하면 정상적으로 접근하는 것을 알 수 있다.

    이렇게 OS에서 시스템 환경변수를 확인할 수 있도록 해줬고 소스코드에서도 민감정보를 감출 수 있게 되었따. 

    그러나 배포 시엔 어떻게 주입시켜줘야 할까? 

     

     

    배포환경에서 환경변수 설정하기

    1. 실행 시 command에서 설정하기 

    java -jar myselectshop-0.0.1-SNAPSHOT.jar -DADMIN_TOKEN=토큰값 -DDATABASE_SOURCE_URL=데이터베이스URL값

     

    배포할 서버에 빌드해놓은 jar 파일을 실행하면서 -D 파라미터로 시스템 프로퍼티들을 넣어줄 수 있다. 하지만 일일이 입력해 주는 번거로움, 프롬포트에 값들이 노출된다는 단점이 있다. 

     

     

    2. 외부파일에 작성하여 관리하기 

    #env_variable.sh
    export API_NAVER_CLIENT="값"
    export API_NAVER_SECRET="값"
    export DATASOURCE_DBNAME="shopdb"
    export DATASOURCE_PASSWORD="값"
    export DATASOURCE_URL="값"
    export DATASOURCE_USERNAME="값"

     

    배포서버에 다음과 같이 환경변수 이름과 값을 매핑한 파일을 저장해 놓고 source 명령을 통해 적용시켜놓는 방법도 있다. 

    sudo source env_variable.sh
    nohup java -jar myselectshop-0.0.1-SNAPSHOT.jar > output.log 2>&1 & // nohup으로 백그라운드에서 실행

     

    그러나 파일에 직접적으로 작성하여 민감정보가 유출될 수 있는 가능성이 존재한다. 

     

     

    3. 서드파티에서 민감정보를 관리하고 해당 서비스에서 접근해서 사용하기 

    따라서 안전하게 보관하기 위해 외부에 민감정보 관리를 맡겨놓는 경우가 일반적이다. key-value 모두 외부서비스에 작성해 놓고 배포서버에서 접근만 하도록 하는 것이다.

     

    키관리 서비스로 HashiCorp의 Vault 등 다양한 서비스들이 있는데, 현재 내가 배포할 서버 및 데이터베이스가 AWS 서비스라서 AWS가 제공하는 비밀 키 관리 서비스인 AWS Secret Manager를 활용해보려고 한다. 

     

     

    AWS Secret Manager로 키 관리하기

    AWS Secret Manager에서 새 시크릿 저장하기

     

     

    AWS Secret Manager 서비스에서 - create secret 버튼을 클릭해서 other type of secret을 선택, 키와 밸류를 입력한다. 
    딱히 캡처를 안한 부분은 디폴트 설정을 그대로 유지했다. 

     

     

    Next버튼을 클릭하여 secret name을 자유롭게 설정한다.
    다음페이지는 키를 주기적으로 업데이트하는 Rotation 설정인데 부수적인 설정이라 Next 버튼을 클릭하여 넘기고 마지막으로 store버튼을 눌러 시크릿을 저장한다. 

     

     

    AWS EC2 인스턴스에 Secret Manager 접속 권한 부여하기 

     

    이제 EC2 인스턴스에서 Secret Manager를 접근할 수 있도록 IAM 설정을 해줘야 한다. 

     

    IAM 콘솔에 접속하여 Roles 탭의 Create Role을 클릭한다

     

     

    EC2에 롤을 부여해주기 위해 AWS service를 선택하고 EC2 유즈케이스를 선택하여 넘어간다. 

     

     

    퍼미션에서 Secret Manager 읽기 쓰기 권한을 찾아 선택하고 Next 버튼을 눌러 Role 선택을 마무리한다. 

     

     

    만들어진 IAM role을 부여하기 위해 다시 EC2 콘솔에 접속하여 인스턴스 선택 후 Actions - Security - Modify IAM role로 접속한다 

     

     

    아까 만들었던 IAM role을 찾아 업데이트하고 인스턴스 상세 - Security 탭에 적용되어 있는 것을 확인한다 

     

    배포서버에서 Secret Manager에 접근한 후 실행하기

     

    외부서비스에 key-value를 입력했고 접근하기 위한 권한도 부여했으니 이제 인스턴스에서 실행해보자. 

     

    1. AWS EC2 인스턴스를 접속해서 AWS-CLI 설치하기 

    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    unzip awscliv2.zip
    sudo ./aws/install

     

    Secret Manager에서 키 정보를 가져오기 위해 EC2 서버에 AWS-CLI를 설치한다. 

     

     

     

    2. 실행을 위한 배치 스크립트 작성하기 

    # start_app.sh 파일에 아래 내용 한번에 작성 
    
    # AWS Secrets Manager에서 시크릿 가져오기
    SECRET_JSON=$(aws secretsmanager get-secret-value --secret-id "설정했던SecretName입력" --query "SecretString" --output text)
    
    # 시크릿 값들을 환경 변수로 설정 - 시크릿매니저에 등록한 key이름과 동일해야함
    # export 키이름=$(echo $SECRET_JSON | jq -r '.키이름')
    export ADMIN_TOKEN=$(echo $SECRET_JSON | jq -r '.ADMIN_TOKEN')
    export API_NAVER_CLIENT=$(echo $SECRET_JSON | jq -r '.API_NAVER_CLIENT')
    export API_NAVER_SECRET=$(echo $SECRET_JSON | jq -r '.API_NAVER_SECRET')
    export DATASOURCE_DBNAME=$(echo $SECRET_JSON | jq -r '.DATASOURCE_DBNAME')
    export DATASOURCE_PASSWORD=$(echo $SECRET_JSON | jq -r '.DATASOURCE_PASSWORD')
    export DATASOURCE_URL=$(echo $SECRET_JSON | jq -r '.DATASOURCE_URL')
    export DATASOURCE_USERNAME=$(echo $SECRET_JSON | jq -r '.DATASOURCE_USERNAME')
    export JWT_SECRET_KEY=$(echo $SECRET_JSON | jq -r '.JWT_SECRET_KEY')
    
    # Java 애플리케이션 실행
    nohup java -jar myselectshop-0.0.1-SNAPSHOT.jar > output.log 2>&1 &

     

    먼저 secret name을 기준으로 키를 가져오는데, SectetString이 아까 저장해놓은 Key-Value를 json형식으로 저장하고 있는 필드다.

    따라서 해당 SectetString을 파싱해 환경변수로 설정하고 자바 어플리케이션을 백그라운드로 실행할 수 있도록 한다. 

     

     

    3. 애플리케이션 실행 후 정상적으로 연결되는 것 확인하기

    ./start.sh

     

    위에서 만든 스크립트를 실행하고 나와 output.log에서 정상적으로 실행되는지 확인한다.

    tail -f output.log

     

     

     

    정상적으로 접속됨을 알 수 있다. 
    AWS Secret Manager로 활용시 과금이 발생하는지 AWS 빌링을 통해 지속적으로 확인하길 바란다

Designed by Tistory.