Jasypt와 Github Secrets로 Github 개인 정보 유출 방지하기

HeavyJ·2023년 5월 10일
1

자바/스프링부트

목록 보기
10/17

프로젝트를 깃허브에 올릴 때 가장 신경써야할 부분은 바로 보안이라고 생각합니다.

실제로, 스터디원 중에 aws 정보가 노출돼서 요금 폭탄을 맞을뻔 했다는 이야기를 듣고(ㄷㄷ) 스프링 프로젝트의 보안을 어떻게 하면 강화할 수 있을까에 대해 고민을 많이 했습니다.

돈 아낀다고 프리티어 쓰는데 몇 십, 몇 백 만원 요금 맞으면 피눈물 날듯요 ㅠㅠ

그래서 저는 Github에서 개인정보를 보호하기 위해 Jasypt를 사용했습니다.

Jasypt 개념

Jasypt는 자바 라이브러리로 쉽게 암호화 기능을 사용할 수 있도록 제공해줍니다.
보통 스프링 프로젝트의 application.yml파일에서 개인 정보를 암호화(encryption)할 때 많이 사용됩니다.

Jasypt 적용하기

1. 의존성 추가

저는 Gradle을 사용하기 때문에 적용하는 방법은 build.gradle에 아래와 같이 의존성을 추가해줍니다.

implementation "com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.3"

(springboot에서 dependency 매니징을 해주지 않기 때문에 버전까지 명시를 해줘야 하는 것 같습니다)

2. Config 파일 만들기

@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입니다.

3. Jasypt를 통해 텍스트를 암호화하기

Jasypt를 사용해서 암호화하는 방법은 2가지가 있습니다.

  • Test 코드 작성하여 암호화된 데이터 출력받기
  • 사이트에 들어가서 암호화 / 복호화 진행하기

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에 암호화된 데이터가 출력됩니다.

오른쪽에서 같은 방식으로 복호화까지 가능합니다.

저는 직접 테스트코드를 작성해서 출력받는 것 보다 직접 사이트에서 입력해주는 것이 편했기 때문에 사이트를 이용했습니다.

4. yml 파일에 암호화된 데이터 입력하기

#DB
spring:
  datasource:
    url: jdbc:mysql://asdifjsaoifjaosjofij
    username: ENC(gjio34qj3oigjihiohjg=)
    password: ENC(jg3io4jiorejgiorjbrpj=0249i3j)

jasypt.encryptor.password=joonghyunPark

yml 파일에는 반드시 ENC() 안에 암호화된 텍스트를 입력해줘야 합니다.
그리고 jasypt.encryptor.passowrd에 key 값을 입력해줍니다.(이 값은 보안을 위해 나중에 다시 숨길겁니다)

5. Jasypt 키 값 숨기기

키 값을 yml에 입력한 채로 깃허브에 올리면 제가 했던 Jasypt 암호화 방식이 말짱 도루묵, 의미없는 도루마무가 됩니다.

왜냐하면, 해커가 그냥 key 값으로 복호화를 해버리면 제 정보가 다시 들통나기 때문입니다.

그렇기 때문에 저 joonghyunPark이라는 키 값을 숨겨야 합니다.

명령어에 key 값 입력할까??

EC2에서 프로젝트를 실행할 때 명령어에 -Djasypt.encryptor.password=joonghyunPark 를 붙이는 방법도 있지만 이 방법이 좀 번거롭다고 생각했기 때문에 저는 Github Secrets를 사용했습니다.

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 레포지터리에 개인 정보를 그냥 올려놓는 분들도 많이 봤는데 자기 개인 정보는 꼭 자기가 지켜야 합니다!

profile
There are no two words in the English language more harmful than “good job”.

5개의 댓글

comment-user-thumbnail
2023년 5월 14일

대칭키 비대칭키 암호화에 대해서도 알아보시면 좋을 거 같습니다

1개의 답글
comment-user-thumbnail
2023년 11월 27일

안녕하세요! 블로그 잘봤습니다! 감사합니다! 현재 선생님 블로그를 하나하나
따라하는 중인데, 혹시 이메일로 여쭤보고 싶은것이 있는데, 가능하실까요?

1개의 답글
comment-user-thumbnail
2024년 2월 4일

감사합니다. 스프링 프로젝트 구글 api키를 모르고 깃허브에 업로드했더니, 요금이 몇십만원 청구돼서 며칠동안 멘탈이 나갔는데.. 앞으로 이런걸로 대비해두어야 겠어요..

답글 달기