Vault与Spring Boot的集成
Vault简介
Vault是一个专门提供密钥存储的解决方案,它有开源和收费两个版本。一般情况下,开源即可满足要求。
Vault支持多种secret engine,最简单的方式是kv,即把要被保护的密码以键值对的方式存储起来。
这个是官网的地址:developer.hashicorp.com/vault
与Spring Boot的集成
pom依赖
<dependency>
<groupId>org.springframework.vault</groupId>
<artifactId>spring-vault-core</artifactId>
</dependency>
配置类
Spring集成Vault,需要编写一个配置类,继承AbstractVaultConfiguration
,示例如下:
@Configuration
public class VaultConfiguration extends AbstractVaultConfiguration {
@Override
public VaultEndpoint vaultEndpoint() {
return VaultEndpoint.from(URI.create("http://localhost:8200"));
}
@Override
public ClientAuthentication clientAuthentication() {
return new TokenAuthentication("hvs.cLX6B2bsoTL5IBMHc95UW9P4");
}
}
这个示例(仅用于测试)中:
- Vault server跑在
http://localhost:8200
上 - 使用了Token的认证方式
使用secret数据
大致上,有两种使用secret的方式,一是直接调用VaultTemplate
的API,一是使用@VaultPropertySource
注解或者使用VaultPropertySource
的API。
使用VaultTemplate
API
// 注入VaultTemplate
@Autowired
VaultTemplate vaultTemplate;
@GetMapping("/creds")
public Map<String, Object> getData() {
// 使用VaultTemplate的API查询secret数据
VaultVersionedKeyValueOperations kv = vaultTemplate.opsForVersionedKeyValue("secret");
Versioned<Map<String, Object>> versioned = kv.get("creds");
Map<String, Object> data = versioned.getData();
return data;
}
- 这种方式下,因为是直接通过API获取secret,所以如果Vault里面的数据发生了变化,那么可以立即感知
- 问题是,每次调用都会访问Vault,对Vault有一定压力
使用VaultPropertySource
注解或API
@VaultPropertySource("secret/creds")
public class MyConfig {
}
@RestController
public class MyController {
// 注意:使用注入Environment的方式不一定能够获取到PropertySource中的属性,因为
// 有可能由于加载顺序的问题,导致Environment尚未初始化完成
// 最好能够让configuration类实现ApplicationContextAware,从而使用context.getEnviornment()来获取
private final Environment env;
public MyController(Environment env) {
this.env = env;
}
@GetMapping("/password")
public String getPassword() {
return env.getProperty("password")
}
}
- 这种方式下,在服务启动的时候,从Vault中加载了密码信息,之后就保持不变
- ==可以尝试使用@Refresh注解,利用RefreshScope来解决?==
Vault Repository的集成方案
Spring Vault提供了repository的集成方式来提供对secret的CRUD。Vault会采用kv引擎来存取secret数据。
以下是集成步骤。
pom依赖
<dependency>
<groupId>org.springframework.vault</groupId>
<artifactId>spring-vault-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-keyvalue</artifactId>
</dependency>
定义repository及实体
@Data
@NoArgsConstructor
@AllArgsConstructor
@Secret
public class Credentials {
@Id private String id;
private String password;
private String socialSecurityNumber;
Address address;
}
@Repository
public interface CredentialsRepository extends CrudRepository<Credentials, String> {
}
- 使用
@Secret
注解来标识这是一个secret实体对象 - 使用
@Id
注解来标识这是一个主键,所以生成的kv对象的路径为:secret/data/credentials/<id>
配置类
@Configuration
@EnableVaultRepositories(basePackageClasses = CredentialsRepository.class)
public class MyConfig {}
- 需要在配置类上加上
@EnableVaultRepositories
注解来启用自动配置类,并且指定repository所在的包
转载自:https://juejin.cn/post/7301908476837953563