抢占先机
VMware 提供培训和认证,为您的进步加速。
了解更多在本文中,我们将深入探讨如何在 Cloud Foundry 中将 Spring 应用程序绑定到 HashiCorp 的 Vault 服务代理。
Spring Boot 提供了许多自动配置和外部绑定功能,其中一些与 Cloud Foundry 相关,而许多则不相关。Spring Cloud Connectors 是一个库,如果您想通过编程方式创建自己的组件,可以在应用程序中使用它,但它本身并不会做任何“神奇”的事情。
Spring Cloud Connectors 为与各种云服务集成的连接器奠定了基础。它提供了允许正确配置中间件的组件。使用 CloudFoundry 的 Java 构建包附带了“自动重新配置”功能,旨在减轻将简单应用程序迁移到云端的负担。
正确配置中间件服务(例如 HashiCorp 的 Vault)的关键在于了解每种工具提供了什么,以及它们在运行时如何相互影响。根据十二要素应用程序指南,目标应该是实现从开发者桌面上的本地应用程序执行到 Cloud Foundry 中的测试环境,最终再到 Cloud Foundry(或其他方式)中的生产环境的平稳过渡,且无需更改源代码或打包。
Spring Cloud Vault 连接器随附四个库
spring-cloud-vault-connector-core
提供了其他三个库使用的通用组件。
spring-cloud-vault-spring-connector
使用 Vault 连接器配置基于 Spring Framework 和 Spring Boot (Spring Cloud) 的应用程序。
spring-cloud-vault-cloudfoundry-connector
是获取 CloudFoundry 服务配置并将其提供给实际 Spring 连接器所必需的。
spring-cloud-vault-localconfig-connector
允许您提供基于属性的配置,如果您想自己配置服务,例如在 CI 或本地运行时环境中,而无需提供额外的代码来区分云环境和非云环境。
如果您正在使用 Spring Boot 和 Spring Cloud Vault,那么除了引入 Spring 和 CloudFoundry 连接器之外,您实际上无需做其他任何事情。
Spring 连接器附带一个引导配置,该配置使用服务配置中的 token 和端点来配置 Spring 的 Vault 客户端。Spring Cloud Vault 默认配置了一个属性源,指向 ${spring.application.name}/${profile-name}
。HashiCorp 的服务代理在应用程序、空间和组织命名空间中配置了通用后端。连接器按照提到的顺序获取后端和共享后端,从这些后端获取其配置属性。
@SpringBootApplication
public class HelloWorldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
static class MyComponent {
public MyComponent(@Value("${some-property}") String someProperty, (1)
VaultOperations vaultOperations) { (2)
// …
}
}
}
直接注入配置属性。Spring 会尝试从配置了 Vault 的 PropertySource
的 Environment
中解析属性。
注入配置为使用已连接 Vault 服务的 VaultOperations
。
如果您的应用程序纯粹基于 Spring Framework 或是一个不使用 Spring Cloud Vault 的 Spring Boot 应用程序,那么在您的某个配置类上启用 @ServiceScan
就足以获取认证信息和端点。
public class CloudFoundryApplication {
@Configuration
@ServiceScan (1)
static class VaultConfig {
}
public static void main(String[] args) {
GenericApplicationContext ctx =
new AnnotationConfigApplicationContext(VaultConnectorsConfig.class,
VaultConfig.class);
ctx.start();
VaultOperations vaultOperations = ctx.getBean(VaultOperations.class); (2)
ctx.stop();
}
}
@ServiceScan
启用对绑定到您应用程序的服务的扫描。它会为所有找到的服务创建 bean。
VaultOperations
是由服务扫描创建的,因此您可以在应用程序中直接使用它。
您是想自己配置 bean 而不激活 @ServiceScan
,还是想提供定制的客户端配置?那么请直接使用 Cloud
。Cloud
对象使您能够访问服务信息并允许您创建 VaultTemplate
。
@Configuration
class VaultConfig {
@Bean
public Cloud cloud() { (1)
return new CloudFactory().getCloud();
}
@Bean
public SslConfiguration sslConfiguration() { (2)
return SslConfiguration.forTrustStore(…);
}
@Bean
VaultOperations vaultOperations() { (3)
VaultServiceInfo vaultServiceInfo = (VaultServiceInfo) cloud()
.getServiceInfos(VaultOperations.class).get(0);
VaultServiceConnectorConfig config = VaultServiceConnectorConfig.builder()
.sslConfiguration(sslConfiguration())
.build();
return cloud().getSingletonServiceConnector(VaultOperations.class, config);
}
}
Cloud
对象解析绑定的服务。将其注册为 bean 只需解析一次,而无需在每次需要 Cloud
对象时重新解析服务。
在您的配置中,可能需要定制 SSL 或客户端配置选项。这里是一个如何为 Spring 的 Vault 客户端提供信任存储的示例。
cloud 对象暴露了创建服务连接器的方法。将 VaultServiceConnectorConfig
以及 VaultOperations
服务类型传递给这些方法,以创建模板 API 实例。Cloud
对象还使您能够访问包含认证信息和托管 Vault 后端详细信息的服务信息。
HashiCorp 提供了一个服务代理,用于配置可绑定到您应用程序的 Vault 服务。它使用基于 Token 的认证并启动几个后端。具体而言,它们是
应用程序实例独享的 generic
密钥后端
应用程序实例独享的 transit
后端
在您的空间范围内的共享 generic
密钥后端
在您的组织范围内的共享 generic
密钥后端
每个应用程序的一组策略,例如限制共享组织后端对应用程序为只读。
服务实例的详细信息通过 VCAP_SERVICES
提供,这是一个应用程序可见的环境变量。通常,它看起来像
{
"hashicorp-vault": [
{
"credentials": {
"address": "https://your-server:8200/",
"auth": {
"token": "00000000-0000-0000-0000-000000000000"
},
"backends": {
"generic": "cf/20fffe9d-d8d1-4825-9977-1426840a13db/secret",
"transit": "cf/20fffe9d-d8d1-4825-9977-1426840a13db/transit"
},
"backends_shared": {
"organization": "cf/1a558498-59ad-488c-b395-8b983aacb7da/secret",
"space": "cf/d007583f-5617-4b02-a5a7-550648827cfa/secret"
}
},
"label": "hashicorp-vault",
"name": "hashicorp-vault",
}
]
}
Token 由服务代理管理和刷新,应用程序不应触碰它。撤销 Token 将关闭绑定应用程序中所有应用程序实例的访问。
哦,对了,谢谢提醒。您偶尔会希望在部署到云端之前在本地测试您的应用程序,或者您不想使用服务绑定。Spring Cloud Vault LocalConfig 连接器正是为此目的而设计的。它允许您指定一个由连接器获取的配置属性,并提供与 CloudFoundry 上的 VCAP_SERVICES
相同的一组配置键。
引导配置需要至少设置两个键
spring.cloud.appId
:应用程序标识符名称。任何描述性的应用程序名称(甚至可能是 ${spring.application.name}
)都可以。
在 spring.cloud.
命名空间下的一个键,设置为 HTTP/HTTPS URL。
spring.application.name=…
spring.cloud.appId=your-app-id spring.cloud.my-vault-service=http://localhost:8200?token=my-token &backend.generic=cf/secret &backend.transit=cf/transit &shared_backend.space=cf/space
或者写成 YAML 格式
spring.application.name: …
spring.cloud:
appId: your-app-id
my-vault-service: http://localhost:8200?token=my-token
&backend.generic=cf/secret
&backend.transit=cf/transit
&shared_backend.space=cf/space
您可能已经注意到,这个 URL 看起来与您通常使用的 Vault 端点前缀 URL 有些不同。连接器需要额外的配置选项,这些选项表示为查询参数。连接器只使用协议、主机和端口来配置端点。额外的查询参数代表了通常通过 VCAP_SERVICES
传输的键
token
认证 token(必需)
backend.(.*)
到专用后端的上下文路径。backend.
后面的属性键表示专用后端名称。
shared_backend.(.*)
到共享后端的上下文路径。shared_backend.
后面的属性键表示共享后端名称。
您可以配置多个后端和共享后端。
是的,可以!在您想对正在发生的事情拥有更多控制权,或者想避免额外的依赖项的情况下,还有另一种连接到 Vault 的可能性。Spring Boot 提供了 CloudFoundryVcapEnvironmentPostProcessor
,它通过属性源将 CloudFoundry 的 VCAP
变量导出到您的应用程序。这些属性对于 VCAP_APPLICATION
分别带有 vcap.application
前缀,对于 VCAP_SERVICES
带有 vcap.services
前缀。您可以在配置中像引用任何其他属性一样引用 VCAP 属性。
通过 VCAP_SERVICES
配置 Vault 连接需要了解 VCAP_SERVICES
的实际结构。配置 URL 和 token 认证是使 Spring Boot 与 Spring Cloud Vault 一起工作所需的仅有的两个属性。根据上面的示例,您的引导配置将如下所示
spring.application.name=…
spring.cloud.vault.url=${vcap.services.hashicorp-vault.credentials.address}
spring.cloud.vault.token=${vcap.services.hashicorp-vault.auth.token}
spring.cloud.vault.generic.backend=${vcap.services.hashicorp-vault.credentials.backend.generic}
或者写成 YAML 格式
spring.application.name: …
spring.cloud.vault:
url: ${vcap.services.hashicorp-vault.credentials.address}
token: ${vcap.services.hashicorp-vault.auth.token}
generic.backend: ${vcap.services.hashicorp-vault.credentials.backend.generic}
您可以在没有任何额外自动配置库的情况下拥有完全控制权。使用属性可以利用 profiles 进行条件激活。
Spring Vault: https://projects.spring.io/spring-vault/
Spring Cloud Vault: https://cloud.spring.io/spring-cloud-vault/
Spring Cloud Connectors: http://cloud.spring.io/spring-cloud-connectors/
Spring Vault 和 Spring Cloud Vault 示例: https://github.com/mp911de/spring-cloud-vault-config-samples
项目仓库: https://github.com/pivotal-cf/spring-cloud-vault-connector
Dave Syer 关于 CloudFoundry 上绑定数据服务的优秀文章: https://springframework.org.cn/blog/2015/04/27/binding-to-data-services-with-spring-boot-in-cloud-foundry