Vault에 있는 값을 Spring Boot로 가져와 보자!

Karim·2022년 5월 27일
5

vault 운영

목록 보기
4/4
post-thumbnail

1. Version

💬

  • IntelliJ : 2020.3.2.community
  • vault : v1.10.0
  • spring boot : 2.6.1

2. 시작 전 확인사항

💬 gradle 추가

	implementation 'org.springframework.boot:spring-boot-starter'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'

	implementation group: 'org.springframework.vault', name: 'spring-vault-core', version: '2.3.2'

	//lombok 관련
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'

	testCompileOnly 'org.projectlombok:lombok:1.18.22' // 테스트 의존성 추가
	testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' // 테스트 의존성 추가

3. application.yml 추가

💡 application.yml 필요 설정 추가

vault.props:
  schema: http
  host: 볼트 서버 Ip
  port: 볼트 서버 Port
  roleId: 볼트R oldId
  secretId: 볼트 secretId
  mainPath: kv
  subPath: karim

4. vault 설정 부분 구현

💡 vault 객체 구현

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("vault.props")
@Data
public class VaultProps {
    private String host;
    private int port;
    private String schema;
    private String roleId;
    private String secretId;
    private String mainPath;
    private String subPath;
}

💬 어노테이션 설명

  • @ConfigurationProperties
    .yml 파일에 있는 property를 자바 클래스에 값을 바인딩 사용할 수 있게 해주는 어노테이션
  • @Data
    @Getter, @Setter, @RequiredArgsConstructor, @ToString, @EqualsAndHashCode 어노테이션을 한꺼번에 설정해주는 어노테이션

5. 사용자 Credentials 구현

💡 vault에서 가져오는 사용자Id와 pw에 매핑 되는 Credentials class 구현

import lombok.Data;

@Data
public class VaultCredential {
    private String username;
    private String password;
}

💬 어노테이션 설명

  • @Data
    @Getter, @Setter, @RequiredArgsConstructor, @ToString, @EqualsAndHashCode 어노테이션을 한꺼번에 설정해주는 어노테이션

6. Vault 접속 및 데이터 부분 구현

💡

import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.vault.authentication.AppRoleAuthentication;
import org.springframework.vault.authentication.AppRoleAuthenticationOptions;
import org.springframework.vault.authentication.ClientAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.config.AbstractVaultConfiguration;
import org.springframework.vault.core.VaultTemplate;
import org.springframework.vault.core.VaultVersionedKeyValueTemplate;
import org.springframework.vault.support.Versioned;

@Configuration
@EnableConfigurationProperties(VaultProps.class)
@RequiredArgsConstructor
public class VaultConfig extends AbstractVaultConfiguration {

    final private VaultProps vaultProperties;

    @Override
    public VaultEndpoint vaultEndpoint() {
        VaultEndpoint vaultEndpoint = null;
        if (vaultProperties != null) {
            vaultEndpoint = VaultEndpoint.create(vaultProperties.getHost(), vaultProperties.getPort());
            vaultEndpoint.setScheme(vaultProperties.getSchema());
        }
        return vaultEndpoint;
    }

    @Override
    public ClientAuthentication clientAuthentication() {
        AppRoleAuthenticationOptions appRoleAuthenticationOptions = null;
        if (vaultProperties != null) {
            appRoleAuthenticationOptions = AppRoleAuthenticationOptions.builder()
                    .roleId(AppRoleAuthenticationOptions.RoleId.provided(vaultProperties.getRoleId()))
                    .secretId(AppRoleAuthenticationOptions.SecretId.provided(vaultProperties.getSecretId()))
                    .build();
        }
        return appRoleAuthenticationOptions != null ? new AppRoleAuthentication(appRoleAuthenticationOptions, restOperations()) : null;
    }


    @Bean
    @Primary
    public void readVaultCredentials(){
        VaultTemplate vaultTemplate = new VaultTemplate(vaultEndpoint(), clientAuthentication());
        VaultVersionedKeyValueTemplate vaultVersionedKeyValueTemplate;
        vaultVersionedKeyValueTemplate = new VaultVersionedKeyValueTemplate(vaultTemplate, vaultProperties.getMainPath());
        Versioned<VaultCredential> vaultResponse = vaultVersionedKeyValueTemplate.get("/"+ vaultProperties.getSubPath(), VaultCredential.class);
        System.out.println("###################################################################");
        System.out.println("###### vault get username : " + vaultResponse.getData().getUsername() );
        System.out.println("###### vault get password : " + vaultResponse.getData().getPassword() );
        System.out.println("###################################################################");

    }
}

✒️ 메소드 설명

  • VaultEndpoint (Override)
    • Vault 연결 좌표를 정의하는 값 개체
    • 호스트 이름, TCP 포트, 프로토콜 체계(HTTP 또는 HTTPS) 및 컨텍스트 경로 접두사를 정의
  • ClientAuthentication (Override)
    • VaultToken 및 RoleId/SecretId 인증된 Vault 액세스에 사용
    • 위 예제는 appRole 방식이기 때문에 AppRoleAuthentication 반환
  • readVaultCredentials
    • 실질적으로 데이터를 조작하는 메소드
      • VaultTemplate : 템플릿은 Vault에서 데이터를 읽고, 쓰고, 삭제하는 편리한 작업을 제공하고 도메인 개체와 Vault 데이터 간의 매핑을 제공
      • VaultVersionedKeyValueTemplate : KV v2 secrets 엔진에서 데이터를 가져올 때 사용하는 메소드

💬 어노테이션 설명

  • @Configuration / @Bean
    수동으로 스프링 컨테이너에 빈을 등록
  • @EnableConfigurationProperties
    VaultProps.class 빈 주입
  • @RequiredArgsConstructor
    생성자 자동 생성 및 final 변수를 의존관계를 자동으로 설정해 준다.
  • @Primary
    같은 우선순위로 있는 클래스가 여러 개가 있을 시 그 중 가장 우선순위로 주입 설정

7. 결과 로그

💻

Vault 해당 경로에 있는 사용자Id,Pw를 가져온 것을 확인할 수 있다.


📌 여담

  • 🔌

📚 참고

profile
나도 보기 위해 정리해 놓은 벨로그

2개의 댓글

comment-user-thumbnail
2023년 3월 17일

application.yml 에 적히는 vault 서버 정보들은 어떻게 관리하시나요?

1개의 답글