1. 概述

本教程将实现 Spring CredHub,这是 CredHub 的 Spring 抽象层,用于存储带有访问控制规则的密钥,将凭证资源映射到用户和操作。⚠️ 注意:运行代码前需确保应用运行在已安装 CredHub 的 Cloud Foundry 平台上。

2. Maven 依赖

首先添加 spring-credhub-starter 依赖:

<dependency>
    <groupId>org.springframework.credhub</groupId>
    <artifactId>spring-credhub-starter</artifactId>
    <version>2.2.0</version>
</dependency>

3. 为什么凭证管理很重要?

凭证管理是安全、集中处理凭证全生命周期的过程,主要包括生成、创建、轮换和撤销。尽管各公司的应用和 IT 环境差异很大,但有一件事是共通的:每个应用都需要凭证来访问其他应用、数据库或工具。

凭证管理对数据安全至关重要,它为用户和应用提供敏感信息访问权限。因此,确保凭证在传输和静态存储时的安全性非常重要。最佳实践之一是:用 API 调用替代硬编码凭证和手动管理,通过 CredHub 等专用工具程序化获取凭证。

4. CredHub API

4.1. 认证

CredHub API 支持两种认证方式:UAA(OAuth2)双向 TLS

默认使用双向 TLS 认证,在应用配置中指定 CredHub 服务器 URL:

spring:
  credhub:
    url: https://credhub.example.com

另一种方式是通过 UAA 认证,需要客户端凭据获取访问令牌:

spring:
  credhub:
    url: https://credhub.example.com
    oauth2:
      registration-id: credhub-client
  security:
    oauth2:
      client:
        registration:
          credhub-client:
            provider: uaa
            client-id: credhub-admin
            client-secret: admin-secret
            authorization-grant-type: client_credentials
        provider:
          uaa:
            token-uri: https://uaa.example.com/oauth/token

访问令牌随后会被添加到授权头中。

4.2. 凭证 API

通过 CredHubCredentialOperations 接口,可调用 CredHub API 创建、更新、检索和删除凭证。CredHub 支持的凭证类型包括:

  • value – 单个配置的字符串
  • json – 静态配置的 JSON 对象
  • user – 包含用户名、密码和密码哈希的 3 个字符串
  • password – 密码和其他字符串凭证
  • certificate – 包含根 CA、证书和私钥的对象
  • rsa – 包含公钥和私钥的对象
  • ssh – 包含 SSH 格式公钥和私钥的对象

4.3. 权限 API

权限在写入凭证时设置,用于控制用户访问、更新或检索的权限。Spring CredHub 提供 CredHubPermissionV2Operations 接口管理权限。用户允许的操作包括:readwritedelete

5. CredHub 集成

我们将实现一个返回订单详情的 Spring Boot 应用,通过示例演示凭证管理的完整生命周期。

5.1. CredHubOperations 接口

CredHubOperations 接口位于 org.springframework.credhub.core 包中,是 Spring CredHub 的核心类,提供与 CredHub 交互的丰富功能。它访问建模整个 CredHub API 的接口,并在领域对象和 CredHub 数据间映射:

public class CredentialService {
    private final CredHubCredentialOperations credentialOperations;
    private final CredHubPermissionV2Operations permissionOperations;

    public CredentialService(CredHubOperations credHubOperations) {
        this.credentialOperations = credHubOperations.credentials();
        this.permissionOperations = credHubOperations.permissionsV2();
    }
}

5.2. 凭证创建

创建 password 类型凭证,使用 PasswordCredentialRequest 构建:

SimpleCredentialName credentialName = new SimpleCredentialName(credential.getName());
PasswordCredential passwordCredential = new PasswordCredential((String) value.get("password"));
PasswordCredentialRequest request = PasswordCredentialRequest.builder()
  .name(credentialName)
  .value(passwordCredential)
  .build();
credentialOperations.write(request);

类似地,其他 CredentialRequest 实现可用于构建不同类型凭证,如 ValueCredentialRequestvalue 类型)、RsaCredentialRequestrsa 类型)等:

ValueCredential valueCredential = new ValueCredential((String) value.get("value"));
request = ValueCredentialRequest.builder()
  .name(credentialName)
  .value(valueCredential)
  .build();
RsaCredential rsaCredential = new RsaCredential((String) value.get("public_key"), (String) value.get("private_key"));
request = RsaCredentialRequest.builder()
  .name(credentialName)
  .value(rsaCredential)
  .build();

5.3. 凭证生成

Spring CredHub 支持动态生成凭证,避免应用端管理开销,提升数据安全性。实现方式如下:

SimpleCredentialName credentialName = new SimpleCredentialName("api_key");
PasswordParameters parameters = PasswordParameters.builder()
  .length(24)
  .excludeUpper(false)
  .excludeLower(false)
  .includeSpecial(true)
  .excludeNumber(false)
  .build();

CredentialDetails<PasswordCredential> generatedCred = credentialOperations.generate(PasswordParametersRequest.builder()
  .name(credentialName)
  .parameters(parameters)
  .build());

String password = generatedCred.getValue().getPassword();

5.4. 凭证轮换与撤销

凭证轮换是管理的重要环节。以下代码演示 password 类型凭证的轮换:

CredentialDetails<PasswordCredential> newPassword = credentialOperations.regenerate(credentialName, PasswordCredential.class);

CredHub 允许 certificate 类型凭证同时存在多个活跃版本,实现零停机轮换。最关键的撤销阶段实现如下:

credentialOperations.deleteByName(credentialName);

5.5. 凭证检索

理解完整生命周期后,我们检索订单 API 认证所需的最新 password 凭证:

public ResponseEntity<Collection<Order>> getAllOrders() {
    try {
        String apiKey = credentialService.getPassword("api_key");
        return new ResponseEntity<>(getOrderList(apiKey), HttpStatus.OK);
    } catch (Exception e) {
        return new ResponseEntity<>(HttpStatus.FORBIDDEN);
    }
}

public String getPassword(String name) {
    SimpleCredentialName credentialName = new SimpleCredentialName(name);
    return credentialOperations.getByName(credentialName, PasswordCredential.class)
      .getValue()
      .getPassword();
}

5.6. 凭证访问控制

权限可附加到凭证以限制访问。例如:

  • 权限 A:允许单个用户访问凭证并执行所有操作
  • 权限 B:允许所有用户仅执行 READ 操作

添加权限示例(允许用户 u101 执行 READWRITE):

Permission permission = Permission.builder()
  .app(UUID.randomUUID().toString())
  .operations(Operation.READ, Operation.WRITE)
  .user("u101")
  .build();
permissionOperations.addPermissions(name, permission);

Spring CredHub 支持的操作包括:

  • READ – 按 ID/名称获取凭证
  • WRITE – 按名称设置/生成/轮换凭证
  • DELETE – 按名称删除凭证
  • READ_ACL – 按凭证名称获取 ACL
  • WRITE_ACL – 添加/删除凭证 ACL 条目

6. 总结

本教程展示了如何使用 Spring CredHub 库集成 CredHub 与 Spring Boot。我们为订单应用集中管理凭证,覆盖两大关键点:凭证生命周期和权限控制

完整源代码可在 GitHub 获取。


原始标题:A Guide to Spring CredHub