In scenarios in which Java Database Connectivity (JDBC) is used to connect to a database, you can store the account of the database in an ApsaraDB RDS secret or a generic secret and then integrate the secret JDBC client into your application. This way, the application can complete identity authentication by using the secret managed by Key Management Service (KMS). This topic describes how to install and use the secret JDBC client.
SDK overview
The secret JDBC client is designed for scenarios in which JDBC is used to connect to databases. The secret JDBC client automatically obtains a secret from KMS to complete identity authentication. In other scenarios in which you want to obtain and use a secret, we recommend that you preferentially use the secret client, followed by KMS Instance SDK and Alibaba Cloud SDK. For more information, see SDK references.
To manage a secret, use Alibaba Cloud SDK.
The secret JDBC client has the following characteristics:
Supports JDBC connections, including connections in connection pools such as c3p0 and database connection pool (DBCP) and connections in data sources.
Supports ApsaraDB RDS for MySQL, ApsaraDB RDS for SQL Server, ApsaraDB RDS for PostgreSQL, and ApsaraDB RDS for MariaDB.
Allows you to specify a custom rotation interval for a secret.
Usage notes
Supported secret types: ApsaraDB RDS secret and generic secret.
We recommend that you use ApsaraDB RDS secrets in Manage Dual Account mode.
The value of a generic secret is in the JSON format. Example:
{ "AccountName":"<The username of your database account>", "AccountPassword":"<The password of your database account>" }
Supported programming languages: Java 8 or later.
Supported access credentials: AccessKey pair, Resource Access Management (RAM) role, instance RAM role of an Elastic Compute Service (ECS) instance, Security Token Service (STS) token, and client key
Step 1: Create an access credential
To obtain the values of secrets that store access credentials such as AccessKey pairs, RAM roles, instance RAM roles of ECS instances, and STS tokens, use a KMS endpoint. To obtain the values of secrets that store client keys, use a KMS endpoint or a KMS instance endpoint. For more information about endpoints, see Endpoint description.
KMS instance endpoints supports high performance. We recommend that you use KMS instance endpoints to obtain the values of secrets that store client keys.
AccessKey
For more information, see Create an AccessKey pair.
RAM role
Create a RAM role. For more information, see Create a RAM role.
Obtain RamRoleArn of the RAM role. For more information, see View the information about a RAM role.
NoteRamRoleArn is the Alibaba Cloud Resource Name (ARN) of the RAM role, which is the ID of the RAM role to be assumed. Format: acs:ram::$accountID:role/$roleName. $accountID is the ID of the Alibaba Cloud account. $roleName is the name of the RAM role.
Instance RAM role of an ECS instance
Attach an instance RAM role to an ECS instance. For more information, see Grant ECS access to other Alibaba Cloud services by using instance RAM roles.
STS
Create a RAM user or a RAM role. For more information, see Create a RAM user and Create a RAM role.
Grant the
AliyunSTSAssumeRoleAccess
permission to the RAM user or RAM role. For more information, see Grant permissions to a RAM user and Grant permissions to a RAM role.Use the RAM user or RAM role to call the AssumeRole operation of STS to obtain an STS token. For more information, see AssumeRole.
ClientKey
Create an application access point (AAP) and then create a client key in the AAP. For more information, see Create an AAP.
Step 2: Install the secret JDBC client
Visit aliyun-secretsmanager-jdbc to view more installation information and source code.
Install the secret JDBC client in your project by using Maven.
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-secretsmanager-jdbc</artifactId>
<version>x.x.x</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.x.x</version>
</dependency>
We recommend that you install the latest version.
Step 3: Use the secretsmanager.properties configuration file to configure the runtime parameters of the secret JDBC client
Add the secretsmanager.properties configuration file to the code of your project. The parameters vary based on the access credential that is used.
AccessKey
## The type of the access credential.
credentials_type=ak
## Access Key Id
credentials_access_key_id=#credentials_access_key_id#
## Access Key Secret
credentials_access_secret=#credentials_access_secret#
## The region of the KMS instance.
cache_client_region_id=[{"regionId":"#regionId#"}]
## The custom rotation interval. Default value: 21600000. Minimum value: 300000. Unit: milliseconds. The default value is equivalent to 6 hours, and the minimum value is equivalent to 5 minutes.
refresh_secret_ttl=21600000
RAM role
## The type of the access credential.
credentials_type=ram_role
## Access Key Id
credentials_access_key_id=#credentials_access_key_id#
## Access Key Secret
credentials_access_secret=#credentials_access_secret#
## The name of the session associated with the access credential.
credentials_role_session_name=#credentials_role_session_name#
## RAM Role ARN
credentials_role_arn=#credentials_role_arn#
## The policy for the access credential.
credentials_policy=#credentials_policy#
## The region of the KMS instance.
cache_client_region_id=[{"regionId":"#regionId#"}]
## The custom rotation interval. Default value: 21600000. Minimum value: 300000. Unit: milliseconds. The default value is equivalent to 6 hours, and the minimum value is equivalent to 5 minutes.
refresh_secret_ttl=21600000
Instance RAM role of an ECS instance
## The type of the access credential.
credentials_type=ecs_ram_role
## The name of the instance RAM role that is attached to your ECS instance.
credentials_role_name=#credentials_role_name#
## The region of the KMS instance.
cache_client_region_id=[{"regionId":"#regionId#"}]
## The custom rotation interval. Default value: 21600000. Minimum value: 300000. Unit: milliseconds. The default value is equivalent to 6 hours, and the minimum value is equivalent to 5 minutes.
refresh_secret_ttl=21600000
STS
## The type of the access credential.
credentials_type=sts
## Access Key Id
credentials_access_key_id=#credentials_access_key_id#
## Access Key Secret
credentials_access_secret=#credentials_access_secret#
## The name of the session associated with the access credential.
credentials_role_session_name=#credentials_role_session_name#
## RAM Role ARN
credentials_role_arn=#credentials_role_arn#
## The policy for the access credential.
credentials_policy=#credentials_policy#
## The region of the KMS instance.
cache_client_region_id=[{"regionId":"#regionId#"}]
## The custom rotation interval. Default value: 21600000. Minimum value: 300000. Unit: milliseconds. The default value is equivalent to 6 hours, and the minimum value is equivalent to 5 minutes.
refresh_secret_ttl=21600000
ClientKey
KMS endpoint
## The type of the access credential. credentials_type=client_key ## The password for the client key. You can obtain the password from an environment variable or a file. client_key_password_from_env_variable=#your client key private key password environment variable name# client_key_password_from_file_path=#your client key private key password file path# ## The region of the KMS instance. cache_client_region_id=[{"regionId":"#regionId#"}] ## The custom rotation interval. Default value: 21600000. Minimum value: 300000. Unit: milliseconds. The default value is equivalent to 6 hours, and the minimum value is equivalent to 5 minutes. ## In the following configuration, the rotation interval is set to 1 hour. refresh_secret_ttl=3600000 client_key_file_path=#your client key file path#
KMS instance endpoint
Method 1: Obtain the password for the client key from a file
You must save the password to a file. The name of the file must be the same as the value of
passwordFromFilePath
.cache_client_dkms_config_info=[{"regionId":"<your dkms region>","endpoint":"<your dkms endpoint>","passwordFromFilePath":"< your password file path >","clientKeyFile":"<your Client Key file path>","ignoreSslCerts":false,"caFilePath":"<your CA certificate file path>"}]
Method 2: Obtain the password for the client key from an environment variable
You must save the password to an environment variable. The name of the environment variable must be the same as the value of
passwordFromEnvVariable
.cache_client_dkms_config_info=[{"regionId":"<your dkms region>","endpoint":"<your dkms endpoint>","passwordFromEnvVariable":"<your_password_env_variable>","clientKeyFile":"<your ClientKey file path>","ignoreSslCerts":false,"caFilePath":"<your CA certificate file path>"}]
Description
Parameter
Description
Setting notes
regionId
The ID of the region where the KMS instance resides.
For more information about how to obtain the region ID, see Regions and endpoints.
endpoint
The endpoint of the KMS instance, which is in the
{Instance ID}.kms.aliyuncs.com
format.To view the endpoint of a KMS instance, go to the Instances page in the KMS console, view the details of the KMS instance, obtain the value of Instance VPC Endpoint, and then remove
https://
from the value.clientKeyFile
The absolute or relative path to the client key file in the JSON format.
Client key file: The file is downloaded when you create a client key for an AAP. The file stores the content of Application Access Secret(ClientKeyContent) and is named in the ClientKey_******.json format.
Password file: The file is downloaded when you create a client key for an AAP. The file stores the content of Password and is named in the ClientKey_******_password.txt format.
ImportantThe client key and password have a one-to-one correspondence. You can obtain both only when you create the client key. If you do not save the client key or password when you create the client key, you must create another client key. For more information, see Create an AAP.
passwordFromFilePath or passwordFromEnvVariable
passwordFromFilePath: The password for the client key is obtained from a file. The value is the absolute or relative path to the file that contains the password for the client key. To configure passwordFromFilePath, you must save the password to a file.
passwordFromEnvVariable: The password for the client key is obtained from an environment variable. The value is the name of the environment variable that stores the password for the client key. You must save the password to the environment variable.
ignoreSslCerts
Specifies whether to ignore the validity check on the SSL certificate of the KMS instance. The KMS instance has a built-in SSL certificate that is used for identity verification and SSL-encrypted or TLS-encrypted communication. Valid values:
true: The validity check is ignored.
NoteIf you set this parameter to true, you do not need to configure caFilePath.
false: The validity check is performed.
In the production environment, set this parameter to false.
caFilePath
The absolute or relative path to the certificate authority (CA) certificate file of the KMS instance.
The CA certificate is used to check the validity of the SSL certificate of the KMS instance. For example, you can check whether the SSL certificate is issued by the required CA, whether the SSL certificate is within the validity period, and whether the domain name bound to the SSL certificate is the endpoint of the KMS instance.
To obtain the CA certificate, go to the Instances page and click Download below Instance CA Certificate.
Step 4: Use the secret JDBC client to connect to a database
In this example, only the properties that must be modified are provided. You can configure other properties based on your business requirements.
Connect to a database by using JDBC
ApsaraDB RDS for MySQL
NoteReplace
#your-mysql-secret-name#
,<your-mysql-ip>
,<your-mysql-port>
, and<your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class SecretManagerJDBCSample { public static void main(String[] args) throws Exception { // Load the secret JDBC client. Class.forName("com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver"); Connection connect = null; try { connect = DriverManager.getConnection("secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>", "#your-mysql-secret-name#",""); } catch(SQLException e) { e.printStackTrace(); } } }
ApsaraDB RDS for SQL Server
NoteReplace
#your-sqlserver-secret-name#
,<your-sqlserver-ip>
,<your-sqlserver-port>
, and<your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class SecretManagerJDBCSqlServerSample { public static void main(String[] args) throws Exception{ // Load the secret JDBC client. Class.forName("com.aliyun.kms.secretsmanager.MssqlSecretsManagerSimpleDriver"); Connection connect = null; try { connect = DriverManager.getConnection("secrets-manager:sqlserver://<your-sqlserver-ip>:<your-sqlserver-port>;databaseName=<your-database-name>", "#your-sqlserver-secret-name#", ""); } catch (SQLException e) { e.printStackTrace(); } } }
ApsaraDB RDS for PostgreSQL
NoteReplace
#your-postgresql-secret-name#
,<your-postgresql-ip>
,<your-postgresql-port>
, and<your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class SecretManagerJDBCPostgreSQLSample { public static void main(String[] args) throws Exception { // Load the secret JDBC client. Class.forName("com.aliyun.kms.secretsmanager.PostgreSQLSecretManagerSimpleDriver"); Connection connect = null; try { connect = DriverManager.getConnection("secrets-manager:postgresql://<your-postgresql-ip>:<your-postgresql-port>/<your-database-name>", "#your-postgresql-secret-name#", ""); } catch (SQLException e) { e.printStackTrace(); } } }
ApsaraDB RDS for MariaDB
NoteReplace
#your-mariadb-secret-name#
,<your-mariadb-ip>
,<your-mariadb-port>
, and<your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class SecretManagerJDBCMarialDBSample { public static void main(String[] args) throws Exception{ // Load the secret JDBC client. Class.forName("com.aliyun.kms.secretsmanager.MariaDBSecretManagerSimpleDriver"); Connection connect = null; try { connect = DriverManager.getConnection("secrets-manager:mariadb://<your-mariadb-ip>:<your-mariadb-port>/<your-database-name>", "#your-mariadb-secret-name#", ""); } catch (SQLException e) { e.printStackTrace(); } } }
Connect to a database by using a connection pool
Configure c3p0.user
, c3p0.driverClass
, and c3p0.jdbcUrl
in the c3p0 c3p0.properties configuration file. c3p0.user
specifies the name of the secret. c3p0.driverClass
specifies the name of the secret JDBC driver class. The vale of c3p0.jdbcUrl
must start with secrets-manager
.
ApsaraDB RDS for MySQL
NoteReplace
#your-mysql-secret-name#
,<your-mysql-ip>
,<your-mysql-port>
, and<your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.c3p0.user=#your-mysql-secret-name# c3p0.driverClass=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver c3p0.jdbcUrl=secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>
ApsaraDB RDS for SQL Server
NoteReplace
#your-sqlserver-secret-name#
,<your-sqlserver-ip>
,<your-sqlserver-port>
, and<your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.c3p0.user=#your-sqlserver-secret-name# c3p0.driverClass=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver c3p0.jdbcUrl=secrets-manager:sqlserver://<your-sqlserver-ip>:<your-sqlserver-port>/<your-database-name>
ApsaraDB RDS for PostgreSQL
NoteReplace
#your-postgresql-secret-name#
,<your-postgresql-ip>
,<your-postgresql-port>
, and<your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.c3p0.user=#your-postgresql-secret-name# c3p0.driverClass=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver c3p0.jdbcUrl=secrets-manager:postgresql://<your-postgresql-ip>:<your-postgresql-port>/<your-database-name>
ApsaraDB RDS for MariaDB
NoteReplace
#your-mariadb-secret-name#
,<your-mariadb-ip>
,<your-mariadb-port>
, and<your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.c3p0.user=#your-mariadb-secret-name# c3p0.driverClass=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver c3p0.jdbcUrl=secrets-manager:mariadb://<your-mariadb-ip>:<your-mariadb-port>/<your-database-name>
Connect to a database by using a data source
In this example, c3p0 ComboPooledDataSource and ApsaraDB RDS for MySQL are used. Add the following configuration to the Spring configuration file:
Replace #your-mysql-secret-name#
, <your-mysql-ip>
, <your-mysql-port>
, and <your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name="driverClass" value="com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver" />
<property name="user" value="#your-mysql-secret-name#" />
<property name="jdbcUrl" value="secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>" />
<property name="maxPoolSize" value="***" />
<property name="minPoolSize" value="***" />
<property name="initialPoolSize" value="***" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="dataSource" />
</bean>
Configure maxPoolSize, minPoolSize, and initialPoolSize based on your business requirements.
Connect to a database by using a Druid connection pool
In this example, ApsaraDB RDS for MySQL is used. You must modify the following properties in the configuration file.
Replace #your-mysql-secret-name#
, <your-mysql-ip>
, <your-mysql-port>
, and <your-database-name>
in the sample code with the actual secret name, server IP address of the database, server port number of the database, and name of the database.
properties configuration file
username=#your-mysql-secret-name# driverClassName=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver url=secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>
Bean configuration mode
Method 1: XML configuration file
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="username" value="${your-mysql-secret-name}" /> <property name="driverClassName" value="com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver" /> <property name="url" value="secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>" /> </bean>
Method 2: Property injection
Create a driver class to load database connection information in the application.
@Configuration public class DataConfig { @Value("${your-mysql-secret-name}") private String username; @Value("com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver") private String driverClassName; @Value("secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>") private String url; @Bean(name = "dataSource",initMethod = "init",destroyMethod = "close") public DruidDataSource dataSource(){ DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setUsername(username); druidDataSource.setDriverClassName(driverClassName); druidDataSource.setUrl(url); return druidDataSource; } }