Back-End/Spring 자료실

[스프링 부트] Jasypt 설정 암호화로 Github Repo 에 안전하게 올리기

Chipmunks 2023. 6. 20. 02:44
728x90

안녕하세요.

스프링 부트에서 Jasypt 라이브러리를 사용해서 설정을 암호화하는 방법을 알아봅시다.

application.yml 파일에 아래와 같이 DB 접속 정보를 저장해둔다면, Github 레포에 올리지 못하겠죠?

spring:
  profiles: local
  datasource:
    url: DB주소
    username: DB계정
    password: DB비밀번호
    driver-class-name: com.mysql.cj.jdbc.Driver

applicaiton.yml 을 .gitignore 파일에 추가하면, Git Stage 에 올라가지 않습니다.

그 다음에 작업자들끼리만 application.yml 파일을 공유해도 되지만,

공개 가능한 다른 설정까지 번거롭게 변경할 때 마다 모든 작업자들끼리 동기화하는 게 여간 귀찮은 일이 아닙니다.

 

Jasypt 라이브러리를 사용하면 환경 변수나 IDE VM Option 에 암호화 키만 등록하면,

설정 파일에 민감한 정보를 그대로 Github 깃허브 레포에 올릴 수 있게 됩니다.

설정 파일에는 아래와 같이 암호화된 문자열만 들어가서 안전합니다.

spring:
  profiles: local
  datasource:
    url: ENC(qJcIphp38nLaMwEHY2nO22BQEPIEF8yWA1eQIUCs70jIm8XjBGlxKblYHGFx/MaGU7c0Zz2I4nnLYTe3YD8ne+n9g1VZwwhpdS666PEEkkhFraY9Ck84lIoFmTROXRhW38rkBLyxoOSQlQI55T1bpH63BQnf+HoTp04ZMF34fp8cuRUSTY=)
    username: ENC(CVvoCs9unAb7HYSbkbF+mPj)
    password: ENC(45XIx7pX22h/sW7SQIrL7q/N9bpb5acKBks=)

 

1. Jasypt 라이브러리 Gradle 의존성 추가

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

위 코드로 Gradle 의존성에 추가하여 설치합니다.

인텔리제이 기준 Gradle 정보가 변경되면, 에디터 우측 상단에 Gradle 의존성을 새로고침하는 버튼이 나타납니다.

이 버튼을 눌러 Gradle 의존성을 새로 설치합니다.

또는 우측 Gradle 탭을 눌러 새로고침을 해줘 Jasypt 라이브러리 의존성을 설치합니다.

 

2. Jasypt Configuration 빈 등록

Jasypt 관련 설정해주는 @Configuration 빈을 등록합니다.

 

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JasyptConfig {

    @Value("${jasypt.encryptor.password}")
    private String encryptKey;

    @Bean(name = "jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(encryptKey); // 암호화할 때 사용하는 키
        config.setAlgorithm("PBEWithMD5AndDES"); // 암호화 알고리즘
        config.setKeyObtentionIterations("1000"); // 반복할 해싱 회수
        config.setPoolSize("1"); // 인스턴스 pool
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator"); // salt 생성 클래스
        config.setStringOutputType("base64"); //인코딩 방식
        encryptor.setConfig(config);
        return encryptor;
    }
}

JasyptConfig 빈을 생성할 때, 설정에서 jasypt.encryptor.password 값을 가져와 encryptKey 변수에 주입합니다.

jasypt.encryptor.password 는 암호화 해주는 키이며, 스프링 부트 서버를 실행할 때 외부에서 주입할 예정입니다.

바로 설정 해볼까요?

 

3. Jasypt.encryptor.password 값 설정

 

인텔리제이 기준으로 Application 클래스에다 코드 라인 넘버에 있는 실행 버튼을 누릅니다.

Modify Run Configuration 메뉴를 누릅니다.

Modify options > Add VM options 를 눌러, VM options 텍스트 칸을 활성화 시킵니다.

-Djasypt.encryptor.password=랜덤문자열

으로 설정합니다.

 

실행 설정한 걸 보려면 상단 메뉴 Run > Edit Configurations ... 에서 모두 확인이 가능합니다.

다른 작업자에게 설정 방법을 공유하거나, 앞으로 테스트 코드에서도 또 설정해야 하므로 숙지해주시면 좋습니다.

 

4. 암호화 문자열을 구할 테스트 코드 작성

그렇다면 이제 암호화한 문자열을 어떻게 얻을 수 있을까요?

매 번 문자열을 암호화할 때 마다, 다른 프로덕션 코드와 같이 실제 서버를 실행시키면서 얻는다면 시간도 오래 걸리고

비효율적으로 얻을 겁니다.

테스트 코드를 활용하면 프로덕션 코드를 실행하지 않고도 간단하게 암호화한 문자열을 얻을 수 있습니다.

 

테스트 코드를 실행할 때마다 jasypt.encryptor.password 값을 넣어줘야 한다면, 어떻게 해야 할까요?

Gradle 코드에서 아래처럼 추가해줄 수 있습니다.

테스트를 실행시킬 때 jasypt.encryptor.password 를 VM options 에서 가져오고 프로퍼티에 등록해줍니다.

tasks.named('test') {
	useJUnitPlatform()
	systemProperty "jasypt.encryptor.password", System.getProperty("jasypt.encryptor.password")
}

 

plainText 변수에 암호화하고 싶은 값을 입력하여 테스트를 실행하면,

System.out.println(encryptedText) 으로 암호화한 값을 확인할 수 있습니다.

import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;

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

public class JasyptTest extends JasyptConfig {

    @Test
    public void jasypt_encrypt_decrypt_test() {
        String encryptKey = System.getProperty("jasypt.encryptor.password");

        String plainText = "";

        StandardPBEStringEncryptor jasypt = new StandardPBEStringEncryptor();
        jasypt.setPassword(encryptKey);

        String encryptedText = jasypt.encrypt(plainText);
        String decryptedText = jasypt.decrypt(encryptedText);

        System.out.println(encryptedText);

        assertThat(plainText).isEqualTo(decryptedText);
    }
}

 

마찬가지로 VM options 에 등록시켜줍니다.

 

plainText 값을 변경한 다음 테스트 코드를 실행합니다.

String plainText = "암호화하고싶은문자열";

테스트 결과창을 보면 아래처럼 암호화한 값을 얻을 수 있습니다.

 

이제 환경설정에 암호화한 값을 입력해줍니다.

 

5. 암호화한 문자열 설정 파일에 대체

application.yml 에 아래처럼 등록해줍니다.

암호화한 문자열을 그대로 넣는게 아니라, 'ENC(암호화한문자열)' 형태로 넣어줍니다.

spring:
  datasource:
    url: ENC(qJcIphp38nLK6wAUrFUJv6MsP1XaMwEHY2nO22BQEPIEF8yWA1eQIUCsVxDIZ6XJm70jIm8XjBGlxKblYHGFx/MaGU7c0Zz2I4nnLYTe3YD8ne+n9g1VZwwhpdS666PEEkkhFraY9Ck84lIoFmTR=)
    username: ENC(CVvoCs9unAbL2iuSbkbF+mPj)
    password: ENC(45XI2J452h/sW7S58rL7q/N9bpb5oks=)

 

6. jasypt.encryptor.password 값 작업자끼리 공유

설정한 jasypt.encryptor.password 값을 작업자끼리 공유하여 IDE에 똑같이 설정합니다.

스프링 부트 jar 파일을 실행할 때도 jar -Djasypt.encryptor.password=설정한키값 형태로 넘겨주는 것도 잊지 않기를 바랍니다.

 

7. Github 에 안심하고 업로드

Github 에 암호화한 키를 실수로 올리지 않는 한, 안심하고 민감한 정보가 들어간 설정 파일을 업로드할 수 있습니다.

 

긴 글 봐주셔서 감사합니다.

도움이 되었다면, 공감과 댓글 부탁드려요.