Vault 是由 HashiCorp 开发的一款用于管理和保护敏感数据的工具。它可以帮助组织安全地存储、分发和使用各种类型的敏感信息,如 API 密钥、密码、证书等。
应用场景
-
API 密钥管理: -
将 API 密钥存储在 Vault 中,并根据需要分配给不同的服务或团队成员。这样可以确保密钥的安全性和可追溯性。
-
-
数据库凭证管理: -
Vault 可以生成动态数据库凭证,每个凭证都有特定的权限和有效期。当凭证不再需要时,可以自动撤销。
-
-
SSH 密钥管理: -
Vault 可以作为 SSH 密钥管理系统,为用户提供一次性或长期有效的 SSH 密钥。
-
-
TLS/SSL 证书管理: -
Vault 可以签发和管理 TLS/SSL 证书,简化证书生命周期管理过程。
-
-
云平台凭证管理: -
Vault 可以管理和轮换 AWS、Azure、Google Cloud Platform 等云平台的凭证。
-
-
CI/CD 环境中的秘密管理: -
在持续集成/持续交付管道中使用 Vault 来传递敏感信息,如 Docker 镜像仓库凭证、配置文件等。
-
-
微服务架构中的秘密管理: -
在微服务架构中,不同服务之间可能需要共享某些敏感信息。Vault 可以集中管理这些信息,并根据服务的需求提供相应的访问权限。
-
-
合规性和审计: -
Vault 提供强大的审计功能,帮助组织满足合规要求,如 GDPR、HIPAA 等。
-
启动Vault并配置Token
首先,确保你已经安装并启动了Vault服务器。你可以使用以下命令来初始化和启动Vault:
# 启动Vault开发服务器
vault server -dev
# 记录下生成的root token和unseal key
我的Vault根Token是 s.9ZvP3oJHqQcXzKw6FyGmEhLr
,并且Vault运行在默认的 http://localhost:8200
上。
将敏感信息存储到Vault
使用Vault CLI或API将敏感信息存储到Vault中。这里我们使用Vault CLI来创建一个密钥路径 secret/app-secrets
并添加一个键值对 {"password": "mySuperSecretPassword"}
。
# 设置Vault地址
export VAULT_ADDR=http://localhost:8200
# 设置Vault Token
export VAULT_TOKEN=s.9ZvP3oJHqQcXzKw6FyGmEhLr
# 写入敏感信息到Vault
vault kv put secret/app-secrets password=mySuperSecretPassword
代码实操
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-vault-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2022.0.1</spring-cloud.version>
</properties>
配置Vault (application.yml
)
server:
port:8080
spring:
cloud:
vault:
host:localhost
port:8200
scheme:http
token:s.9ZvP3oJHqQcXzKw6FyGmEhLr
generic:
enabled:true
backend:secret
default-context:app-secrets
创建Vault认证类 (VaultConfig.java
)
package com.example.vaultdemo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.vault.authentication.ClientAuthentication;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.core.VaultTemplate;
@Configuration
publicclass VaultConfig {
@Bean
public ClientAuthentication clientAuthentication() {
returnnew TokenAuthentication("s.9ZvP3oJHqQcXzKw6FyGmEhLr");
}
@Bean
public VaultTemplate vaultTemplate(ClientAuthentication clientAuthentication) {
VaultTemplate vaultTemplate = new VaultTemplate(VaultEndpoint.create("localhost", 8200), clientAuthentication);
return vaultTemplate;
}
}
编写服务类 (SecretService.java
)
package com.example.vaultdemo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.vault.core.VaultOperations;
@Service
publicclass SecretService {
privatefinal VaultOperations vaultOperations;
@Autowired
public SecretService(VaultOperations vaultOperations) {
this.vaultOperations = vaultOperations;
}
public String getSecretPassword() {
return vaultOperations.read("secret/data/app-secrets").getData().get("data").toString();
}
}
配置Spring Security (WebSecurityConfig.java
)
package com.example.vaultdemo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
publicclass WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/secrets/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.httpBasic();
}
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("password")
.roles("ADMIN")
.build();
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
returnnew InMemoryUserDetailsManager(admin, user);
}
}
编写控制器 (SecretController.java
)
package com.example.vaultdemo.controller;
import com.example.vaultdemo.service.SecretService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/secrets")
publicclass SecretController {
privatefinal SecretService secretService;
@Autowired
public SecretController(SecretService secretService) {
this.secretService = secretService;
}
@GetMapping("/password")
public ResponseEntity<String> getPassword() {
String password = secretService.getSecretPassword();
return ResponseEntity.ok(password);
}
}
主应用程序类 (VaultDemoApplication.java
)
package com.example.vaultdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class VaultDemoApplication {
public static void main(String[] args) {
SpringApplication.run(VaultDemoApplication.class, args);
}
}
测试用例 (SecretServiceTest.java
)
package com.example.vaultdemo;
import com.example.vaultdemo.service.SecretService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
importstatic org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
class SecretServiceTest {
@Autowired
private SecretService secretService;
@Test
void shouldReturnCorrectPassword() {
// 在Vault中的路径为secret/data/app-secrets,键值对为{"password": "mySuperSecretPassword"}
assertThat(secretService.getSecretPassword()).contains("mySuperSecretPassword");
}
}
启动Spring Boot应用程序
确保所有文件都已正确放置在相应的目录中,然后运行Spring Boot应用程序。
./mvnw spring-boot:run
测试API
使用Postman发送HTTP GET请求到 http://localhost:8080/secrets/password
,
使用HTTP Basic Authentication,用户名为 admin
,密码为 password
。
请求
-
URL: http://localhost:8080/secrets/password
-
Method: GET
-
Authorization: -
Type: Basic Auth -
Username: admin
-
Password: password
-
响应
{
"password": "mySuperSecretPassword"
}
扫码领红包微信赞赏
支付宝扫码领红包
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。侵权投诉:375170667@qq.com