본문 바로가기
🔬아키텍처/- Spring Cloud for MSA

Spring Cloud Config 에서 대칭키를 이용한 application.yml 의 민감 정보 암호화 하기

by Wonit 2021. 4. 27.

해당 글은 Spring Cloud Config의 name, profiles 그리고 Github 를 연동해서 설정 파일 관리하기에 의존하는 글입니다. 실습 환경을 따라하시려면 이전 글에 나온 실습을 따라하시길 권고드립니다.

목차

  • 기존 Config Server의 문제점
    • 암호화를 하지 않은 정보의 탈취 가능성
  • 암호화 종류
    • 대칭키
    • 비대칭키
  • Spring Cloud Config 의 encrypt, decrypt
    • encrypt
    • decrypt
  • 실습하기
    • 대칭키 이용하기

기존 Config Server의 문제점

지난 시간 우리는 github를 이용해서 원격 저장소에 설정 파일들을 저장해놓고 Config 서버에서 가져다가 다른 마이크로서비스로 뿌려주는 과정을 알아보고 이를 구현하였었다.

 

우리의 원격 레포지토리로 다시 들어가보자.

 

 

그럼 이렇게 파일 내부에 있는 민감한 정보가 바로 노출된다.

 

물론 해당 레포지토리는 public repository라서 그렇다! 라고 할 수 있겠지만 그럼 private 으로 repository 를 변경한다고 해서 보안 위협이 사라지는걸까?

 

이렇게 단지 숨기는 방식의 보안은 전혀 안전하지 않다.

보안 처리를 했다는 그 생각 때문에 사람들은 안심을 할 수 있는데, 이는 오히려 이런 숨기는 보안을 하지 않는 것 보다 못하다.

 

그럼 이 문제는 어떻게 해결해야 할까?

 

바로 yml에 들어갈 민감 정보를 암호화 한다면 해결될 것 같다.

암호화 종류

암호화 종류에는 크게 3가지가 존재한다.

  1. 대칭키 암호
  2. 비대칭키 암호
  3. 단방향 암호

여기서 단방향 암호는 비밀번호를 저장할 때 해싱을 하여 암호화를 하는 것으로 단지 평문을 해독하지 못하도록하는 것이라 복호화가 사실상 불가능하다는 점으로 일단 우리 논점에서 빠지게 되고 대칭키와 비대칭키에 대해서만 이야기를 해보자.

 

대칭키 암호

대칭키 암호는 암호화 키와 복호화 키가 같은 점으로 간편하다.


게다가 널리 쓰이는 AES는 128 ~ 256 비트의 키를 적용할 수 있어서 보안성이 뛰어남과 동시에 공개된 알고리즘이라 누구나 사용할 수 있지만 가장 치명적인 단점이 존재한다.

 

바로 키를 어떻게 배송할 것인지에 대한 논의이다.

 

아무리 훌륭한 방식으로 암호화가 되었다고 하더라도 암호화와 복호화의 키가 동일하므로 복호화하는 쪽에 키를 전달해야 하는데, 이 과정에서 키가 누출될 가능성이 있다.

 

그럼 결국 암호화를 하지 않는 것과 같으므로 보안성이 매우 뛰어나다고는 할 수 없다.

 

정리

  • 암호화 키와 복호화키가 같다
  • 키 배송에 문제가 존재한다.
  • AES, DES, ARIA

비대칭키 암호

비대칭키 암호는 암호화 키와 복호화 키가 다른 방식이다.

 

비대칭키는 모두에게 공개된 공개키와 개인만 소지하는 개인키로 구성되어 있는데, 암호화를 수행할 때 공개키나 비밀키 중 하나의 키로 암호화를 수행하고 복호화는 반드시 그의 반대 키를 이용해야 한다.

 

그럼 앞서 말한 대칭키의 문제점인 키배송 문제를 해결할 수 있게 되지만 상대적으로 느린 단점도 존재한다.

 

그래서 몇몇의 솔루션에서는 비대칭 암호를 이용해서 대칭 키를 배송하고 실제 암호문은 대칭키 암호를 사용하는 식으로 운영하기도 한다.

 

우리 실습은 비대칭키를 이용하지 않고 대칭키만 이용하는 것으로 보여줄 것이다. 비대칭키를 이용하는 방법도 대칭키를 이용하는 방법과는 크게 벗어나지 않는다.

 

정리

  • 암호화 키와 복화화키가 다른 공개키 방식이다.
  • 암복호에 시간이 소요된다.
  • RSA, DSS, Rabin

Spring Cloud Config 의 encrypt, decrypt

Spring Cloud Config 에는 여러 특징들이 존재하는데, 그 중에서 encrypt와 decrypt 에 대해서 알아보자.

 

 

Spring Cloud Config 에서는 설정 파일 원본{cipher} 이라는 문자열이 존재한다면 해당 문자열은 암호화 된 것으로 판단하고 각기 다른 서버에 설정 정보를 내릴 때, 해당 암호문을 복호화하여 내려준다.

 

즉, git 저장소에 다음과 같이 파일이 저장되어 있다면

 

spring:
  datasource:
    username: test
    password: "{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ"

 

spring cloud config 가 이 암호문을 해독하기 시작하는데, 만약 키가 존재하고 해당 암호문이 복호화가 가능하다면 아래와 같이 정상적인 문자열로 반환해서 응답해준다.

 

spring:
  datasource:
    username: test
    password: test1234

 

하지만 해당 암호문이 키가 일치하지 않거나 하는 이유로 복호화가 불가능하면 n/a 라는 문자열을 반환시켜준다.

 

/encrypt 와 /decrypt 엔드포인트

우리는 직접 해당 암호화와 복호화를 config 서버를 통해서 수행할 수 있는데, 기본적으로 제공되는 url 을 이용할 수 있다.

  • 암호화 : http://config-server.com/encrypt : POST
  • 복호화 : http://config-server.com/decrypt : POST

하지만 이 엔드포인트는 그냥 사용할 수 없다.

 

적절한 key store가 존재해야 하는데, 만약 key store이 존재하지 않다면 다음과 같은 에러를 만날 것이다.

 

실습하기

그럼 우리는 Config 서버에 존재하는 설정 파일의 데이터를 어떻게 각각 암호할까?

 

우선 우리는 지난 시간동안 user-service 에게 2개의 설정 정보를 넘겼다.


여기서 조금 변경해서 다음과 같은 정보를 넘긴다고 해보자.

 

# application.yml
default:
  owner: config-service's git folder
  content: :) 안녕하세요 각각의 마이크로서비스에서 사용될 데이터입니다.

# user-service.yml
jwt:
  token:
    key: my_token_secret_key

# user-service-test.yml
spring:
  datasource:
    driver: com.mysql.jdbc.Driver
    url: http://db.com
    username: test
    password: test

앞서 이야기했듯, 해당 실습은 지난 시간 Spring Cloud Config의 name, profiles 그리고 Github 를 연동해서 설정 파일 관리하기에 의존하고 있습니다. 만약 실습을 따라하시길 원하신다면 지난 시간의 글을 참고해주세요

 

user-service 에서는 http://config-servcer.com/user-service/test 를 호출하여 yml 데이터를 받아올 것인데, 어떤 데이터가 넘어오는지 확인해보자.

 

 

여기서 민감 정보라고 한다면 뭐 다양한 것들이 민감하겠지만 그 중에서 토큰 값만 암호화를 해보도록 하자

 

  • user-service.ymljwt.token.key

대칭키로 설정정보 암호화 하기

대칭키로 위의 정보들을 암호화 해보자.

 

순서

  1. bootstrap.yml을 이용해 key store 추가하기
  2. bootstrap 의존성 추가하기
  3. bootstrap.yml에 키 저장하기
  4. /encrypt, /decrypt 엔드포인트 사용해서 암호화하기
  5. yml 파일에 암호화된 문자열을 넣고 응답으로 복호화된 문자열 받기

bootstrap.yml을 이용해 key store 추가하기

우선 대칭키로 암호화를 수행하여 /encrypt, /decrypt 를 이용한다면 앞서 본것처럼 key store 이 존재해야 한다.

 

먼저 bootstrap.yml 을 application.yml과 같은 depth 에 생성해주자.


우리는 bootstrap.yml에 우리의 대칭 키를 넣어줄 것이다.

 

의존성 추가하기

지난번 언급했지만 bootstrap.yml은 application.yml 보다 먼저 로드되기 전에 어떠한 설정 정보를 주입하기 위해서 사용된다.


하지만 Spring Cloud 에서는 bootstrap.yml 의존성이 기본적으로 들어있지 않기 때문에 build.gradle 에 다음 정보를 추가해주자.

 

implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'

bootstrap.yml에 키 저장하기

그리고 bootstrap.yml 에 다음과 같이 키를 저장해주자.

 

encrypt:
  key: my_symmetric_key

 

IDE 에서 해당 설정을 한다면 symmetric (대칭키)를 이용한다고 알려준다.

 

/encrypt, /decrypt 엔드포인트 사용하기

  • 암호화 : http://config-server.com/encrypt POST
  • 복호화 : http://config-server.com/decrypt POST

를 이용해서 body 에 암호화를 할 데이터를 넣고 요청을 보내면 다음과 같이 암호화된 문자열을 반환해주는데, 우리의 user-service.yml 에 있는 토큰 값을 암호화 해보자.

 

그럼 다음과 같이 암호화된 데이터가 나오게 된다.

 

우리는 Config 서버에서 해당 문자열을 읽을 때 복화를 할 것이라고 생각하고 사용자, 즉 Config 정보를 받는 마이크로서비스에게 전달될 때는 복호화 된 데이터를 받는다고 예상한다.

 

yml 파일에 암호화된 문자열을 넣고 Config 서버의 응답으로 복호화된 문자열 받기

이제 우리의 Config 서버가 복호화된 문자열을 잘 사용하는지 알아보기 위해서 실제 요청을 보내보자.

 

yml 파일에는 {cipher} 라는 접두사를 포함시켜 해당 문자열이 암호화되었다는 것을 알려줘야 한다.

 

jwt:
  token:
    key: "{cipher}8fe09399c96cdc1bee0cc3dafea404335a5bdd879e4cd85547fd1e7fbe774e11b3adc2c20634d16501be77987bbc210f"

 

이렇게 저장하고 원격 저장소로 push 하자.

 

잘 저장된 것을 볼 수 있다.

 

이제 config 서버를 재기동 시키고 user-service 설정 정보를 받는 요청을 보내보자.

 

 

그럼 위와 같이 저장소에는 암호문으로 저장되었지만 실제 config 서버의 설정 파일 응답은 복호화된 값으로 반환하는 것을 볼 수 있다.

 

댓글0