본문 바로가기
개발자 준비/개발 공부

동적 주입으로 버전 관리시 DB 연동 정보 숨기기

by osul_world 2022. 12. 2.
728x90

서버가 DB와 연결되는 부분에서의 위험

기존 RDS 연결 방식

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
//application.yml에 데이터 베이스와 연결하는 인증 정보가 그대로 노출됨
    url: example.db.net  
    username: ohseungyun 
    password: passwordString 
  jpa:
    database: mysql
    generate-ddl: true
    show-sql: true

위험! 깃 허브를 통해 소스코드를 관리하는 등 버전 관리 로그를 통해 소스코드가 유출되면 데이터 베이스가 직접 공격 받을 수 있다

위험! 데이터 베이스 관리자 이외에도 버전 관리에 동참하는 모든 사람은 권한과 관계없이 데이터 베이스 연결 정보를 알게 된다

 

개선된 RDS 연결

  1. 우선, 대칭키 암호 알고리즘을를 이용해 application.yml에 데이터 베이스와 연결하는 인증 정보 값을 암호화
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
//암호화된 값으로 표시됨
    url: ENC(HLNVkrnK/9aSB19Ehc53W5UiVCAahkCLVkvOyqjRyN6+U5tkR3aH/Kk9jFz5giV6qzXqWOeeegDATsQYL/SQcYd5QRhpAmFXCtSBDqGupfX7G1uq275emdG1nYaT3JQ5MfYsHqInRY)
    username: ENC(d76s+swPRMX6c0RYK2GKo78htB6)
    password: ENC(Dbu9GoFb1HX3q0swGDX2zv7ccxQqGydNs0=)
  jpa:
    database: mysql
    generate-ddl: true
    show-sql: true

문제! 서버 자체도 해당 키 없이는 암호문을 복호화 할 수 없다

 

  1. key값을 가지고 해당 암호문을 복호화할 클래스 JasyptConfig 생성
@Configuration
public class JasyptConfig {

    private String encryptKey = "key노출"; //정적 주입!

    @Bean("jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(encryptKey);
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }

}

문제! 복호화를 위해 이용되는 key값이 정적 할당 되면서 다음처럼 소스코드에 노출되는 문제, 노출되는 위치만 바뀌었을 뿐 위험이 해소되지 않았다

 

해결 아이디어: 모두 런타임에 동적으로 주입해 버리기

JasyptConfig에서 key값은 @Value를 활용해 application.yml에 선언한 환경변수 값을 런타임에 가져와 선언하도록 변경하고,

@Configuration
public class JasyptConfig {
    @Value("${enviroment}") //런타임에 환경 변수를 찾아 값을 동적 할당할 예정
    private String encryptKey;

    @Bean("jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(encryptKey);
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }

}

마찮가지로 application.yml에서 정적으로 환경 변수를 선언하지 않고,

환경 변수 값은 Github Action Workflow를 통해 CI/CD 과정에서 application.yml에 환경변수를 선언하는 라인을 동적으로 추가하도록 한다.

//현재 application.yml에는 환경변수 선언이 되어있지 않다.
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: ENC(HLNVkrnK/9aSB19Ehc53W5UiyN6+U5tkR3aH/Kk9jFz5giV6qzXqWOeeegDATsQYL/SQcYd5QRhpAmFXCtSBDqGupfX7G1uq275emdG1nYaT3JQ5MfYsHqInRY)
    username: ENC(d76s+swPRMX6c0RtB6)
    password: ENC(Dbu9GoFb1ccNGmGBzSQfxQqGydNs0=)
  jpa:
    database: mysql
    generate-ddl: true
    show-sql: true

Github Action Workflow에 리눅스 명령어를 통해 application.yml에 enviroment: key 환경 변수 선언 라인을 동적으로 추가 하도록 명령 합니다

이때, 깃에서 보안 관리해주는 Git Secrets를 통해 enviroment: key 라는 실질 적인 환경 변수 값은 아래와 같이 외부에서 주입 받도록 합니다

#jasypt 복호화 키 환경변수 application.yml에 생성하기 in 리눅스 명령어
      - name: add code in application.yml for jasypt key env
        run: |
          cd ./src/main/resources
					//선언 라인은 Git Secrets에서 주입
          echo "${{ secrets.JASYPT_KEY }}" >> ./application.yml 
        shell: bash

 

정리

이렇게 되면, 깃허브 소스코드 저장소에 application.yml은 enviroment: password 이라는 라인을 가지고 있지 않아, 환경변수를 확인할 수 없다.

또한, workflow에도 Git Secrets를 이용했기 때문에 enviroment: password 이라는 라인을 확인할 수 없다.

CI수행 과정에서 동적으로 해당 라인이 생성되어 빌드되고 배포가 이루어지기 때문에 서버 구동은 정상적으로 이루어진다.

이로써, 버전 관리 과정에서 민감한 정보는 모두 숨겨졌다.

 

728x90