프로젝트를 진행하다 보면 공개된 repo에 업로드되면 안되는 민감 정보들이 있기 마련인데(예를 들어 RDS 엔드포인트, OAuth 2.0 client-secret 등등) 이와 같은 정보들은 암호화하여 업로드해야 한다. 우리들은 어떻게 민감 정보를 감출 것인지 여러 기술들을 검토했는데 그 중 jasypt로 하는 게 좋을 것 같아서 이 기술을 채택했다. (Spring Config Cloud 를 사용하려고 했는데 깃헙 저장소를 3개나 사용하더라...) 지금부터 Jasypt를 이용해서 민감 정보를 암호화해보자.
프로젝트를 만들면서 필요한 부분을 정리하고 있습니다.
모호하거나, 잘못된 부분이 있으면 댓글로 남겨주세요! 감사합니다 :)
다음 의존성을 추가한다.
compile group: 'com.github.ulisesbocchio', name: 'jasypt-spring-boot-starter', version: '3.0.3'
다음 클래스를 추가해준다.
@Configuration
public class JasyptConfig {
@Bean("jasyptStringEncryptor") // (1)
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("hello"); // (2)
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}
}
(1) jasypt 3.0 이상 버전을 사용한다면 'jasyptStringEncryptor'을 사용해주자. 공식 문서에는 'encryptorBean' 을 사용하기도 하는데 3.0 이상 버전에서 에러가 발생한다. 참고 사이트
(2) 자신이 암호화 할 때 설정한 시크릿 키를 넣어준다. 시크릿 키도 암호화하고 싶다면 시스템 환경변수로 설정해두고 가져다 쓰자. (밑에서 설명)
이로써 Jasypt에 관한 설정이 마무리가 됐다.
Jasypt 는 다양한 설정을 할 수 있도록 지원하고 있는데 초보자가 커스텀하게 설정해서 사용하기에는 어렵고 복잡하다. 그래서 'jasypt-spring-boot-starter' 를 제공하여 초보자도 간단하게 사용 할 수 있게 지원해주는 것 같다. 내가 커스텀하게 암호화 설정을 하고 싶다면 공식 문서를 참고하길 바란다.
Jasypt를 사용하여 민감 정보를 암호화 하기 위해서는 다음과 같은 과정이 필요하다.
민감 정보를 암호화 해주는 방법으로 CommandLineRunner 와 사이트 이용 등 여러 방법이 있는데 나는 민감 정보를 암호화 해주는 사이트를 이용했다.
사이트 이용 방법은 다음과 같다.
암호화 할 문자를 입력하세요
더 강화된 암호화를 위해 비대칭 암호화를 사용하려고 합니다. Two Way Encryption(With Secret Text) 를 선택해주세요
시크릿 키를 입력해주세요. 이 시크릿 키는 로그인 시 사용하는 ID/PWD 에서 PWD 같은 역할입니다. 시크릿 키를 모르면 복호화 할 수 없습니다. 참고로 이 키를 설정해주는 이유에 대해선 비대칭 암호화를 공부해주세요.
'Encrypt' 를 누른 뒤 성공하면 비대칭 암호화를 통해 암호화된 문자열이 나타납니다. 우리는 이 문자열을 코드에 삽입 할 겁니다.
비대칭 암호화를 통해 암호화된 문자열을 넣어줍니다.
비대칭 암호화를 했을 경우 Decrypt Password 를 선택합니다
시크릿 키를 입력합니다. 암호화를 했을 때 넣어주었던 시크릿 키를 넣어줍니다.
Match/Decrypt 가 성공했을 때 복호화 된 문자열이 담깁니다. 시크릿 키가 올바르지 않으면 복호화되지 않습니다.
암호화 할 내용을 만들었다면 다음과 같이 설정 파일에 작성해줍니다.
spring:
datasource:
url: ENC(YWG87FUr+PNX6IdWon9E124+h0uKmbfLEwDggm6YvWo=)
username: ENC(i1f8YG+iTZfS7VpbiyDf6TXwYFc4Vjdv)
password: ENC(uI9wv96P4imrilc9EqQBPHwOk5bGmNoq)
어떤 값이 적혀 있는지 겉으로는 모르지만 jasypt 는 프로그램 구동 시 암호화 된 설정들을 복호화하여 프로그램 구동에 문제가 없게 합니다.
그리고 코드에서 이 값을 사용하고 싶다면 @Value 애노테이션으로 값을 불러와서 사용하면 됩니다.
public class RareService {
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String user;
@Value("${spring.datasource.password}")
private String password;
// 비즈니스 로직...
}
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(System.getenv("JASYPT_PASSWORD");
// ...
}
Jasypt 를 적용 후 CodeDeploy 로 서버에 자동 배포될 때 EC2 에서 자동 배포가 제대로 돌지 않는 이슈가 발생했다. 그리고 Windows 로컬 터미널로 프로젝트 jar 파일을 구동했을 때 구동되지 않는 이슈 도 발생했다. (맥에선 구동이 됨) 그래서 한참 트러블슈팅하다가 도저히 해결 할 수 없어서 결국 Jasypt를 버리고 시스템 환경 변수로 암호화를 하기로 했다.
당장 다른 암호화 기술을 사용하여 민감 정보를 암호화 할 수 없어서 차선책으로 시스템 환경 변수를 설정하여 사용했다. 이 방법의 사용법은 다음과 같다.
spring:
datasource:
url: ${DB_URL}
username: ${DB_USER}
password: ${DB_PWD}