领先一步
VMware 提供培训和认证,助您加速进步。
了解更多Spring Vault 2.1 已经提上日程。我想通过这篇博文深入探讨即将发布的版本中的更改和功能。
团队一直在努力开发许多新功能
扩展基于基础设施的身份验证以支持 Google Cloud IAM 和 Azure Managed Service Identity
集成 Vault 的版本化键值后端
包装 API 支持
Java 11 兼容性
Spring Vault 支持 HashiCorp Vault 版本 0.5 到 0.11。您可以在 GitHub 上找到 Spring Vault 和 Spring Cloud Vault 的 示例仓库。现在,让我们深入了解 Spring Vault 2.1 的新功能!
随着 0.8.1 版本的发布,Vault 引入了对 Google Cloud 的认证支持。GCP 认证使用 GCP 的 IAM 服务,通过以下两种认证流程之一进行:
使用服务账号凭据进行 IAM 登录,以生成签名令牌
使用 GCP 的元数据服务进行 GCE 登录,以检索签名令牌
Spring Vault 支持这两种方法。虽然使用 IAM 认证需要设置凭据(通过环境变量或使用凭据文件),但 GCE 认证将平台作为身份提供者,因此 GCE 认证在初始设置方面的要求更少。
IAM 认证使用 Google 的 IAM 服务,通过 Google 凭据的签名来生成签名令牌。签名令牌会被传递给 Vault 进行验证。此认证方法需要通过 GOOGLE_APPLICATION_CREDENTIALS 环境变量提供凭据,或者通过 GcpIamAuthenticationOptions 进行配置。GcpIamAuthentication 使用 Google 的服务 API SDK (google-api-services-iam) 与 IAM 进行交互。客户端配置可能如下面的代码示例所示:
@Configuration
class VaultConfiguration extends AbstractVaultConfiguration {
@Override
public ClientAuthentication clientAuthentication() {
try {
GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
.role("my-role")
.credential(GoogleCredential.getApplicationDefault())
.build();
return new GcpIamAuthentication(options, restOperations());
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
// …
}
默认情况下,IAM 认证方法从凭据中派生项目 ID 和服务账号 ID。您也可以配置特定的值,以便代表特定的服务账号进行认证。
有关更多信息,请参阅 参考文档。
GCE(Google Compute Engine)认证流程适用于虚拟机实例。它使用元数据服务(计算元数据)来获取签名令牌。签名身份被传递给 Vault 以验证虚拟机实例。客户端配置可能如下面的代码示例所示:
@Configuration
class VaultConfiguration extends AbstractVaultConfiguration {
@Override
public ClientAuthentication clientAuthentication() {
GcpComputeAuthenticationOptions options = GcpComputeAuthenticationOptions
.builder().path("my-role").build();
return new GcpComputeAuthentication(options, restOperations());
}
// …
}
有关更多信息,请参阅 参考文档。
随着 0.10.0 版本的发布,Vault 引入了对 Azure 的认证支持。运行在 Azure 虚拟机上的应用程序可以通过 托管服务标识 来向 Vault 进行认证。托管服务标识(MSI)可以为虚拟机激活,而无需预先配置凭据。
Spring Vault 从 Azure Instance Metadata Service (IMDS) 获取 MSI 凭据。Vault 需要额外的详细信息(订阅 ID、资源组名称、VM 名称)来执行认证。默认情况下,这些值也从 IMDS 获取,并与身份令牌一起传递给 Vault。可能的客户端配置可能如下面的代码示例所示:
@Configuration
class VaultConfiguration extends AbstractVaultConfiguration {
@Override
public ClientAuthentication clientAuthentication() {
AzureMsiAuthenticationOptions options = AzureMsiAuthenticationOptions.builder()
.role("my-role").build();
return new AzureMsiAuthentication(options, restOperations());
}
// …
}
有关更多信息,请参阅 参考文档。
Vault 在 0.10 版本中引入了其 Key-Value 后端(几年前也称为通用 secret 后端)的带版本变体。此更改引入了另一种后端类型,其操作(list、get、put、delete)的外部 API 相似,但 API 实现不同。
为了统一带版本和不带版本的 API 访问,我们引入了 VaultKeyValueOperations 作为通用 API。VaultKeyValueOperations 暴露了通用功能,如果您不想与版本控制元数据交互,可以使用它以版本无关的方式访问。以下示例显示了如何使用它:
VaultOperations vaultOperations = …
VaultKeyValueOperations operations = vaultOperations.opsForKeyValue("secret", KeyValueBackend.unversioned());
Map<String, Object> secret = new HashMap<>();
secret.put("key", "value");
secret.put("ttl", "5");
operations.put("key", secret);
operations.put("key", new Person(…));
VaultResponseSupport<Person> person = operations.get("key", Person.class);
上面显示的变体忽略了版本控制的细节,即使目标 secret 后端提供了这些细节。您可以获取带版本的 Key-Value API 来与版本进行交互。VaultVersionedKeyValueOperations 暴露了版本特定的操作,例如检索特定 secret 版本或进行比较并设置。请看以下示例:
VaultOperations vaultOperations = …
VaultVersionedKeyValueOperations operations = vaultOperations.opsForVersionedKeyValue("versioned");
Map<String, Object> secret = new HashMap<>();
secret.put("key", "value");
secret.put("ttl", "5");
Metadata metadata = operations.put("key", secret);
Versioned<Map<String, Object>> versioned = operations.get("key", Version.from(42));
Map<String, Object> update = new HashMap<>();
update.put("key", "new-key");
update.put("ttl", "5");
Versioned<Map<String, Object>> compareAndSet = Versioned.create(secret, versioned.getVersion());
operations.put("key", compareAndSet);
operations.delete("key", Version.from(42));
对带版本 secret 的请求和响应会将内容与版本控制元数据一起包装在 Versioned 对象中,以附加版本上下文。
Vault 的核心概念之一是包装响应并返回一个令牌以获取实际响应正文。响应包装现在由一个专用 API VaultWrappingOperations 提供支持。包装支持允许查找包装的响应。您可以读取这些响应并重新包装内容。VaultWrappingOperations 不支持 Spring Vault API 调用的响应包装。如果您需要创建包装的响应,可以直接通过 VaultOperations.doWithSession(…) 使用 RestTemplate。
以下示例提供了 VaultWrappingOperations 用法的概述:
VaultOperations vaultOperations = …
VaultWrappingOperations operations = vaultOperations.opsForWrapping();
VaultToken wrappingToken = VaultToken.of(…);
// Metadata encapsulated TTL and Creation Time
WrappedMetadata lookup = operations.lookup(wrappingToken);
// Read the response as generic Map
VaultResponse response = operations.read(wrappingToken);
// Read the response applying a type hint.
VaultResponseSupport<SocialSecurityNumber> response = operations.read(
wrappingToken, SocialSecurityNumber.class);
// You can also wrap user-supplied data and get a token in return
Map<String, String> map = Collections.singletonMap("key", "value");
WrappedMetadata metadata = wrappingOperations.wrap(map, Duration.ofSeconds(100));
Spring Vault 完全支持 Java 11,作为下一个长期支持版本。事实上,如果您正在为 JDK 11 开发,我们强烈建议您将 Spring Vault 版本升级到 2.1 版本(与 Spring Framework 5.1 结合使用),这将使您获得无警告的 Spring 库体验。所有 HTTP 客户端集成都支持 JDK 11。
我们正致力于 Spring Vault 2.2 的下一个版本,该版本将提供带版本 Vault Key-Value 后端的基于注解的配置。我们将持续关注 Vault 项目,并继续努力为有意义的应用场景提供功能集成。祝您一切顺利,敬请关注!