반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Starter
- vaultTemplate
- restTemple
- LogInterceptor
- ClientHttpRequestInterceptor
- JsonType
- JsonStringType
- Thread Safety
- @AutoConfiguration
- findFirst
- gradle
- AOP
- RestTemplate
- AOP this
- ResponseBodyAdvice
- Save Action
- findAny
- 포맷터
- AOP 매개변수
- Stream
- Spring Boot
- java
- AccessLevel
- 쓰레드 안전
- 개방/폐쇄 원칙
- jpa
- spring
- auto configuration
- fotmatter
- AOP target
Archives
- Today
- Total
맨땅에 헤딩하는 개바른자
[런타임X] 리얼타임 Vault 값 사용하기 본문
반응형
서론
본 포스팅에 앞서 Vault가 이미 구성 된 프로젝트에서 리얼타임으로 Vault의 값을 사용하기위한 가이드 내용으로 Vault구성이 궁금하시다면 다른 포스팅글을 참고 부탁드립니다.
Vault 소개와 기본 개념 이해하기
Vault는 현대적인 시스템 및 애플리케이션의 비밀 관리를 위한 도구로 널리 사용되고 있습니다. 그러나 Vault의 설정은 복잡하고 다양한 요소가 있어 초보자에게는 약간의 어려움을 줄 수 있습니다. 이 포스팅은 Java SpringBoot 기반의 프로젝트에서 Vault 설정을 실시간으로 구성하는 방법에 대한 포괄적인 가이드를 제공하여 사용자가 보다 간편하게 Vault를 사용할 수 있도록 도와줍니다.
- Vault의 기본 개념 및 원리 소개
- 시크릿(Secrets): Vault는 시크릿(암호, 키, 패스워드 등)의 안전한 저장소로 작동합니다. 이러한 시크릿은 보안 관련 정보로 사용되며, Vault를 통해 안전하게 액세스 및 관리됩니다.
- 액세스 제어(Access Control): Vault는 각 시크릿에 대한 액세스 제어를 제공합니다. 엄격한 액세스 규칙을 설정하여 허가되지 않은 액세스로부터 시크릿을 보호합니다. 이를 통해 보안을 강화하고 시크릿에 대한 액세스 권한을 관리할 수 있습니다.
- 시크릿 엔진(Secret Engine): Vault는 시크릿 엔진을 사용하여 시크릿을 생성, 저장 및 관리합니다. 시크릿 엔진은 다양한 유형의 시크릿(예: 데이터베이스 암호, 클라이언트 API 키 등)을 지원하며, 암호화 및 복호화 작업을 수행합니다.
- 인증(Authentication): Vault는 클라이언트의 신원을 확인하기 위해 다양한 인증 방법을 지원합니다. 사용자 이름과 비밀번호, 액세스 토큰, 클라이언트 인증서 등을 사용하여 클라이언트의 인증을 처리할 수 있습니다.
- 암호화 및 복호화(Encryption and Decryption): Vault는 저장된 시크릿을 안전하게 암호화하여 저장합니다. 클라이언트가 시크릿을 요청하면 Vault는 암호화를 해제하여 시크릿을 제공합니다. 이를 통해 보안성을 유지하면서도 필요에 따라 시크릿을 사용할 수 있습니다.
- VaultTemplate 소개
- VaultTemplate는 RestTemplate를 사용하여 Vault 서버에 인증/인가를 걸친 후 데이터를 조회할 수 있는 기능을 제공합니다.
- API기능을 통해 Vault의 Key/Vaule 데이터를 응답받을 수 있습니다.
학습예제
https://github.com/ymwoo88/vault.git
학습목표
- 연동 된 vault정보를 갱신된 최신데이터를 실시간 사용하기
- 연동방식
(미선택) AbstractVaultConfiguration 상속한 설정파일을 통해 이벤트리스터를 통한 실시간 동기화 된 데이터 사용
특정 springboot 버전에서 방식이 대거 변경 되어 버전에 따라 방식이 다양한 단점이 존재
- (선택) AbstractVaultConfiguration 상속한 설정파일을 통해 VaultTemplate를 통한 실시간 통신으로 최신 데이터 사용
- VaultTemplate에 필요한 property만주입하면되어 여러 환경에서 쉽게 구성할 수 있는 장점이 존재
구성하기 앞서 Vault사용 환경
- vault UI 셋팅
- 인증
- 프로세스에서는 ROLE_ID, SECRET_ID를 사용한 AppRole인증을 사용
- Vault의 경우 API기능이 제공되며 API 기능에 다라 응답데이터를 받을 수 있습니다.
- 로그인 curl 테스트
// [REQUEST]
curl --location --request POST '<https://test.ymwoo.com:8200/v1/auth/approle/login>' \\
--header 'Content-Type: application/json' \\
--data-raw '{
"role_id" : "some..",
"secret_id" : "some.."
}'
// [RESPONSE]
{
"request_id": "123123-32da-123-86b7-123123123",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": null,
"wrap_info": null,
"warnings": null,
"auth": {
"client_token": "s.asdasdasdasdasd",
"accessor": "zzz",
"policies": [
"app-fnd",
"default"
],
"token_policies": [
"app-fnd",
"default"
],
"metadata": {
"role_name": "appfnd"
},
"lease_duration": 2764800,
"renewable": true,
"entity_id": "123123123-c4bf-1233-89d7-e10af9ce58df",
"token_type": "service",
"orphan": true
}
}
- 데이터 호출 curl 테스트
- 추가 param으로 version이란게 존재하는데 이것은 vault설정이 반영 될 때 마다 version이 자동으로 업데이트가 됩니다.
- 예를들어 현재 vault 설정 버전이 version=5라고하면
- {url}?version=3 으로 param을 추가하게되면 이전이력의 version=3의 데이터가 호출 됩니다.
- 저는 해당 param을 사용하지않고 호출 시 항상 최신version의 vault 값을 가져오게 하였습니다.
// [REQUEST]
curl --location --request GET '<https://test.ymwoo.com:8200/v1/app-kv/data/ymwoo/api/vault>' \\
--header 'X-Vault-Token: s.asdasdasdasdasd' // 헤더에 로그인에서 응답받았던 client_token사용
// [RESPONSE]
{
"request_id": "123123-c3f4-0b86-70ea-123123123",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": {
"data": {
"fnd.database": "zzzzzzzzz",
"fnd_database": "바뀌었당",
"password": "pass123",
"username": "aasdfsdfasdfasdfasdf#123"
},
"metadata": {
"created_time": "2023-05-10T16:45:13.471923859Z",
"custom_metadata": null,
"deletion_time": "",
"destroyed": false,
"version": 10
}
},
"wrap_info": null,
"warnings": null,
"auth": null
}
코드 구성하기
- vault설정 시 추가되었던 dependency가 추가되어있어야 한다.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-vault-config</artifactId>
</dependency>
- application.yml 파일에 Vault 정보 기입
spring:
cloud:
vault:
app-role:
app-role-path: approle
role: appfnd
role-id: ${VAULT_ROLE_ID}
secret-id: ${VAULT_SECRET_ID}
uri: https://{url}:8200
- VaultTemplate를 사용하기위한 VaultConfiguration 등록
- AbstractVaultConfiguration 상속받아 vaultEndpoint와 clientAuthentication을 작성합니다.
- 위 2메소드를 작성하기위해 VaultProperties를 주입받아서 사용합니다.
- 해당 데이터는 application.yml에 작성한 데이터를 읽어오게 됩니다.
@Configuration
public class VaultConfiguration extends AbstractVaultConfiguration {
private final VaultProperties vaultProperties;
public VaultConfiguration(VaultProperties vaultProperties) {
this.vaultProperties = vaultProperties;
}
@Override
public VaultEndpoint vaultEndpoint() {
try {
return VaultEndpoint.from(new URI(Objects.requireNonNull(vaultProperties.getUri())));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
@Override
public ClientAuthentication clientAuthentication() {
VaultProperties.AppRoleProperties appRole = vaultProperties.getAppRole();
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
.appRole(appRole.getRole())
.roleId(AppRoleAuthenticationOptions.RoleId.provided(Objects.requireNonNull(appRole.getRoleId())))
.secretId(AppRoleAuthenticationOptions.SecretId.provided(Objects.requireNonNull(appRole.getSecretId())))
.build();
return new AppRoleAuthentication(options, restOperations());
}
}
- VaultTemplate를 주입받아 데이터 응답받기
- 응답 Dto는 cUrl로 응답받은 샘플을 통해서 작성하였습니다.
- 쩜(.)이나 _언더바로 구분된 key명은 @JsonAlias로 설정하여 주입받았습니다.
- 꼭 사용에 필요한 데이터만 변수로 선언하여 사용합니다.
- password는 제외
@Slf4j
@RestController
@RequiredArgsConstructor
public class VaultController {
private final VaultTemplate vaultTemplate;
@GetMapping("webjars/test")
public VaultDTO test() {
VaultDTO result = null;
try {
VaultResponseSupport<VaultDTO> response = vaultTemplate.read("app-kv/data/fnd/api/vault", VaultDTO.class);
result = response.getData();
log.info("Retrieved data {} from Vault", result);
} catch (Exception e) {
log.error("error = {}", e.getMessage());
}
return result;
}
@Getter
@Setter
@ToString
public static class VaultDTO {
private Data data;
}
@Getter
@Setter
@ToString
public static class Data {
private String username;
@JsonAlias("fnd.database")
private String fndDatabase;
}
}
- 결과
[
{
"data": {
"username": "aasdfsdfasdfasdfasdf#123",
"fndDatabase": "zzzzzzzzz"
}
}
]
맺음말
이 포스팅을 통해 실시간 Vault 값을 참조하여 사용할 수 있도록 하였습니다. 보안이 중요한 기능이다보니 너무 남용하면 오히려 보안에 취약해지고 Vault를 도입한 취지가 무용지물되는 상황이 올 수 있습니다.
저 같은 경우는 applicaiotn.yml에 설정 된 항목이 보안상 민감하진 않지만 변경이 자주 발생되다보니 서비스 배포를 통해서 적용하는 케이스를 줄일 수 있는 방법이 없을까 생각하다가 고안해낸 방안입니다.
글을 보시는 분들도 업무에 유용하게 사용하셨으면 좋겠습니다.
감사합니다.
반응형
'개발 TIP' 카테고리의 다른 글
IntelliJ Save Actions, Formatter 적용 가이드 (1) | 2024.01.25 |
---|---|
JPA사용 시 Json 타입지정에 따른 영향도 (0) | 2023.11.10 |
Lombok > 생성자 AccessLevel.PROTECTED 를 알고 사용하자 (0) | 2023.01.19 |
CRUD 공통로직 만들기 (0) | 2022.05.10 |
Request DTO Validate Aspect 적용기 (0) | 2022.05.10 |