Spring Vault的Vault 的概念和语义以及语法、核心功能(二)

时间:2022-12-20 16:03:18

Spring Vault的Vault 的概念和语义以及语法、核心功能(二)

14.3.1. 自定义用户标识

更高级的方法允许您实现自己的 . 此类必须位于类路径上,并且必须实现 界面 和方法。Spring Vault 将获取 UserId 通过每次使用 AppId 进行身份验证时调用 获取令牌。​​AppIdUserIdMechanism​​​​org.springframework.vault.authentication.AppIdUserIdMechanism​​​​createUserId​​​​createUserId​

我的用户 ID 机制.java

public class MyUserIdMechanism implements AppIdUserIdMechanism {

@Override
public String createUserId() {

String userId = …
return userId;
}
}

另请参阅:保管库文档:使用 App ID 身份验证后端

14.4. 应用角色认证

应用角色允许计算机 身份验证,例如已弃用的(自保管库 0.6.1 起)AppId 身份验证。 AppRole 身份验证由两个难以猜测的(机密)令牌组成:RoleId 和 SecretId。

Spring Vault 通过仅提供任一 RoleId 来支持 AppRole 身份验证 或与提供的 SecretId 一起,并从保管库获取 RoleId/SecretId (带响应展开的推拉模式)。

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
.roleId(RoleId.provided("…"))
.secretId(SecretId.wrapped(VaultToken.of("…")))
.build();

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

// …
}

Spring Vault 还支持完全拉取模式:如果未提供 RoleId 和 SecretId, Spring Vault 将使用角色名称和初始令牌检索它们。这 初始令牌可能与 TTL 和使用限制相关联。

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

VaultToken initialToken = VaultToken.of("…");
AppRoleAuthenticationOptions options = AppRoleAuthenticationOptions.builder()
.appRole("…")
.roleId(RoleId.pull(initialToken))
.secretId(SecretId.pull(initialToken))
.build();

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

// …
}

另请参阅:保管库文档:使用 AppRole 身份验证后端

14.5. AWS-EC2 身份验证

aws-ec2 身份验证后端提供安全的引入机制 适用于 AWS EC2 实例,允许自动检索文件库 令 牌。与大多数保管库身份验证后端不同,此后端 不需要首次部署或预配安全敏感型 凭据(令牌、用户名/密码、客户端证书等)。 相反,它将 AWS 视为受信任的第三方,并使用 经过加密签名的动态元数据信息,具有唯一性 表示每个 EC2 实例。

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {
return new AwsEc2Authentication(restOperations());
}

// …
}

AWS-EC2 身份验证默认允许随机数跟随 首次使用信任 (TOFU) 原则。任何无意的一方 获取对 PKCS#7 身份元数据可以进行身份验证的访问权限 反对避难所。

在第一次登录期间,Spring Vault 会生成一个随机数 存储在实例 ID 旁边的身份验证后端中。 重新身份验证需要发送相同的随机数。任何其他 派对没有随机数,可以在保险柜中发出警报 进一步调查。

随机数保留在内存中,并在应用程序重新启动期间丢失。

AWS-EC2 身份验证角色是可选的,默认为 AMI。 您可以通过设置 它在.​​AwsEc2AuthenticationOptions​

另请参阅:文件库文档:使用 AWS-EC2 身份验证后端

14.6. 亚马逊云数据库身份验证

AWS 身份验证后端允许使用现有 AWS IAM 凭证登录文件库。

AWS IAM 身份验证创建一个签名的 HTTP 请求,该请求是 由保险柜执行,以使用 AWS STS 方法获取签名者的身份。AWSv4 签名需要 IAM 凭证。​​GetCallerIdentity​

可以从运行时环境获取 IAM 凭证 或外部供应。运行时环境,如 AWS-EC2, 分配了 IAM 委托人的 Lambda 和 ECS 不需要特定于客户端的 凭据的配置,但可以从其元数据源获取这些凭据。

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

AwsIamAuthenticationOptions options = AwsIamAuthenticationOptions.builder()
.credentials(new BasicAWSCredentials(…)).build();

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

// …
}

例 27。使用 AWS-EC2 实例配置文件作为凭证源

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

AwsIamAuthenticationOptions options = AwsIamAuthenticationOptions.builder()
.credentialsProvider(InstanceProfileCredentialsProvider.getInstance()).build();

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

// …
}

​AwsIamAuthentication​​需要 AWS Java 开发工具包依赖项 () 因为身份验证实施使用 AWS 开发工具包类型进行凭证和请求签名。​​com.amazonaws:aws-java-sdk-core​

您可以通过 配置身份验证。​​AwsIamAuthenticationOptions​

另请参阅:

  • 文件库文档:使用 AWS 身份验证后端
  • AWS 文档:STS GetCallerIdentity

14.7. Azure (MSI) 身份验证

Azure 身份验证后端提供安全的引入机制 适用于 Azure VM 实例,允许自动检索保管库 令 牌。与大多数保管库身份验证后端不同,此后端 不需要首次部署或预配安全敏感型 凭据(令牌、用户名/密码、客户端证书等)。 相反,它将 Azure 视为受信任的第三方,并使用 可以是托管服务标识和实例元数据信息 绑定到虚拟机实例。

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

AzureMsiAuthenticationOptions options = AzureMsiAuthenticationOptions.builder()
.role(…).build();

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

// …
}

Azure 身份验证需要有关 VM 环境的详细信息(订阅 ID、 资源组名称、VM 名称)。可以通过 配置这些详细信息。 如果未配置,则将 Azure 的实例元数据服务查询到 获取这些详细信息。​​AzureMsiAuthenticationOptionsBuilder​​​​AzureMsiAuthentication​

另请参阅:

  • 保管库文档:使用 Azure 身份验证后端
  • Azure 文档:托管服务标识

14.8. GCP-GCE 身份验证

gcp 身份验证后端允许使用现有的 GCP(Google Cloud Platform)IAM 和 GCE 凭证登录保险柜。

GCP GCE(谷歌计算引擎)身份验证以 服务帐户的 JSON Web 令牌 (JWT)。计算引擎实例的 JWT 使用实例标识从 GCE 元数据服务获取。 此 API 创建一个可用于确认实例身份的 JSON Web 令牌。

与大多数保管库身份验证后端不同,此后端 不需要首次部署或预配安全敏感型 凭据(令牌、用户名/密码、客户端证书等)。 相反,它将 GCP 视为受信任的第三方,并使用 经过加密签名的动态元数据信息,具有唯一性 表示每个 GCP 服务帐号。

您可以通过 配置身份验证。​​GcpComputeAuthenticationOptions​

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

GcpComputeAuthenticationOptions options = GcpComputeAuthenticationOptions.builder()
.role(…).build();

GcpComputeAuthentication authentication = new GcpComputeAuthentication(options,
restOperations());
}

// …
}

另请参阅:

  • 保险库文档:使用 GCP 身份验证后端
  • GCP 文档:验证实例的身份

14.9. GCP-IAM 身份验证

gcp 身份验证后端允许使用现有的 GCP(Google Cloud Platform)IAM 和 GCE 凭证登录保险柜。

GCP IAM 身份验证以 JSON Web 令牌 (JWT) 的形式创建签名 对于服务帐户。服务帐户的 JWT 由 调用 GCP IAM 的 projects.serviceAccounts.signJwt API。调用方针对 GCP IAM 进行身份验证 并由此证明其身份。此保险柜后端将 GCP 视为受信任的第三方。

可以从运行时环境获取 IAM 凭证 或作为 JSON 等外部提供。JSON 是首选形式,因为它 携带调用所需的项目 ID 和服务帐户标识符。​​projects.serviceAccounts.signJwt​

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder()
.role(…).credential(GoogleCredentials.getApplicationDefault()).build();

GcpIamAuthentication authentication = new GcpIamAuthentication(options,
restOperations());
}

// …
}

​GcpIamAuthenticationOptions​​需要 Google Cloud Java SDK 依赖项 ( 和 ) 因为身份验证实现使用谷歌 API 进行凭据和 JWT 签名。​​com.google.apis:google-api-services-iam​​​​com.google.auth:google-auth-library-oauth2-http​

您可以通过 配置身份验证。​​GcpIamAuthenticationOptions​

Google 凭据需要 OAuth 2 令牌来维护令牌生命周期。所有接口 是同步的,因此,不支持哪个 反应性使用是必需的。​​GcpIamAuthentication​​​​AuthenticationSteps​

另请参阅:

  • 保险库文档:使用 GCP 身份验证后端
  • GCP 文档:projects.serviceAccounts.signJwt

14.10. PCF 认证

pcf 身份验证后端允许 PCF 实例的保管库登录。 它利用了PCF的应用程序和容器身份保证。

PCF 身份验证使用实例密钥和证书来创建由保险柜验证的签名。 如果签名匹配,并且可能绑定的组织/空间/应用程序 ID 匹配,则保险柜会颁发适当范围的令牌。

实例凭据可从文件 和 变量中获得。​​CF_INSTANCE_CERT​​​​CF_INSTANCE_KEY​

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

PcfAuthenticationOptions options = PcfAuthenticationOptions.builder()
.role(…).build();

PcfAuthentication authentication = new PcfAuthentication(options,
restOperations());
}

// …
}

​PcfAuthenticationOptions​​需要 BouncyCastle 库来创建 RSA-PSS 签名。

您可以通过 配置身份验证。​​PcfAuthenticationOptions​

另请参阅:

  • 保管库文档: 使用 PCF 身份验证后端

14.11. TLS 证书认证

身份验证后端允许使用 SSL/TLS 客户端进行身份验证 由 CA 签名或自签名的证书。​​cert​

要启用身份验证,您需要:​​cert​

  1. 使用 SSL,请参阅保管库客户端 SSL 配置
  2. 配置包含客户机的 Java 证书和私钥Keystore
@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

ClientCertificateAuthenticationOptions options = ClientCertificateAuthenticationOptions.builder()
.path(…).build();

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

// …
}

另请参阅:保管库文档:使用 Cert 身份验证后端

14.12. 隔间验证

隔间孔身份验证使用 Vault 原语来提供安全身份验证 工作流。隔间孔身份验证使用令牌作为主要登录方法。 临时令牌用于从保管库的 小隔间秘密后端。登录令牌的生存期通常更长,用于 与保险柜互动。登录令牌可以从包装的 响应或来自该部分。​​data​

创建包装的令牌

创建令牌的响应包装需要保管库 0.6.0 或更高版本。

例 28。装箱和存储代币

$ vault token-create -wrap-ttl="10m"
Key Value
--- -----
wrapping_token: 397ccb93-ff6c-b17b-9389-380b01ca2645
wrapping_token_ttl: 0h10m0s
wrapping_token_creation_time: 2016-09-18 20:29:48.652957077 +0200 CEST
wrapped_accessor: 46b6aebb-187f-932a-26d7-4f3d86a68319

例 29。包装令牌响应使用情况

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions
.builder()
.initialToken(VaultToken.of("…"))
.wrapped()
.build();

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

// …
}

使用存储的令牌

例 30。装箱和存储代币

$ vault token create
Key Value
--- -----
token f9e30681-d46a-cdaf-aaa0-2ae0a9ad0819
token_accessor 4eee9bd9-81bb-06d6-af01-723c54a72148
token_duration 0s
token_renewable false
token_policies [root]

$ vault token create -use-limit=2 -orphan -no-default-policy -policy=none
Key Value
--- -----
token 895cb88b-aef4-0e33-ba65-d50007290780
token_accessor e84b661c-8aa8-2286-b788-f258f30c8325
token_duration 0s
token_renewable false
token_policies [none]

$ export VAULT_TOKEN=895cb88b-aef4-0e33-ba65-d50007290780
$ vault write cubbyhole/token token=f9e30681-d46a-cdaf-aaa0-2ae0a9ad0819

Example 31. Stored token response usage

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

CubbyholeAuthenticationOptions options = CubbyholeAuthenticationOptions
.builder()
.initialToken(VaultToken.of("…"))
.path("cubbyhole/token")
.build();

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

// …
}

剩余 TTL/可再生性

从与非零 TTL 关联的 Cubbyhole 检索的令牌在 令牌创建时间。该时间不一定与应用程序相同 启动。为了补偿初始延迟,Cubbyhole 身份验证执行 自行查找与非零 TTL 关联的令牌,以检索剩余的 TTL。 Cubbyhole 身份验证不会在没有 TTL 的情况下自查找包装的令牌,因为 零 TTL 表示没有关联的 TTL。

未包装的代币仅通过以下方式提供有关可再生性和TTL的详细信息 检索令牌。自我查找将查找可续订性和剩余的 TTL。

另请参阅:

  • 保管库文档:令牌
  • 保管库文档:隔间机密后端
  • 库文档:响应包装

14.13. 库伦特认证

自 0.8.3 以来,Vault 支持使用 Kubernetes 令牌的基于 kubernetes 的身份验证。

使用 Kubernetes 身份验证需要 Kubernetes 服务帐户令牌, 通常安装在 . 该文件包含读取并发送到保管库的令牌。 Vault 在登录期间使用 Kubernetes 的 API 验证其有效性。​​/var/run/secrets/kubernetes.io/serviceaccount/token​

配置 Kubernetes 身份验证至少需要提供角色名称:

@Configuration
class AppConfig extends AbstractVaultConfiguration {

// …

@Override
public ClientAuthentication clientAuthentication() {

KubernetesAuthenticationOptions options = KubernetesAuthenticationOptions.builder()
.role(…).jwtSupplier(…).build();

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

// …
}

您可以通过 配置身份验证。​​KubernetesAuthenticationOptions​

另请参阅:

  • Vault 文档:使用 Kubernetes 身份验证后端
  • Kubernetes 文档:为 Pod 配置服务帐户

14.14. 身份验证步骤

​ClientAuthentication​​对象描述身份验证流程并执行实际 身份验证步骤。预先组合的身份验证易于使用和配置 与同步执行的紧密绑定。

认证方法的组成和重用常用步骤,如发布登录 不打算有效负载到保险柜或从 HTTP 源检索身份验证输入 与对象。​​ClientAuthentication​

身份验证步骤提供常见身份验证活动的可重用性。 通过创建的步骤描述函数中的身份验证流 样式将实际的身份验证执行留给特定的执行程序。​​AuthenticationSteps​

例 32。存储的令牌身份验证流。

AuthenticationSteps.just(VaultToken.of(…));

仅从 .​​AuthenticationSteps​​​​VaultToken​

可以从单个输入创建单步身份验证流。流声明 多个身份验证步骤以 或 开头,提供 身份验证状态对象,可用于映射或发布到 Vault 以进行登录。​​Supplier​​​​HttpRequest​

例 33。应用角色身份验证流

AuthenticationSteps.fromSupplier(                                       

() -> getAppRoleLogin(options.getRoleId(), options.getSecretId()))

.login("auth/{mount}/login", options.getPath());

开始声明接受 .

状态对象类型取决于响应类型,该类型可以在后面的步骤中映射。​​AuthenticationSteps​​​​Supplier<T>​​​​Supplier​

实际实现。

在这种情况下创建一个。​​Supplier​​​​Map​

通过将状态对象 () 发布到保管库端点以创建保管库令牌来执行保管库登录。

请注意,模板变量受 URL 转义的影响。​​Map​

身份验证流需要执行程序才能执行实际登录。我们提供两个执行者 对于不同的执行模型:

  • ​AuthenticationStepsExecutor​​作为同步 的直接替代品。ClientAuthentication
  • ​AuthenticationStepsOperator​​用于反应式执行。

许多 都附带静态工厂方法,用于为其特定于身份验证的选项创建:​​ClientAuthentication​​​​AuthenticationSteps​

例 34。同步执行​​AuthenticationSteps​

CubbyholeAuthenticationOptions options = …
RestOperations restOperations = …

AuthenticationSteps steps = CubbyholeAuthentication.createAuthenticationSteps(options);

AuthenticationStepsExecutor executor = new AuthenticationStepsExecutor(steps, restOperations);

VaultToken token = executor.login();

14.15. 代币生命周期

保险柜的代币可以与生存时间相关联。通过身份验证方法获取的令牌 旨在只要会话处于活动状态就使用,并且不应在应用程序处于活动状态时过期。

Spring Vault 为 Lifecycle AwareSessionManager 提供了一个会话管理器,它可以续订令牌,直到它到达其终端 TTL,然后执行另一次登录以获取与会话关联的下一个令牌。

根据身份验证方法,登录名可以创建两种令牌:

  • VaultToken:封装实际令牌的通用令牌。
  • LoginToken:与可续订性/TTL 关联的令牌。

诸如令牌身份验证之类的身份验证方法只是创建一个不携带任何可续订性/ TTL详细信息的身份验证方法。 将对令牌运行自查找,以从保险柜中检索可续订性和 TTL。 如果启用了自查找,则定期续订。请注意,永远不会撤销,只会被撤销。​​VaultToken​​​​LifecycleAwareSessionManager​​​​VaultToken​​​​VaultToken​​​​LoginToken​

直接创建的身份验证方法(所有基于登录名的身份验证方法)已提供了设置令牌续订所需的所有详细信息。如果会话管理器关闭,则从登录名获取的令牌将被吊销。​​LoginToken​​​​LifecycleAwareSessionManager​

15. 其他

在本章中了解值得一提的细节,例如 Spring 安全性集成。

15.1. 弹簧安全性

Spring Vault通过提供BytesKeyGenerator和BytesEncryptor的实现与Spring Security集成。这两种实现都使用Vault的后端。​​transit​

例 35。 例​​VaultBytesKeyGenerator​

VaultOperations operations = …;
VaultBytesKeyGenerator generator = new VaultBytesKeyGenerator(operations);

byte[] key = generator.generateKey();

例 36。 例​​VaultBytesEncryptor​

VaultTransitOperations transit = …;

VaultBytesEncryptor encryptor = new VaultBytesEncryptor(transit, "my-key-name");

byte[] ciphertext = encryptor.encrypt(plaintext);

byte[] result = encryptor.decrypt(ciphertext);

Vault 封装了一个与 JVM 分离的熵源以及服务器端密钥管理。这减轻了应用程序开发人员正确加密/解密的负担,并将负担推给了 Vault 的运营商。保险柜的运营商通常包括组织的安全团队,这意味着他们可以确保数据正确加密/解密。此外,由于加密/解密操作必须进入审核日志,因此会记录任何解密事件。

后端还支持密钥轮换,这允许生成命名密钥的新版本。使用密钥加密的所有数据都将使用最新版本的密钥;以前加密的数据可以使用旧版本的密钥解密。管理员可以控制哪些以前版本的密钥可用于解密,以防止攻击者获取密文的旧副本,从而能够成功解密它。

毕竟,Vault 是一种网络服务,每个操作都会产生延迟。大量使用加密或随机字节生成的组件可能会遇到吞吐量和性能的差异。