使用 Vault 管理您的数据库秘密

工程 | Mark Paluch | 2016 年 8 月 15 日 | ...

在我之前关于使用 Vault 管理秘密的帖子中,我向您介绍了 Vault 以及如何使用通用秘密后端存储任意秘密。Vault 不仅可以管理 API 密钥、密码和其他敏感字符串数据等秘密数据。今天,我们将探讨 Vault 与数据库、服务和证书的集成。

数据库凭据倾向于静态

就数据库而言,获取数据库凭据的常规流程是请操作员或自助工具为您提供凭据,以便您的应用程序可以登录数据库。此时,凭据被认为是静态的。凭据通常在数据库迁移或发生安全漏洞时才会更改。

使用Spring Cloud Vault,您可以将用户名和密码存储在 Vault 中,而不是存储在应用程序配置中。Spring Config Server 也是一个不错的选择;它允许您在配置仓库中存储加密的秘密。您的凭据受到保护。

存在一个注意事项:长期存在的凭据很容易被泄露。泄露的凭据可能允许非预期方访问。一些数据库对源主机实施了限制。在某些情况下,数据库用户可以被限制在主机组内。这种限制可以防止从其他主机访问。但是,每个有权访问许可机器的用户和进程仍然可以使用泄露的凭据。那么如何发现这种泄露呢?如果您的数据被泄露到公共领域或互联网上,您可能会发现泄露,但这并非总是如此。在其他情况下,非预期方可能会读取或更改您的数据,并且很确定泄露会在相当长一段时间内不被发现。

让我们将凭据的生命周期缩短。

Vault 与数据库

Vault 提供了与各种系统的多种集成。其中一些集成了PostgreSQLMySQL作为秘密后端。秘密后端可以提供秘密。在这种情况下,秘密后端并不意味着秘密数据存储在 PosgreSQL/MySQL 中。它意味着 Vault 可以按需为数据库创建(和撤销)用户。

要生成数据库凭据,您首先需要设置一个角色。角色控制数据库凭据生成的权限上下文。角色定义与凭据关联的权限。如果您运行不同的应用程序,并且每个应用程序需要不同的数据库权限,那么这个概念就很有用。角色还定义了获取的凭据的最大租约时间。在 Vault 术语中,租约是凭据有效的持续时间。一旦凭据过期,Vault 就会从数据库系统中撤销它们。某些数据库,例如 PostgreSQL,内置了密码过期支持,使用 CREATE ROLE … VALID UNTIL … 子句。

Vault 与 MySQL 的第一步

那么如何开始使用 Vault 和 MySQL 呢?

您需要一个已初始化并解除封印的 Vault 服务器和一个正在运行的 MySQL 服务器。请参阅上一篇帖子了解如何设置 Vault。

然后,您可以设置 MySQL 后端以及连接详情和角色声明。

首先,使用以下命令挂载 mysql 秘密后端:

$ vault mount mysql
Successfully mounted 'mysql' at 'mysql'!

每个挂载对应一个 MySQL 服务器。如果您想为多个服务器生成凭据,则需要使用不同的路径多次挂载后端。

后端挂载后,您需要提供由用户名/密码组合以及主机和端口组成的控制连接详细信息。控制连接用于创建和撤销用户。

$ vault write mysql/config/connection \
	connection_url="root:root@tcp(127.0.0.1:3306)/"
Success! Data written to: mysql/config/connection

角色包含用于用户创建和授权的脚本。如果需要,您可以包含多个命令。Vault 将在每次生成凭据时执行这些命令。

$ vault write mysql/roles/readonly \
	sql="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON *.* TO '{{name}}'@'%';"
Success! Data written to: mysql/roles/readonly

Vault 现在已准备好为 readonly 角色生成凭据。您可以使用以下命令获取凭据:

$ vault read mysql/creds/readonly
Key            	Value
---            	-----
lease_id       	mysql/creds/readonly/2e7cd1d0-e313-158e-c9a4-1dd3c3277642
lease_duration 	2592000
lease_renewable	true
password       	04cf512a-57f8-d146-9cf5-ec2bd829ca8c
username       	token-10a8b69f-a

并使用 mysql 控制台应用程序验证它们是否工作:

$ mysql -h 127.0.0.1 -utoken-10a8b69f-a -p04cf512a-57f8-d146-9cf5-ec2bd829ca8c
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
...

现在我们知道我们的 Vault/MySQL 集成正在工作,我们可以在 Spring Boot 应用程序中结合 Spring Cloud Vault 使用它。

获取一个 Spring Boot 项目。start.spring.io 是一个不错的起点。

在您的项目中包含 Spring Cloud Vault Starter、Database 依赖项、spring-jdbc 和 MySQL 驱动程序。将以下代码添加到您的构建配置文件中。这些行包含所有必需的依赖项。

Maven

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-vault-starter-config</artifactId>
	<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-vault-config-databases</artifactId>
	<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jdbc</artifactId>
</dependency>

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
</dependency>

<repositories>
	<repository>
		<id>spring-snapshots</id>
		<name>Spring Snapshots</name>
		<url>https://repo.spring.io/libs-snapshot</url>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
	</repository>
</repositories>

Gradle

repositories {
	maven {
		url 'https://repo.spring.io/libs-snapshot'
	}
}

dependencies {
	compile("org.springframework.cloud:spring-cloud-vault-starter-config:1.0.0.BUILD-SNAPSHOT")
	compile("org.springframework.cloud:spring-cloud-vault-config-databases:1.0.0.BUILD-SNAPSHOT")
	compile("org.springframework:spring-jdbc:4.3.1.RELEASE")
	compile("mysql:mysql-connector-java:5.1.39")
}

设置配置

Spring Cloud Vault 默认使用通用秘密后端。在我们的案例中,我们不需要通用后端。因此,我们需要禁用 generic 后端并启用 MySQL 后端。所有配置都需要在引导配置中指定。在本例中,我们使用 src/main/resources 中的 bootstrap.yml

spring.cloud.vault:
		token: 9a63de21-8af7-311a-9a5a-151b6a0d4795
		scheme: http
		generic:
			enabled: false
		mysql:
			enabled: true
			role: readonly

spring.datasource.url: jdbc:mysql://127.0.0.1:3306		

我们没有在配置文件中添加任何数据库凭据。这些通常是 spring.datasource.usernamespring.datasource.password

spring.cloud.vault.scheme 被设置为 http,因为我们以纯文本 HTTP 模式启动了 Vault(spring.cloud.vault.scheme 默认值为 https)。生产环境中请勿这样做。纯文本模式会使整个秘密故事变得无用,因为网络上的所有监听者都可以看到您的秘密。请注意,示例中使用的 token 是根 token。

您可以使用以下命令创建新的 token:

$ vault token-create
Key            	Value
---            	-----
token          	728d26ae-53a6-d8b6-d7a0-c5f62238ea55
token_accessor 	2fd7dcba-39d0-04d3-8d6b-096c3529cf14
token_duration 	0
token_renewable	true
token_policies 	[root]

显然,这就是您将 Vault MySQL 集成与 Spring Boot 应用程序所需做的一切。

让我们快速为您的应用程序添加一些代码,以便您可以测试与实际代码的集成。


@SpringBootApplication
public class MySqlApplication {
	public static void main(String[] args) {
		SpringApplication.run(MySqlApplication.class, args);
	}

	@Autowired
	DataSource dataSource;

	@PostConstruct
	private void postConstruct() throws Exception {

		try (Connection connection = dataSource.getConnection();
				Statement statement = connection.createStatement()) {
				
			ResultSet resultSet = statement.executeQuery("SELECT CURRENT_USER();");
			resultSet.next();

			System.out.println("Connection works with User: " + resultSet.getString(1));

			resultSet.close();
		}
	}

然后启动您的应用程序。代码会产生如下输出:

与 User: token-... 的连接正常

Spring Cloud Vault 在启动时获取数据库凭据,并使用默认属性名存储它们,以便 Spring Boot 可以获取这些凭据。

其他服务

Vault 支持其他几种集成。我们已经为我们在 Spring Boot 中支持的集成构建了支持。

您可以使用以下服务和数据库:

  • PostgreSQL 和 MySQL - 生成与 JDBC 和 Spring Data JPA 一起使用的凭据
  • Apache Cassandra - 生成与 Datastax 客户端和 Spring Data Cassandra 一起使用的凭据
  • Hashicorp Consul - 生成可与 Spring Cloud Consul 一起使用的 ACL token
  • RabbitMQ - 生成与 Spring AMQP 一起使用的凭据
  • Amazon AWS - 生成与 Spring Cloud AWS 一起使用的 Access key 和 Secret key

您可以在我们的示例仓库中查看完整示例:https://github.com/mp911de/spring-cloud-vault-config-samples

获取 Spring 新闻通讯

订阅 Spring 新闻通讯,保持联系

订阅

抢占先机

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

了解更多

获取支持

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

了解更多

即将到来的活动

查看 Spring 社区所有即将到来的活动。

查看全部