반응형
Spring 연동 예제
build.gradle
extra["springCloudVersion"] = "2022.0.0"
dependencies {
...
implementation("org.springframework.cloud:spring-cloud-starter-vault-config")
}
dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
}
}
application.yml
공통 설정
spring.cloud.vault:
uri: http://192.168.56.11:8200 # vault 서버 주소
token: hvs.EwyXMoRXoseiVXke0TdXiDYe # root_token
connection-timeout: 5000
read-timeout: 15000
option 1
- vault://{engine_name}/{application_name}, vault://{engine_name}/{application_name}/{profile} 경로의 kv 값을 로딩
- engine_name의 default 값은 secret
- application_name의 default 값은 application
- 아래처럼 설정 후 spring.profiles.active=local로 실행하면 가져오는 대상은 아래와 같음
- vault://secret/application
- vault://secret/application/local
- vault://secret/demo
- vault://secret/demo/local
spring.config.import: vault://
spring.application.name: demo
option 2
- 아래처럼 설정 후 spring.profiles.active=local로 실행하면 가져오는 대상은 아래와 같음
- vault://example/common
- vault://example/common/local
- vault://example/demo
- vault://example/demo/local
spring.config.import: vault://
spring.cloud.vault:
kv:
enabled: true
backend: example # engine_name
default-context: common
application-name: demo
# profiles: local, dev
# profile-separator: '/'
DemoController
@RestController
public class DemoController {
@Value("${password}")
private String password;
@GetMapping("/api/password")
public String getPassword() {
return password;
}
}
Spring 실행 후 확인
spring.profiles.active=local로 설정 & 실행 후 확인
Scheduler로 갱신하기 예제
설명
- @Scheduled와 ContextRefresher를 활용하여 서버가 실행된 상태에서 재실행 없이 vault의 설정값을 갱신하는 예제.
DemoController
@RefreshScope // vault 설정값을 사용하는 클래스에 어노테이션 추가
@RestController
public class DemoController {
@Value("${password}")
private String password;
@GetMapping("/api/password")
public String getPassword() {
return password;
}
}
VaultRefreshScheduler
@Slf4j
@RequiredArgsConstructor
@EnableScheduling
@Component
public class VaultRefreshScheduler {
// !!주의!! : ContextRefresher 객체를 주입받는 클래스에는 @RefreshScope를 붙이면 refresh() 실행시 hang이 걸림. 이유는 모름..
private final ContextRefresher contextRefresher;
@Scheduled(cron = "0/10 * * * * *") // 0초부터 10초마다 실행
public void refresh() {
log.info("refresh - start");
log.info("refresh - changed : {}", contextRefresher.refresh());
log.info("refresh - end");
}
}
Vault 설정값 변경 & refresh 이후 설정값 변경 확인
password를 local-123456 -> local-123456-v2로 변경
Redis Pub/Sub으로 갱신하기 예제
설명
- 스프링 서버가 실행될 때 Redis의 특정 topic을 구독하고, 해당 topic에 publish가 발생했을 때 서버의 설정값을 갱신하는 예제
gradle.build
dependencies {
...
implementation("org.springframework.boot:spring-boot-starter-data-redis")
}
application.yml
spring.redis.host: localhost
spring.redis.port: 6379
RedisConfig
@Configuration
public class RedisConfig {
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(
RedisConnectionFactory connectionFactory,
VaultRefreshListener vaultRefreshListener,
ChannelTopic vaultRefreshTopic
) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(vaultRefreshListener, vaultRefreshTopic);
return container;
}
@Bean
public ChannelTopic vaultRefreshTopic() {
return new ChannelTopic("VAULT_REFRESH_TOPIC");
}
}
VaultRefreshListener
@Slf4j
@RequiredArgsConstructor
@Component
public class VaultRefreshListener implements MessageListener {
// 주의 : ContextRefresher 객체를 주입받는 클래스에는 @RefreshScope를 붙이면 refresh() 실행시 hang이 걸림. 이유는 모름..
private final ContextRefresher contextRefresher;
@Override
public void onMessage(Message message, byte[] pattern) {
String topic = new String(message.getChannel());
String body = new String(message.getBody());
log.info("refresh - start - topic : {}, body : {}", topic, body);
log.info("refresh - changed : {}", contextRefresher.refresh());
log.info("refresh - end");
}
}
VaultRefreshController
@RequiredArgsConstructor
@RestController
public class VaultRefreshController {
private final StringRedisTemplate redisTemplate;
private final ChannelTopic vaultRefreshTopic;
@GetMapping("/api/vault/refresh")
public String refresh() {
redisTemplate.convertAndSend(vaultRefreshTopic.getTopic(), "refresh");
return "OK";
}
}
실행 후 확인
- 서버 실행시 VAULT_REFRESH_TOPIC을 구독
- Vault Web UI에서 설정값 변경
- /api/vault/refresh 호출시 VAULT_REFRESH_TOPIC에 발행
- VAULT_REFRESH_TOPIC 발행이 일어났으므로 onMessage()에서 Vault 설정값 갱신 처리 수행
- 갱신된 Vault 설정값을 활용
참고
- https://docs.spring.io/spring-cloud-vault/docs/current/reference/html/#quick-start
- https://docs.spring.io/spring-cloud-vault/docs/current/reference/html/#vault.config.backends.kv.versioned
- https://velog.io/@rainbowweb/Redis-%EC%97%B0%EC%8A%B5-2-pubsub-%EA%B5%AC%EC%84%B1
반응형
'Development > Vault' 카테고리의 다른 글
[Vault] Secret Key 추가 (0) | 2023.01.14 |
---|---|
[Vault] Vault 설치 (0) | 2023.01.14 |