1. 概述
在这个教程中,我们将演示如何将一个Spring Boot应用与AWS Secrets Manager集成,以便获取数据库凭据和其他类型的密钥,如API密钥。
2. AWS Secrets Manager
AWS Secrets Manager 是AWS的一项服务,用于安全地存储、轮换和管理凭据,例如数据库、API密钥、令牌或任何我们想要管理的其他密钥。
我们可以将密钥分为两类:一类是专门用于数据库凭据,另一类则更为通用,适用于任何类型的密钥。
使用AWS Secrets Manager的一个好例子是为应用程序提供一组凭据或API密钥。
推荐的密钥存储格式是JSON。此外,如果要利用密钥轮换功能,必须使用 JSON结构。
3. 与AWS Secrets Manager集成
AWS Secrets Manager可以轻松地与我们的Spring Boot应用集成。我们将通过AWS CLI创建密钥,然后在Spring Boot中通过简单配置来获取它们。
3.1. 密钥创建
让我们在AWS Secrets Manager中创建一个密钥。为此,我们可以使用AWS CLI和aws secretsmanager create-secret
命令。
在我们的案例中,我们将密钥命名为test/secret/
,并创建两对API密钥——api-key1
和apiKeyValue1
,以及api-key2
和apiKeyValue2:
:
aws secretsmanager create-secret \
--name test/secret/ \
--secret-string "{\"api-key1\":\"apiKeyValue1\",\"api-key2\":\"apiKeyValue2\"}"
作为响应,我们应该会得到创建的密钥的ARN、名称和版本ID:
{
"ARN": "arn:aws:secretsmanager:eu-central-1:111122223333:secret:my/secret/-gLK10U",
"Name": "test/secret/",
"VersionId": "a04f735e-3b5f-4194-be0d-719d5386b67b"
}
3.2. Spring Boot应用集成
为了获取新创建的密钥,我们需要添加依赖[spring-cloud-starter-aws-secrets-manager-config](https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-aws-secrets-manager-config)
:
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-starter-aws-secrets-manager-config</artifactId>
<version>2.4.4</version>
</dependency>
接下来,我们在application.properties
文件中添加一个属性:
spring.config.import=aws-secretsmanager:test/secret/
这里提供了我们刚刚创建的密钥的名称。设置完成后,我们可以在应用中使用新的密钥并验证其值。
为了做到这一点,我们可以通过@Value
注解将密钥注入到应用中。在注解中,指定我们在创建密钥过程中提供的字段名称。在本例中,这些字段是api-key1
和api-key2
:
@Value("${api-key1}")
private String apiKeyValue1;
@Value("${api-key2}")
private String apiKeyValue2;
为了在示例中验证值,我们可以在bean属性初始化后的@PostConstruct
方法中打印它们:
@PostConstruct
private void postConstruct() {
System.out.println(apiKeyValue1);
System.out.println(apiKeyValue2);
}
需要注意的是,在控制台上输出密钥值不是一个好习惯。然而,我们可以看到,当运行应用时,我们的值已正确加载:
2023-03-26 12:40:24.376 INFO 33504 [main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
apiKeyValue1
apiKeyValue2
2023-03-26 12:40:25.306 INFO 33504 [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
4. 数据库凭据专用密钥
在AWS Secrets Manager中,有一种特殊的密钥类型用于存储数据库凭据。我们可以选择AWS支持的数据库之一,如Amazon RDS、Amazon DocumentDB或Amazon Redshift。对于非Amazon数据库,另一种可能性是提供服务器地址、数据库名称和端口。
在Spring Boot应用中使用aws-secretsmanager-jdbc
库,我们可以轻松地将这些凭据提供给数据库。此外,如果在Secrets Manager中轮换凭证,由AWS提供的库会在使用旧凭据时自动检索新的凭证,当遇到认证错误时。
4.1. 数据库类型密钥创建
要在AWS Secrets Manager中创建数据库类型的密钥,我们将再次使用AWS CLI:
$ aws secretsmanager create-secret \
--name rds/credentials \
--secret-string file://mycredentials.json
在上述命令中,我们使用mycredentials.json
文件,其中包含了我们数据库所需的所有属性:
{
"engine": "mysql",
"host": "cwhgvgjbpqqa.eu-central-rds.amazonaws.com",
"username": "admin",
"password": "password",
"dbname": "db-1",
"port": "3306"
}
4.2. Spring Boot应用集成
创建了密钥后,我们就可以在Spring Boot应用中使用它了。为此,我们需要添加一些依赖,如[aws-secretsmanager-jdbc](https://mvnrepository.com/artifact/com.amazonaws.secretsmanager/aws-secretsmanager-jdbc)
和mysql-connector-java
:
<dependency>
<groupId>com.amazonaws.secretsmanager</groupId>
<artifactId>aws-secretsmanager-jdbc</artifactId>
<version>1.0.11</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
最后,我们还需要在application.properties
文件中设置一些属性:
spring.datasource.driver-class-name=com.amazonaws.secretsmanager.sql.AWSSecretsManagerMySQLDriver
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.datasource.url=jdbc-secretsmanager:mysql://db-1.cwhqvgjbpgfw.eu-central-1.rds.amazonaws.com:3306
spring.datasource.username=rds/credentials
在spring.datasource.driver-class-name
中,指定我们想要使用的驱动程序名称。
下一个属性是spring.jpa.database-platform
,在这里提供我们的方言。
当我们设置数据库URL时(spring.datasource.url
),需要在URL前加上jdbc-secretsmanager
前缀,因为我们在集成AWS Secrets Manager。在这个示例中,我们的URL指向MySQL RDS实例,但也可以指向任何MySQL数据库。
在spring.datasource.username
中,只需提供我们在AWS Secrets Manager中设置的用户名。基于这些属性,应用会在连接数据库之前尝试从Secrets Manager获取用户名和密码。
在应用日志中,我们可以看到已成功连接到数据库,并且EntityManager
已经初始化:
2023-03-26 12:40:22.648 INFO 33504 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2023-03-26 12:40:22.697 INFO 33504 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.12.Final
2023-03-26 12:40:22.845 INFO 33504 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2023-03-26 12:40:22.951 INFO 33504 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2023-03-26 12:40:23.752 INFO 33504 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2023-03-26 12:40:23.783 INFO 33504 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
2023-03-26 12:40:24.363 INFO 33504 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2023-03-26 12:40:24.376 INFO 33504 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
此外,我们还创建了一个简单的UserController
,用于创建、读取和删除用户。
我们可以使用curl
创建用户:
$ curl --location 'localhost:8080/users/' \
--header 'Content-Type: application/json' \
--data '{
"name": "my-user-1"
}'
并得到成功的响应:
{"id":1,"name":"my-user-1"}
5. 结论
在这篇文章中,我们学习了如何将Spring Boot应用与AWS Secrets Manager集成,以及如何获取数据库凭据和其他类型的密钥。
如往常一样,示例代码可在GitHub上找到。