이전에 필요한 환경변수 파일들을 Github에 Config Repository를 하나 생성해 관리했다.
Spring Cloud Config Server는 실행 시 이 환경 설정파일들을 애플리케이션이 실행될 때 전파해주었다.
이런 환경설정 파일들을 Public Repository에서 관리하거나 Private Repository에서 관리하더라도 암/복호화를 통해 안전하게 관리해야한다.
일반적으로 암/복호화하는 방식은 크게 대칭키방식과 비대칭키 방식이 있다.
- 대칭키(Symmetric) : 암/복호화하는 키가 동일한 경우를 의미한다. 대표적으로 AES, SEED, ARIA와 같은 알고리즘이 있다.
- 비대칭키(Asymmetric) : 암/복호화 하는 키가 다른 경우를 의미한다. 모든 사람이 사용할 수 있는 공개키와 공개키를 이용해 암호화된 데이터를 복호화 할 수 있는 개인키로 구분된다. 대표적으로 RSA 알고리즘이 있다.
Java Key Store를 이용해 키를 관리
Java는 Java Cryptography Extension(JCE)을 이용해 암호 관련 기능을 제공한다. Java 11이상부터는 기본적으로 제공하고 있으며 그 밑 버전에서는 해당 라이브러리를 다운받아야 사용이 가능하다.
Java Key Store(JKS)는 JCE를 이용해 만든 키를 저장하고 관리하는 저장소이다.
Spring Cloud Config Server에서는 설정 파일을 암/복호화 하기 위해 JCE와 JKS를 이용해 사용할 수 있다.
Keytool을 이용해 key 생성
Spring Cloud Config Server에서 사용할 Key를 생성하자.
$ keytool -genkeypair -alias [별칭] -keyalg RSA \\
-dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \\
-keypass [비밀번호] -keystore [파일명].jks -storepass [비밀번호]
Java 11 이상 버전을 사용하는 경우 keypass의 패스워드와 storepass의 패스워드가 동일한지 확인하는 경고메세지가 출력된다. keypass와 storepass를 동일하게 설정하면 해결된다.
이렇게 생성된 키는 입력한 비밀번호를 이용해 암호키가 생성되며, 생성된 암호키를 Key Store 파일에 저장한다. 따라서 확장자가 .jks임을 알 수 있다.
생성된 키로 인증서 및 공개키 생성
생성된 JKS 파일을 이용해 공개키를 만들기 위한 인증서를 만든다.
$ keytool -export -alias [별칭] -keystore [위에서 만들어진 파일명].jks -rfc -file [인증서명].cer
마지막으로 인증서를 이용해 공개키를 만든다.
$ keytool -import -alias [별칭] -file [인증서 파일].cer -keystore [파일명].jks
application.yml 수정
Spring Cloud Config Server의 /encrypt, /decrypt 엔드포인트를 POST 방식으로 호출하면 암/복호화된 데이터를 확인할 수 있다.
암/복호화를 이용하기 위해 Spring Cloud Config Server의 application.yml 파일을 수정한다.
encrypt:
key-store:
location: file://[JKS 생성 경로]/[파일명].jks # 위에서 생성한 키 경로와 키
alias: [지정한 별칭] # 생성 시 지정한 별칭
password: [store-pass] # KeyStore에 접근하기 위한 패스워드 (-storepass)
이제 /encrypt와 /decrypt를 호출해보자.
/encrypt
/encrypt 엔드포인트를 호출할 땐 POST방식에 Text 타입의 암호화할 데이터를 담아 전송한다.
설정에 문제가 없다면 아래처럼 암호화된 데이터를 반환해준다.
/decrypt
/decrypt 엔드포인트 또한 POST 방식으로 Text에 암호화한 데이터를 담아 전송하면 복호화 된 데이터를 반환해준다.
Spring Cloud Config Repository에 암호화 데이터 넣고 확인하기
우리의 목적은 Repository에서 관리되는 설정 파일 내 민감 정보에 대해서 암호화를 통해 보안을 강화화고 환경 설정 파일을 불러오는 클라이언트에서 복호화를 통해 안전하게 로드하길 원한다.
/encrypt로 암호화환 데이터를 Config Repository에 업데이트한다.
Config Repository에 업데이트 할 때는 반드시 ‘{cipher}’라는 접두사가 붙어야 암호화 된 데이터라 인식하여 복호화를 진행한다.
암호화 데이터를 입력할 때 반드시 ‘’ 안에 넣어주자! 넣지 않고 평문으로 넣을 시 No Such Label 에러가 발생한다.
암호화 된 데이터는 Spring Cloud Config Server에서 먼저 복호화 한 후 복호화 된 데이터를 클라이언트로 보내주는 방식이 있고, 클라이언트에서 직접 복호화를 진행하는 경우가 있다.
전자는 모든 환경 설정에 대한 복호화를 Config Server에서 공통적으로 진행한다는 장점이 있지만, 클라이언트 서비스로 전달되는 시점에 다시 탈취될수도 있기에 후자가 더 안전하다 판단했다.
클라이언트 서비스에서 복호화를 진행하기 위해 Spring Cloud Config Server에 설정한 application.yml 파일 설정을 동일하게 추가해준다 .
아래 설정을 하면 이제 클라이언트 서비스에서도 암호화된 데이터 ({cipher} 데이터)를 복호화 할 수 있게 된다.
encrypt:
key-store:
location: file://[JKS 생성 경로]/[파일명].jks # 위에서 생성한 키 경로와 키
alias: [지정한 별칭] # 생성 시 지정한 별칭
password: [store-pass] # KeyStore에 접근하기 위한 패스워드 (-storepass)
클라이언트에서 암호화된 설정 데이터를 로드하고 복호화하기 위한 준비가 끝났다.
제대로 호출해오는지 확인하기 위해 간단한 테스트를 해보자.
간단한 Config 파일을 생성했다.
@Value부분에서 암호화 한 데이터를 읽어올 것이고 키 스토어 설정을 했기 때문에 cipher문자열보고 복호화를 진행할 것이다.
@RefreshScope // Spring Actuator
@Component
public class LocalConfig {
// {application-profiles}.yml 에 정의한 내용을 해당 변수에 넣어줌
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
@Override
public String toString() {
return "LocalConfig{" +
"username='" + username + '\\'' +
", password='" + password + '\\'' +
'}';
}
}
실제로 호출을 통해 테스트하기 위해 간단히 Controller를 작성했다.
localhost:9001/service/local로 호출하면 위의 config에서 작성한 설정 정보가 호출될 것이다.
@RestController
@RequestMapping(value = "/service")
public class LocalController {
// Configuration 주입
private final LocalConfig localConfig;
// 생성자 주입
public LocalController(LocalConfig localConfig) {
this.localConfig = localConfig;
}
// /service/local 엔드포인트 호출 시 "config-local.yml에 정의한 내용 불러옴"
@GetMapping("/local")
public String loadLocalConfig() {
return localConfig.toString();
}
}
암호화된 설정정보를 제대로 복호화해서 가져오는 것을 확인할 수 있다.
📄 References
[Spring] Spring Cloud Config-Asymmetric Key Encryption(비대칭키 암호화) : https://joomn11.tistory.com/101
Spring 공식 문서 : https://cloud.spring.io/spring-cloud-config/reference/html/#_encryption_and_decryption
'Backend > Spring Boot' 카테고리의 다른 글
RestTemplate (0) | 2022.07.01 |
---|---|
Converter를 이용해 URI에 Enum 타입 매핑하기 (0) | 2022.06.26 |
RestControllerAdvice, ExceptionHandler를 이용한 전역 예외 처리 (0) | 2022.05.27 |
Spring Cloud Gateway를 이용한 서비스 라우팅 및 JWT 토큰 검증 (2) | 2022.05.24 |
Custom Exception을 이용한 예외 처리 (0) | 2022.05.22 |