使用 Vault 管理数据库密钥

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

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

数据库凭据往往是静态的

在数据库方面,获取凭据的常规工作流程是请求某个操作员或自助服务工具为您提供凭据,以便您的应用程序可以登录到数据库。此时,凭据被视为静态的。如果数据库迁移或发生安全漏洞,通常会更改凭据。

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

有一个需要注意的地方:长期有效的凭据很容易泄漏。泄漏的凭据可能会授予未经授权的访问。一些数据库对源主机实施限制。在某些情况下,可以将数据库用户限制为一组主机。该限制可以阻止来自其他主机的访问。但是,每个有权访问已授权机器的用户和进程都可以使用泄漏的凭据。但是,您如何发现这种泄漏呢?如果您的数据泄漏到公众或互联网上,您可能会发现泄漏,但情况并非总是如此。在其他情况下,未经授权的方可能会读取或更改您的数据,并且可以肯定的是,泄漏会在相当长的一段时间内未被发现。

让我们使凭据的有效期变短。

Vault 和数据库

Vault 提供了与各种不同系统的集成。其中一些与 PostgreSQLMySQL 集成作为密钥后端。密钥后端可以提供密钥。在这种情况下,密钥后端并不意味着密钥数据存储在 PostgreSQL/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、数据库依赖项 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)。在生产环境中不要这样做。纯文本使整个密钥故事毫无用处,因为网络上的所有侦听器都可以看到您的密钥。请注意,示例中使用的令牌是根令牌。

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

$ 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();
		}
	}

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

连接使用用户: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 令牌
  • RabbitMQ - 生成可与 Spring AMQP 一起使用的凭据
  • Amazon AWS - 生成可与 Spring Cloud AWS 一起使用的访问密钥和密钥

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

获取 Spring 电子邮件简报

通过 Spring 电子邮件简报保持联系

订阅

领先一步

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

了解更多

获取支持

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

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部