IT recording...

[Spring] 자동배포시 secret 관리 본문

Spring

[Spring] 자동배포시 secret 관리

I-one 2022. 1. 13. 15:19

[원문 링크]

https://adorable-aspen-d23.notion.site/Spring-secret-297c0bf3b3a04dcb93f924eb9358f4f4

 

[Spring] 자동배포시 secret 관리

자동 배포를 위해 github action + code deploy + nginx 로 특정 action마다 자동배포가 되게 설정해보았다.

adorable-aspen-d23.notion.site

 

 

자동 배포를 위해 github action + code deploy + nginx 로 특정 action마다 자동배포가 되게 설정해보았다.

https://github.com/Jionee/autodeploy_practice

 

GitHub - Jionee/autodeploy_practice: repository for autodeploy

repository for autodeploy. Contribute to Jionee/autodeploy_practice development by creating an account on GitHub.

github.com

BUT, 문제가 발생한다. 배포를 위해 github에 올린다면 모두가 우리의 secret 정보를 볼 수 있고 그러면 보안에 심각한 위협이 된다는 것!

데이터베이스의 엔드포인트, username, password 등이 그 타깃이 될 수 있다.

따라서 이를 어떻게 숨길 수 있는지에 대해 살펴 보겠다.

간단히 말하면

  1. application.yml의 profile을 사용하기
    1. 기존 application-어쩌구.yml 들은 .gitignore에 추가
  2. github action의 secret 사용하기
    1. github secret에 등록하기
    2. CI.yml에서 echo를 통해 application-어쩌구.yml에 시크릿 값 넣기

1. application.yml의 profile 사용하기

//설명
* dev 개발시에는 testdb(h2)를 사용한다. + common,secret(기타 공통으로 숨겨야 할 내용) 
* prod 배포시에는 proddb(mysql)을 사용한다. + common,secret(기타 공통으로 숨겨야 할 내용) 

나의 경우는 총 4가지를 사용하였다.

  • src/main/resources/application.yml
#profile의 그룹을 설정한다. 예를 들면 dev로 run 환경을 설정하면 testdb, common, secret이 실행된다.
spring:
  profiles:
    group:
      "local": "testdb,common,secret"
      "dev":  "testdb,common,secret"
      "prod": "proddb,common,secret"

---

#공통적으로 설정되어야 할 내용들을 작성한다.
spring:
  config:
    activate:
      on-profile: "common"
  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        show_sql: true
        format_sql: true
logging:
  level:
    org:
      hibernate:
        type:
          descriptor:
            sql: trace
  • src/main/resources/application-prod.properties
spring.config.activate.on-profile="proddb"
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/각자db이름?validationQuery="select 1"
spring.datasource.username=각자유저네임
spring.datasource.password=각자비밀번호어쩌구
  • src/main/resources/application-dev.properties
spring.config.activate.on-profile = "testdb"
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url= jdbc:h2:tcp://localhost/~/각자db이름
spring.datasource.username=각자유저네임
spring.datasource.password=각자비밀번호어쩌구
  • src/main/resources/application-secret.properties
  • (기타 공통으로 숨겨야 할 내용 - 나는 jwt를 사용해서 이것을 숨기기 위해 작성하였다.)
jwt.secret = dsfwrsfwr123sfw=sdfweiweff1어쩌구저쩌구=

1-2) 해당 파일들은 .gitignore파일에 지정하여 git에 올라가지 않도록 한다.

### Config ###
application-dev.properties
application-prod.properties
application-secret.properties

2. github action의 secret에 시크릿 값들을 등록한다.

2-2) 자 이제 github action에서 어떻게 꺼내 쓸 지 설정해보자

- name: Decode application-prod file
  env:
    ACTIVATE_ON_PROFILE: ${{ secrets.ACTIVATE_ON_PROFILE }}
    MYSQL_DRIVER_CLASS_NAME: ${{ secrets.MYSQL_DRIVER_CLASS_NAME}}
    MYSQL_URL: ${{ secrets.MYSQL_URL }}
    MYSQL_USERNAME: ${{ secrets.MYSQL_USERNAME}}
    MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD}}
  run: |
    echo -e "spring.config.activate.on-profile=$ACTIVATE_ON_PROFILE\\nspring.datasource.driver-class-name=$MYSQL_DRIVER_CLASS_NAME\\nspring.datasource.url=$MYSQL_URL\\nspring.datasource.username=$MYSQL_USERNAME\\nspring.datasource.password=$MYSQL_PASSWORD\\n" > ./src/main/resources/application-prod.properties  

- name: Decode application-common file
  env:
   JWT_SECRET: ${{ secrets.JWT_SECRET }}
  run: echo jwt.secret=$JWT_SECRET > ./src/main/resources/application-secret.properties
  • env를 통해 깃허브 시크릿에 등록되어 있는 값들을 해당 run의 환경변수로 등록한다.
  • 그 후 echo를 이용하여 지정된 파일에 우리가 원하는 시크릿 내용을 작성하도록 한다.
    • echo -e를 쓴 이유?
      • echo의 경우는 \n과 같은 것들이 먹지 않으므로 앞에 -e 옵션을 주어 실행한다.
      • 맨 앞뒤 “” 가 존재해야 먹으므로 주의한다.
echo -e "spring.config.activate.on-profile=$ACTIVATE_ON_PROFILE\\nspring.datasource.driver-class-name=$MYSQL_DRIVER_CLASS_NAME\\nspring.datasource.url=$MYSQL_URL\\nspring.datasource.username=$MYSQL_USERNAME\\nspring.datasource.password=$MYSQL_PASSWORD\\n" > ./src/main/resources/application-prod.properties 

⇒ 실행시 ./src/main/resources/application-prod.properties에 아래 내용이 저장됨

spring.config.activate.on-profile="proddb"
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/각자db이름?validationQuery="select 1"
spring.datasource.username=각자유저네임
spring.datasource.password=각자비밀번호어쩌구
  • 전체 CI 파일 참고
# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
on:
  push:
    branches: [ feat_autodeploy ]

env:
  S3_BUCKET_NAME: omoolen-deploy 

jobs: 
  build: 
    runs-on: ubuntu-latest 
  
    steps:
      - name: Checkout 
        uses: actions/checkout@v2

      - name: Decode application-prod file
        env:
          ACTIVATE_ON_PROFILE: ${{ secrets.ACTIVATE_ON_PROFILE }}
          MYSQL_DRIVER_CLASS_NAME: ${{ secrets.MYSQL_DRIVER_CLASS_NAME}}
          MYSQL_URL: ${{ secrets.MYSQL_URL }}
          MYSQL_USERNAME: ${{ secrets.MYSQL_USERNAME}}
          MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD}}
        run: |
          echo -e "spring.config.activate.on-profile=$ACTIVATE_ON_PROFILE\\nspring.datasource.driver-class-name=$MYSQL_DRIVER_CLASS_NAME\\nspring.datasource.url=$MYSQL_URL\\nspring.datasource.username=$MYSQL_USERNAME\\nspring.datasource.password=$MYSQL_PASSWORD\\n" > ./src/main/resources/application-prod.properties  
      
      - name: Decode application-common file
        env:
         JWT_SECRET: ${{ secrets.JWT_SECRET }}
        run: echo jwt.secret=$JWT_SECRET > ./src/main/resources/application-secret.properties
        
      - name: Set up JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 11

      - name: Grant execute permission for gradlew 
        run: chmod +x gradlew 
        shell: bash 
      
      - name: Build with Gradle
        run: ./gradlew build -x test
        shell: bash
        
      - name: Make zip file 
        run: zip -r ./$GITHUB_SHA.zip . 
        shell: bash 
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2
          
      - name: Upload to S3 
        run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip
        
      - name: Code Deploy
        run: aws deploy create-deployment --application-name pratice-deploy --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name develop --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$GITHUB_SHA.zip

참고

spring boot 에서 profile 사용한 application.properties 로딩 (gradle build)

참고

https://github.com/wkk91193/harry-kart/blob/master/.github/workflows/master_harry-kart-web-api.yml

https://ji5485.github.io/post/2021-06-26/create-env-with-github-actions-secrets/

https://devblog.croquis.com/ko/2020-11-06-1-using-github-actions/

https://velog.io/@jsje02/스프링-입문-6-스프링-DB-접근-기술

Comments