프로젝트를 깃허브에 올릴 때 가장 신경써야할 부분은 바로 보안이라고 생각합니다.
실제로, 스터디원 중에 aws 정보가 노출돼서 요금 폭탄을 맞을뻔 했다는 이야기를 듣고(ㄷㄷ) 스프링 프로젝트의 보안을 어떻게 하면 강화할 수 있을까에 대해 고민을 많이 했습니다.
돈 아낀다고 프리티어 쓰는데 몇 십, 몇 백 만원 요금 맞으면 피눈물 날듯요 ㅠㅠ
그래서 저는 Github에서 개인정보를 보호하기 위해 Jasypt를 사용했습니다.
Jasypt는 자바 라이브러리로 쉽게 암호화 기능을 사용할 수 있도록 제공해줍니다.
보통 스프링 프로젝트의 application.yml
파일에서 개인 정보를 암호화(encryption)할 때 많이 사용됩니다.
저는 Gradle을 사용하기 때문에 적용하는 방법은 build.gradle
에 아래와 같이 의존성을 추가해줍니다.
implementation "com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.3"
(springboot에서 dependency 매니징을 해주지 않기 때문에 버전까지 명시를 해줘야 하는 것 같습니다)
@Configuration
public class JasyptConfig {
@Value("${jasypt.encryptor.password}")
private String encryptKey;
/**
* String encryptor string encryptor.
*
* @return the string encryptor
*/
@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor(){
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(encryptKey);
config.setPoolSize("1");
config.setAlgorithm("PBEWithMD5AndDES");
config.setStringOutputType("base64");
config.setKeyObtentionIterations("1000");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
encryptor.setConfig(config);
return encryptor;
}
}
JasyptConfig.class
파일을 만든 뒤 @Configuration
으로 빈을 등록해줍니다.
들어간 내용 중 set 메소드를 살펴보면 알고리즘으로 PBEWithMD5AndDES 알고리즘을 확인할 수 있습니다.
PBEWithMD5AndDES 암호화 알고리즘
PBE는 Password Based Encryption으로 암호 기반 암호화 알고리즘입니다. PBE는 패스워드를 기반으로 해서 만든 키로 암호화를 수행하는 방법입니다. 여기서 MD5, DES 알고리즘을 사용해서 키를 생성하는 것이 PBEWithMD5AndDES입니다.
Jasypt를 사용해서 암호화하는 방법은 2가지가 있습니다.
Test Code로 작성하는 방법은 다음과 같습니다.
public class JasyptTest extends JasyptConfig{
@Test
public void jasypt_encyrpt_and_decrypt_test(){
String text = "암호화 하고 싶은 내용"
StandardPBEStringEncryptor jasypt = new StandardPBEStringEncryptor();
jasypt.setPassword("password");
String encryptedText = jasypt.encrypt(plainText);
String decryptedText = jasypt.decrypt(encryptedText);
System.out.println(encryptedText);
assertThat(plainText).isEqualTo(decryptedText);
}
}
테스트를 실행 후 출력된 암호화 데이터를 yml
파일에 입력해주면 됩니다.
사이트에서 진행하는 방법
Jasypt 암호화/복호화 사이트
plain text에 암호화하고 싶은 텍스트(joonghyun)을 입력, Two Way Encryption을 선택해주고, 밑에 Secret Key(joonghyunPark)를 입력해주면 됩니다.
그러면 Encrypted String에 암호화된 데이터가 출력됩니다.
오른쪽에서 같은 방식으로 복호화까지 가능합니다.
저는 직접 테스트코드를 작성해서 출력받는 것 보다 직접 사이트에서 입력해주는 것이 편했기 때문에 사이트를 이용했습니다.
#DB
spring:
datasource:
url: jdbc:mysql://asdifjsaoifjaosjofij
username: ENC(gjio34qj3oigjihiohjg=)
password: ENC(jg3io4jiorejgiorjbrpj=0249i3j)
jasypt.encryptor.password=joonghyunPark
yml 파일에는 반드시 ENC() 안에 암호화된 텍스트를 입력해줘야 합니다.
그리고 jasypt.encryptor.passowrd에 key 값을 입력해줍니다.(이 값은 보안을 위해 나중에 다시 숨길겁니다)
키 값을 yml에 입력한 채로 깃허브에 올리면 제가 했던 Jasypt 암호화 방식이 말짱 도루묵, 의미없는 도루마무가 됩니다.
왜냐하면, 해커가 그냥 key 값으로 복호화를 해버리면 제 정보가 다시 들통나기 때문입니다.
그렇기 때문에 저 joonghyunPark이라는 키 값을 숨겨야 합니다.
EC2에서 프로젝트를 실행할 때 명령어에 -Djasypt.encryptor.password=joonghyunPark
를 붙이는 방법도 있지만 이 방법이 좀 번거롭다고 생각했기 때문에 저는 Github Secrets
를 사용했습니다.
Github Secrets
는 Github Actions로 배포를 할 때 사용할 수 있는 것으로 환경 변수를 암호화 시키는 역할을 합니다.
해당 깃허브 레포지토리의 설정으로 들어가서 Security -> Secrets and variables -> Actions로 들어갑니다.
New repository secret을 클릭하여 원하는 제목을 작성하고 안에 키 값을 넣어줍니다.
(참고로 제 레포지터리의 실제 키 값은 joonghyunPark이 아닙니다.. 그냥 참고용 예시입니다!!, joonghyunPark로 복호화 시도해도 못 뚫어요 ㅠㅠ)
자, 그러면 Github Secrets
로 암호화를 했는데 이제 어떻게 프로젝트에 적용해야 할까요... ?
방법은 간단합니다.
빌드하기 전에 application-secrets.properties
파일을 workflow로 만들고 해당 APPLICATION_SECRET값을 넣어주면 됩니다.
즉, 이 방법을 gradle.yml
파일에서 보겠습니다.
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
# 사용하는 자바 버전 17
java-version: '17'
distribution: 'temurin'
- run: touch ./src/main/resources/application-secret.properties
- run: echo "${{ secrets.APPLICATION_SECRET }}" > ./src/main/resources/application-secret.properties
- run: cat ./src/main/resources/application-secret.properties
# gradlew에 권한 부여
- name: Grant execute permission for gradlew
run: chmod +x gradlew
# gradlew 빌드
- name: Build with Gradle
run: ./gradlew clean build --exclude-task test
touch
명령어로 application-secret.properties
파일을 만들고
echo
명령어로 APPLICATION_SECRET 내용을 그대로 입력해줍니다.
(gradle.yml
에서 ${{ secrets.여기넣기 }} 이 형식으로 작성해야 Github Secrets 값이 들어갑니다.)
cat
명령어로 잘 들어갔는지 확인합니다. (어차피 *** 이렇게 출력이 되기 때문에 보안 걱정은 안 해도 됩니다)
이 방식을 사용하려면 기존의 application.yml
에서
spring:
profiles:
include: secret
를 입력해줘야겠죠?
이렇게 깃허브에서 개인 정보를 보호를 해봤습니다. 다른 Public 레포지터리에 개인 정보를 그냥 올려놓는 분들도 많이 봤는데 자기 개인 정보는 꼭 자기가 지켜야 합니다!
대칭키 비대칭키 암호화에 대해서도 알아보시면 좋을 거 같습니다