在一个Spring启动应用程序中使用多种类型的Vault机密



考虑以下Spring Boot应用程序的application.properties文件。

# Spring configuration parameters
spring.application.name=MyApplication
server.port=${SERVICE_PORT:8080}
# SSL Configuration
server.ssl.key-store-type=JKS
server.ssl.key-store=classpath:keystore/keystore.jks
server.ssl.key-store-password=${KEYSTORE_PASSWORD}
server.ssl.key-alias=my-alias
server.ssl.enabled=true
# Security configuration
keycloak.realm = ${AUTHENTICATION_REALM}
keycloak.auth-server-url = https://${AUTHENTICATION_HOST}:${AUTHENTICATION_PORT}/
keycloak.ssl-required = external
keycloak.resource = ${AUTHENTICATION_CLIENT}
keycloak.credentials.secret = ${AUTHENTICATION_SECRET}
keycloak.use-resource-role-mappings = true
keycloak.bearer-only = true
keycloak.truststore=classpath:keystore/cacerts.jks
keycloak.truststore-password=${TRUSTSTORE_PASSWORD}
# Database configuration
spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT:3306}/mydatabase
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update

从安全角度来看,我正在调查使用HashiCorp Vault安全存储和管理应用程序所需机密的可能性。根据秘密的种类,可以进行以下区分。

  1. SERVICE_PORTAUTHENTICATION_REALMAUTHENTICATION_HOSTAUTHENTICATION_PORTAUTHENTICATION_CLIENTDB_HOSTDB_PORT不包含高度敏感的信息,并且可以被认为是不随时间变化的。将这些值作为环境参数存储在docker compose文件中是否被认为是安全和常见的做法
  2. KEYSTORE_PASSWORDTRUSTSTORE_PASSWORDAUTHENTICATION_SECRET等参数是敏感的,但不会随着时间的推移而(经常)更改,因为更改这些密码需要更改/更新相应的密钥库文件。将这些值存储为关键价值机密有意义吗
  3. DB_USERDB_PASSWORD这样的参数极易被滥用,需要非常小心地处理。由于这些值的性质,我想将它们存储为动态生成的秘密。这也有道理吗

我在网上找到了一系列教程和文章,介绍如何将Vault集成到Spring Boot中。不幸的是,没有一篇文章描述在同一应用程序中使用多个秘密引擎。

  1. 是否可以在同一个Spring Boot应用程序中使用多个秘密引擎(键值和数据库)?如果是,bootstrap.yml文件应该是什么样子?我正在努力寻找合适的配置
  2. 什么是最好的方法?让Spring Boot使用spring-cloud-starter-vault-config处理机密的检索,或者通过产生应用程序不同Docker容器的某种编排机制处理机密检索。目前,我正在使用docker compose,其中包含Spring所需的所有秘密,这当然是一个非常糟糕的主意

EDIT01

在前面提到的application.properties文件中添加以下配置可以解决KV机密引擎中访问机密的问题。

# Vault Server Configuration
spring.cloud.vault.host=${VAULT_HOST:localhost}
spring.cloud.vault.port=${VAULT_PORT:8200}
spring.cloud.vault.scheme=http
spring.cloud.vault.connection-timeout=5000
spring.cloud.vault.read-timeout=15000
spring.cloud.vault.authentication=TOKEN
spring.cloud.vault.token=${VAULT_TOKEN}
spring.config.import=vault://secrets/my-application, vault://database
# Vault Common Secrets Configuration
spring.cloud.vault.kv.enabled=true
spring.cloud.vault.kv.backend=secrets

为了访问数据库的动态机密,我在pom.xml文件中添加了spring-cloud-starter-vault-config之外的spring-cloud-vault-config-databases依赖项,并在application.properties中添加了以下配置

# Vault Database Secrets Configuration
spring.cloud.vault.database.enabled=true
spring.cloud.vault.database.backend=database
spring.cloud.vault.database.role=ROLE_MANAGE_USERS
spring.cloud.vault.database.static-role=false
spring.cloud.vault.database.username-property=DB_USER
spring.cloud.vault.database.password-property=DB_PASSWORD

Vault上的动态秘密引擎的配置已经完成,并且似乎可以工作。我可以使用UI生成凭据,允许我登录MySQL数据库并执行任务。所以我认为那里的一切都是正常的。

Spring Boot应用程序本身无法检索数据库凭据,导致抛出Access denied for user '${DB_USER}'@'172.19.0.1' (using password: YES)错误消息。

正如我发现的一些教程中所解释的,我也尝试将每个与Vault相关的配置放在bootstrap.properties文件中,但KV机密在这种配置下不再有效。我还试图分别在application.properties和bootstrap.properties中拆分KV和数据库机密,但这似乎也不起作用。。。

我还试图将${}放在DB_USERDB_PASSWORD周围。不幸的是,没有效果。

显然,配置似乎缺少了一些东西(可能是非常基本的),但我似乎不明白。。。

感谢你阅读我的问题并为我指明正确的方向。

我添加了我的发现作为答案,以供未来参考,其他用户也在努力实现这一点。原来初始配置有一些错误。

首先,我必须删除

spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}

其次,我不得不替换

spring.cloud.vault.database.username-property=DB_USER
spring.cloud.vault.database.password-property=DB_PASSWORD

带有

spring.cloud.vault.database.username-property=spring.datasource.username
spring.cloud.vault.database.password-property=spring.datasource.password

这会自动将正确的spring.datasource.usernamespring.datasource.password属性添加到配置中,这样就不必再显式定义它们了。

最后,验证您的Vault配置是否配置了两个机密引擎:一个名为数据库(用于数据库动态机密),另一个名为主机密的(用于静态键值机密)。

secrets秘密引擎应包含与spring.config.import属性中指定的值同名的秘密(在本例中为vault://secrets/我的应用程序)。该秘密引擎定义了用作KEYSTORE_PASSWORDTRUSTSTORE_PASSWORDAUTHENTICATION_SECRET的值。

数据库机密引擎的名称应与属性spring.cloud.vault.database.backend的值相同(在本例中为数据库)。由于此机密引擎管理数据库的动态机密,因此Vault会按需创建适当的用户名和密码。确保为Vault中的每个数据库配置正确的数据库连接和角色。还要检查负责创建用户名和密码凭据的数据库用户的权限。

关于我帖子中的其他问题:

  1. 是否可以在同一个Spring Boot应用程序中使用多个秘密引擎(键值和数据库)?如果是bootstrap.yml文件看起来像?我正在努力寻找合适的这样做的配置

=>是的,你可以也不需要bootstrap.yml文件

  1. 什么是最好的方法?让Spring Boot处理使用spring-cloud-starter-vault-config或通过某种产生的编排机制处理秘密检索应用程序的不同Docker容器。目前我正在使用docker由一组环境参数组成,这些参数包含春天需要的秘密,这是一个非常糟糕的主意

=>由于我目前使用的是docker compose,所以我决定让Spring来处理机密的检索。这里肯定还有改进的空间

最新更新