Java/Spring

SpringBoot 설정 암호화

jwKim96 2022. 5. 27. 03:27

Github Action 을 이용한 배포 자동화를 진행해보려니, application.properties 의 민감정보를 어떻게 처리해야할지 고민이 되었습니다.

여러 방법을 찾아보다가, 찾은 선택지는 다음과 같습니다.

  1. 민감정보 환경변수(변수) 관리
  2. Secrets 에서 설정파일 내용을 읽어와서 Github Action 에서 설정파일 생성
  3. 민감정보 암호화

결론부터 말씀드리면 저는 4번 방법을 선택했는데요.
각 방법에 장단점이 있어서, 간단하게 정리해봤습니다.

방법 장점 단점
1. 민감정보 환경변수 관리 - 설정파일을 Github 에 올릴 수 있음 - 개발, 빌드, 서버 세곳의 환경변수를 관리해야함
- 관리할 민감정보가 많아질수록 관리하기 힘듦
2. Secrets 에서 설정파일 내용을 읽어와서
Github Action 에서 설정파일 생성
- Secrets 에만 최신화 해주면 됨 - 여러명이서 협업할 경우, 설정 파일을 공유하기 힘듦
3. 민감정보 암호화 - application.properties 를 Github 에 올릴 수 있음 - 정보가 변경될때 마다 다시 암호화 해야함

참고 : SpringBoot 설정파일 외부에서 읽기

1번의 경우에는 관리할 항목이 너무 많아지기 때문에, 선택하지 않았습니다.

2번의 경우에는 SpringBoot 에서도 외부 설정파일을 읽어와야 하고,
Github Action 에서도 설정 파일을 만들어주는 과정 때문에 작업이 복잡해져서 선택하지 않았습니다.

그래서 3번을 선택했는데요.
민감정보를 모두 암호화 하여 작성하고 암호키만 환경변수로 관리하면 되기 때문에, 이 방법을 선택했습니다.

SpringBoot 설정 암호화

제가 선택한 라이브러리는 간편한 암호화 기능을 제공하는 jasypt 입니다.

1. 의존성 추가

implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.4'

2. Configuration class 추가

// Configuration 클래스
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JasyptConfig {

    public static final String ENV_JASYPT_KEY = "encryption_key";

    @Bean
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();

        config.setPassword(System.getenv(ENV_JASYPT_KEY));
        config.setAlgorithm("PBEWithMD5AndTripleDES");
        config.setKeyObtentionIterations(1000);
        config.setPoolSize(1);
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);

        return encryptor;
    }
}

// TEST 클래스 
import org.jasypt.encryption.StringEncryptor;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import static org.assertj.core.api.Assertions.assertThat;

@TestConfiguration()
class JasyptConfigTest {

    private StringEncryptor encryptor;

    @BeforeEach
    void setUp() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JasyptConfig.class);
        encryptor = context.getBean(StringEncryptor.class);
    }

    @Test
    void 환경변수_설정여부_확인 () {
        // when
        String encryptionKey = System.getenv(JasyptConfig.ENV_JASYPT_KEY);

        // then
        assertThat(encryptionKey).isNotNull();
        assertThat(encryptionKey).isNotEmpty();
    }

    @Test
    void 암호화_테스트 () {
        // given
        String source = "암호화 테스트";

        // when
        String encrypted = encryptor.encrypt(source);
        String decrypt = encryptor.decrypt(encrypted);

        System.out.println(encrypted);

        // then
        assertThat(encrypted).isNotNull();
        assertThat(encrypted).isNotEmpty();
        assertThat(decrypt).isEqualTo(source);
    }

}

3. IntelliJ 실행/테스트 환경변수 추가

실행 환경 환경변수 추가

테스트 환경 환경변수 추가

왼쪽 아래의 Edit configuration templates... 를 클릭합니다.

4. 암호화 테스트 실행