유랑하는 나그네의 갱생 기록

だけど素敵な明日を願っている -HANABI, Mr.children-

Devlog/SpringBoot

[Spring Boot] Properties Encryption

Madirony 2024. 7. 18. 23:24
728x90

Properties 암호화의 중요성?

GitGuardian

 첫 번째 프로젝트 발표를 마쳤을 때, 그동안 했던 프로젝트를 GitLab에서 GitHub로 미러링 하는 과정에서 GitGuardian으로부터 메일이 왔었습니다. 외부로 공개되어서는 안 될 value가 노출이 되었던 겁니다. 첫 번째 프로젝트에서는 application.properties에 담겨있는 value들에 대해 암호화 처리를 하지 않았었죠.. 첫 프로젝트라 다들 어수선하기도 했고 미러링에 문제가 생기자 팀원 중 한 명이 properties 파일을 제거해 버렸습니다..

 

...

 처음부터 properties에 대해 암호화를 적용시켰더라면 이러한 불상사를 막을 수 있었을 텐데..

라는 생각이 들었습니다. 그래서? 두 번째 프로젝트부터는 인프라 세팅을 하면서 스켈레톤 프로젝트의 properties 파일에 암호화를 적용하고 싶었습니다. 이와 관련된 정보를 알아보던 도중 Jasypt라는 것을 알게 되었습니다.


Java Simplified Encryption

 

 Jasypt는 Java 애플리케이션에서 암호화 작업을 간단하게 해주는 오픈소스 라이브러리입니다. 다양한 암호화 알고리즘(AES, DES, PBE, etc..)을 지원하면서, 설정 파일이나 데이터베이스에 저장된 데이터를 암호화하고 복호화할 수 있습니다.

 

 spring boot에서는 ulisesbocchio라는 아저씨가 만든 걸 사용합니다.

https://github.com/ulisesbocchio/jasypt-spring-boot

 

GitHub - ulisesbocchio/jasypt-spring-boot: Jasypt integration for Spring boot

Jasypt integration for Spring boot. Contribute to ulisesbocchio/jasypt-spring-boot development by creating an account on GitHub.

github.com


제 프로젝트에 어떻게 적용하나요?

1. build.gradle에 아래의 종속성을 추가합니다. 현재까지는 3.0.5 이후로 업데이트가 되지 않아 이게 최신버전입니다.

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

 

※ jasypt 3 버전 이상 적용했을 때 jdk 1.8에서 지원하지 않는 기본 알고리즘이 있다는 이슈가 있어서 jdk 1.8을 쓴다면 다운 그레이드해야 합니다.

 

2. @EnableEncryptableProperties Config를 추가합니다.

package {패키지명};

import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableEncryptableProperties
public class JasyptConfig {

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

    @Bean
    public PooledPBEStringEncryptor jasyptStringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        encryptor.setPoolSize(8);
        encryptor.setPassword(key);
        encryptor.setAlgorithm("PBEWithMD5AndTripleDES");

        return encryptor;
    }
}

 Config를 설정해 주면 암호화 가능한 속성(environment property, command line argument, application.properties, yaml properties...)은 전체 Spring 환경에서 활성화됩니다.

 

 코드를 좀 분석해 볼까요?

@EnableEncryptableProperties는 Jasypt를 사용하여 암호화된 프로퍼티를 처리할 수 있도록 활성화하는 어노테이션입니다.

jasypt.encryptor.password의 값은 3단계에서 설정할 겁니다.

@Value("${jasypt.encryptor.password}")

 

그 후, PooledPBEStringEncryptor 객체를 생성하고 Bean으로 등록합니다.

  • encryptor.setPoolSize()는 암호화/복호화 작업을 위한 스레드 풀의 크기를 설정하는 부분입니다.
  • encryptor.setPassword()는 3단계에서 설정할 암호화키를 세팅해 주는 부분입니다.
  • encryptor.setAlgorithm()은 사용할 알고리즘을 설정합니다.

 

3. VM 옵션도 추가합니다.

 

1
2

-Djasypt.encryptor.password={암호화키}

 암호화 키는 임의대로 설정하시면 됩니다. 그리고 만약 Docker를 사용하고 있다면, 이미지를 실행시킬 때 환경 변수로 상기의 옵션을 넣어주면 됩니다. 다른 방법들도 있긴 한데 이 방법이 제일 무난하다고 생각합니다.

 

3-1. 다른 방법도 있습니다.

 application.properties에 다음과 같이 한 줄 추가해 줘도 되는데, 요 부분은 커밋하면 안 되겠죠?

jasypt.encryptor.password={암호화키}

 

3-2. 또 다른 방법도 있습니다.
 Jasypt CLI를 사용하여 데이터를 암호화할 수 있습니다. Maven을 통해 Jasypt CLI를 설치하고, 다음 명령어를 사용하여 데이터를 암호화할 수도 있습니다.

mvn jasypt:encrypt-value -Djasypt.encryptor.password={암호화키} -Djasypt.plugin.value="{value}"

 

4. Test Code를 만들고 암호화 테스트를 진행합니다.

package {패키지명};

import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class JasyptConfigTest {
    @Test
    @DisplayName("properties 암호화 테스트")
    public void jasyptEncryptorPassword() {
        String key = "{암호화키}";
        
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        encryptor.setPoolSize(8);
        encryptor.setPassword(key);
        encryptor.setAlgorithm("PBEWithMD5AndTripleDES");

        String str = "{value}";
        String encryptStr = encryptor.encrypt(str);
        String decryptStr = encryptor.decrypt(encryptStr);

        System.out.println("ENC : " + encryptStr);
        System.out.println("DEC : " + decryptStr);
    }
}

 

test folder

 테스트 코드를 만들었다면? 실행

복호화도 잘되었는지 체크한 후, 암호화된 값을 properties 파일에다가 붙여놓고 ENC()로 감싸주면 됩니다.

 

Encryption Image!

근데, 저 yml 쓰는데...
spring:
  datasource:
    hikari:
      maximum-pool-size: ####
    url: ENC(+XPODfbCmaEUcFm0NFTFcIRBn96DqfB8KiA1wep/kszK2yKypopESCkZXk13Wuj0/BH1A1iNAGU=)
    username: ENC(GSpxgpIVOhZVryh0i9gn5hx0MD/qinGC)
    password: ENC(vOKU56G/+aomdpR97oe99Q==)

jasypt:
  encryptor:
    bean: jasyptStringEncryptor

 application.properties처럼 똑같이 해주면 됩니다.

 

좀 더 자세히 들어가고 싶다면 울리세스 아저씨 Github를 참고하면 되겠습니다!

https://github.com/ulisesbocchio/jasypt-spring-boot

 

728x90