본문 바로가기
[IT]/SpringBoot

[Spring Boot] 설정파일 암호화 (application.yml)

by dop 2021. 4. 28.

설정파일 암호화

보통 Spring 프로젝트를 진행하면 application.yml(.propertise)파일을 이용해 프로젝트 설정을 관리하게 되고, DB Connection 관련 부분도 다음과 같이 작성하게 된다.

spring:
  output:
    ansi:
      enabled: always
  datasource:
    url: jdbc:mariadb://(서버주소):3306/(DB명)
    username: (id)
    password: (pw)
    driver-class-name: org.mariadb.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: none  #create , create-drop , update , validate, none
    properties:
      hibernate:
        show_sql: true
        format_sql: true

로컬 DB만으로 작업한다면 서버주소에 lcoalhost를 넣어버리면 되니까, github과 같은 저장소에 id와 pw가 유출되어도 치명적으로 작용하지는 않을 것이다. 하지만, 배포를 하거나, 외부 DB에 접근하는 경우에 id, pw, 서버주소까지 노출하게 된다면, 외부 공격을 당할 가능성이 열려있기 때문에 위험하다.

아무튼! 이런 이유로 id와 pw를 암호화 하여 설정파일을 관리하도록 하자.
일단 암호화해줄 라이브러리를 추가해주도록 하자.

    compile (group: 'com.github.ulisesbocchio', name: 'jasypt-spring-boot-starter', version: '2.1.1')
    compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.61'

암호화/복호화 해줄 Config 클래스가 필요하다.
설정 클래스에 @EnableEncryptableProperties를 추가해주고, 암호화 알고리즘과 키(Password)값을 지정해 주도록 하자.

@Configuration
@EnableEncryptableProperties
public class PropertyEncryptConfig {

    @Bean("encryptorBean")
    public PooledPBEStringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        encryptor.setProvider(new BouncyCastleProvider());
        encryptor.setPoolSize(2);
        encryptor.setPassword("MySecretKey");
        encryptor.setAlgorithm("PBEWithSHA256And128BitAES-CBC-BC");
        return encryptor;
    }
}

테스트 코드에서 잘 암/복호화가 되는지 확인해 보도록 하자

@SpringBootTest
public class EncryptTest {

    @Test
    public void checkEncrypt(){
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        encryptor.setProvider(new BouncyCastleProvider());
        encryptor.setPoolSize(2);
        encryptor.setPassword("MySecretKey");
        encryptor.setAlgorithm("PBEWithSHA256And128BitAES-CBC-BC");

        String plainText = "root"; // 암호화 할 내용
        String encryptedText = encryptor.encrypt(plainText); // 암호화
        String decryptedText = encryptor.decrypt(encryptedText); // 복호화
        System.out.println("Enc:"+encryptedText+", Dec:"+decryptedText);
    }
}

출력 내용 : Enc:7WaPANUsZ2BgChaav82ZBgMzJ4LY5a2z9d6SKAB+Y2LpWxWPvFoQAPrMUoGhi6m8, Dec:root

위와같이 출력되면 성공이다. 암호화 할 문자열을 plainText에 넣어서 암호화 시키고, yml파일에 다음과 같이 사용하면 된다

jasypt:
  encryptor:
    bean: encryptorBean
    username: ENC(tB5rllJdNVCnHIgiYnIZ+nfS5yhqBCYag0q+egT4pS+UngjSmOK7aacPO0/ObecK)
    password: ENC(k0SQ5Ypj/86aDM+snjlgI5Ox+3OAgu7Xh6db6y6L3ikLMFcD7jNfxfZtrhfNlcnT)

이런식으로 작성하면 잘 실행되는 것을 확인할 수 있다.

하지만 과연 안전하다고 할 수 있을까??? 이렇게만 하고 끝낸다면, 문을 자물쇠로 잠궈놓고 열쇠를 문 앞에 두고가는 것과 다름이 없다. 암호화 설정 내용이 담긴 클래스와 암호화 된 내용이 담긴 yml 파일이 노출되기 때문에 그대로 가져다가 쓰면, 뚫리는 건 매한가지이다.

 실제 배포환경에서는 민감정보는 ${"ValueName"} 같은 방식으로 설정 파일에 작성하고, 서버 단에서 값을 넣어주는 방식을 활용한다. AWS Secret Manager를 이용해서 설정파일의 값을 안전하게 관리할 수 있다고 한다. 참고로 30일만 무료라고 한다.

 

 

[참고 링크] : goateedev.tistory.com/131

728x90