Spring Vault 2.1 实操

工程技术 | Mark Paluch | 2018年9月24日 | ...

Spring Vault 2.1 已经近在眼前。我想借此文深入探讨一下即将在新版本中出现的更改和功能。

团队一直在致力于大量新功能

  • 扩展基于基础设施的认证,支持 Google Cloud IAM 和 Azure Managed Service Identity

  • 集成 Vault 的版本化 Key-Value 后端

  • Wrapping API 支持

  • Java 11 兼容性

Spring Vault 支持 HashiCorp Vault 0.5 至 0.11 版本。您可以在 GitHub 上找到 Spring Vault 和 Spring Cloud Vault 的示例仓库。现在,让我们深入了解 Spring Vault 2.1 的功能!

Google Cloud 认证

从版本 0.8.1 开始,Vault 引入了对 Google Cloud 的认证支持。GCP 认证使用 GCP 的 IAM 服务来执行以下认证流程之一

  • 使用服务账号凭据生成签名令牌的 IAM 登录

  • 使用 GCP 元数据服务检索签名令牌的 GCE 登录

Spring Vault 支持这两种方法。使用 IAM 认证需要设置凭据(可以通过环境变量或凭据文件),而 GCE 认证使用平台作为身份提供者,因此 GCE 认证对初始设置的要求更少。

IAM 登录

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 登录

GCE (Google Compute Engine) 认证流程适用于虚拟机实例。它使用元数据服务 (compute metadata) 获取签名令牌。签名身份会传递给 Vault 以验证虚拟机实例。客户端配置示例如下所示

@Configuration
class VaultConfiguration extends AbstractVaultConfiguration {

  @Override
  public ClientAuthentication clientAuthentication() {

    GcpComputeAuthenticationOptions options = GcpComputeAuthenticationOptions
        .builder().path("my-role").build();

    return new GcpComputeAuthentication(options, restOperations());
  }

  // …
}

欲了解更多信息,请参阅参考文档

Azure 认证

从版本 0.10.0 开始,Vault 引入了对 Azure 的认证支持。在 Azure 虚拟机上运行的应用程序可以使用托管服务标识对 Vault 进行认证。托管服务标识 (MSI) 可以为无需预先配置凭据的虚拟机激活。

Spring Vault 从 Azure Instance Metadata Service (IMDS) 获取 MSI 凭据。Vault 需要额外的详细信息(subscriptionId、资源组名称、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());
  }

  // …
}

欲了解更多信息,请参阅参考文档

Key-Value API

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 对象中,以附加版本化上下文。

Wrapping API 支持

Vault 的核心概念是将响应包装起来并返回一个令牌,以便获取实际的响应体。现在通过一个带有 VaultWrappingOperations 的专用 API 支持响应包装。Wrapping 支持允许查找包装的响应。您可以读取这些响应并重新包装内容。VaultWrappingOperations 不支持对 Spring Vault API 调用的响应包装。如果您需要创建包装的响应,可以直接使用 RestTemplate 通过 VaultOperations.doWithSession(…)

以下示例概述了 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));

Java 11 兼容性

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 项目,并持续努力提供从应用程序角度来看有意义的功能集成。干杯,敬请关注!

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获取支持

Tanzu Spring 通过简单的订阅方式,提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部