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.
Step 1: Create an access credential
Scenario 1: Use shared gateways to retrieve secret values
Available networks are the Internet and virtual private clouds (VPCs). The following Resource Access Management (RAM)-based authentication methods are supported: RAM roles of Elastic Compute Service (ECS) instances, RamRoleArn, Security Token Service (STS) tokens, and AccessKey pairs. For more information, see Manage access credentials.
RAM role of an ECS instance
An Elastic Compute Service (ECS) instance Resource Access Management (RAM) role is a regular service role that is attached to ECS instances, and the principal is ECS. This allows the ECS instance to obtain STS tokens for temporary access, eliminating the need for AccessKey pairs when calling KMS OpenAPI operations.
Log on to the RAM console, and create an instance RAM role whose Principal Type is an Alibaba Cloud service.
Principal Type: Select Cloud Service.
Principal Name: Select Elastic Compute Service / ECS.
Grant the RAM role access to retrieve KMS secrets.
Method 1: Through identity-based policies
KMS provides system-defined permission policies that can be attached to RAM roles. For more information, see System policies for KMS. You can also create custom policies.
Method 2: Through resource-based policies
KMS supports resource-based policies, which allow you to set access permissions for keys and secrets. This lets you control which Alibaba Cloud accounts, RAM users, and RAM roles have permission to manage or use KMS keys and secrets. For more information, see Key policies and Secret policies.
Log on to the ECS console, and attach the instance RAM role to an ECS instance.
RamRoleArn
RAM users or cloud services can obtain temporary permissions by assuming roles instead of directly using long-term access keys, thereby reducing the risk of key leakage. For instance, in temporary data processing tasks, RAM users or cloud services can temporarily assume a role with a specific RamRoleArn. RamRoleArn is the ARN information of the RAM role. Once the task is completed, the role's permissions are revoked, further mitigating the risk of exposure.
Log on to the RAM console by using an Alibaba Cloud account or a RAM user who has administrative rights.
Grant the RAM role access to KMS. You have two methods to complete the grant.
Method 1: Through identity-based policies
KMS provides system-defined permission policies that can be attached to RAM roles. For more information, see System policies for KMS. You can also create custom policies.
Method 2: Through resource-based policies
KMS supports resource-based policies, which allow you to set access permissions for keys and secrets. This lets you control which Alibaba Cloud accounts, RAM users, and RAM roles have permission to manage or use KMS keys and secrets. For more information, see Key policies and Secret policies.
View the RamRoleArn about a RAM role.
The RamRoleArn follows the format
acs:ram::$accountID:role/$roleName
, where$accountID
is the Alibaba Cloud account and$roleName
is the RAM role name.
STS token
By using STS services, a temporary access credential can be issued to RAM users or RAM roles, allowing them to access KMS with permissions specified by the policy for a limited validity period. After the expiration period, the credential will automatically become invalid.
Log on to the RAM console by using an Alibaba Cloud account or a RAM user who has administrative rights.
Grant AliyunSTSAssumeRoleAccess permission to a RAM user or Grant AliyunSTSAssumeRoleAccess permission to a RAM role.
Grant the RAM user access to KMS. You have two methods to complete the grant.
Method 1: Through identity-based policies
KMS provides system-defined permission policies that can be attached to RAM users. For more information, see System policies for KMS. You can also create custom policies.
Method 2: Through resource-based policies
KMS supports resource-based policies, which allow you to set access permissions for keys and secrets. This lets you control which Alibaba Cloud accounts, RAM users, and RAM roles have permission to manage or use KMS keys and secrets. For more information, see Key policies and Secret policies.
Use the RAM user or RAM role to call the AssumeRole interface of the STS service to obtain temporary access credentials.
AccessKey pair
This section uses a RAM user's AccessKey pair as an example. Alibaba Cloud accounts have default administrator privileges for all resources, which cannot be modified. Because compromised AccessKeys risk significant security vulnerabilities, we strongly recommend against creating them for Alibaba Cloud accounts. Instead, create a RAM user solely for API access, generate its AccessKey, and implement the principle of least privilege.
Log on to the RAM console. In the left-side navigation pane, choose Identities > Users, and click on the desired RAM user.
In the Authentication tab, click Create AccessKey and follow the instructions.
Grant the RAM user access to retrieve KMS secrets.
Method 1: Through identity-based policies
KMS provides system-defined permission policies that can be attached to RAM users. For more information, see System policies for KMS. You can also create custom policies.
Method 2: Through resource-based policies
KMS supports resource-based policies, which allow you to set access permissions for keys and secrets. This lets you control which Alibaba Cloud accounts, RAM users, and RAM roles have permission to manage or use KMS keys and secrets. For more information, see Key policies and Secret policies.
Client key (not recommended)
For instructions, see the standard creation method in Create an application access point. When configurating parameters, ensure the following settings are correct:
When create network rules, select Public or VPC for Network Type.
When configure the scope of permission rules, select Shared KMS Gateway.
Scenario 2: Use dedicated gateways to retrieve secret values (not recommended)
Available networks are KMS VPCs, and available access credentials are client keys.
Method 1: Quick creation
Suitable for quick testing and development scenarios. This method uses a default permission policy that cannot be modified. Your application will have access to all keys and secrets in the specified KMS instance.
Method 2: Standard creation
Use this method to configure fine-grained access permissions for resources.
Method 1: Quick creation
Log on to the KMS console. In the top navigation bar, select a region. In the left-side navigation pane, click .
On the Application Access tab, click Create AAP. In the Create AAP panel, configure the parameters.
Parameter
Description
Mode
Select Quick Creation.
Scope (KMS Instance)
Select the KMS instance that you want to access.
Application Access Point Name
Enter the name of the AAP.
Authentication Method
The default value is ClientKey, which cannot be changed.
Default Permission Policy
The default value is
key/*
secret/*
, which cannot be changed. Your application can access all keys and secrets in the specified KMS instance.Click OK. The browser automatically downloads the client key that is created.
The client key contains Application Access Secret(ClientKeyContent) and Password. By default, Application Access Secret(ClientKeyContent) is saved in a file whose name is in the
clientKey_****.json
format. By default, Password is saved in a file whose name is in theclientKey_****_Password.txt
format.
Method 2: Standard creation
For detailed instructions, see Method 2: Standard creation. When configurating parameters, ensure the following settings are correct:
When create a network access rule, select Private for Network Type.
When configure the scope of permission policy, select the specified KMS Instance ID.
Step 2: Install the secret JDBC client
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. For more information about the installation and source code, visit aliyun-secretsmanager-jdbc.
Step 3: Use the secretsmanager.properties configuration file to initialize the secret JDBC client
Add the secretsmanager.properties configuration file to your project. The parameters vary based on the access credential that is used.
AccessKey pair
## 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
RAMRoleArn
## 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
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 token
## 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
Client key (shared gateway)
## The type of the access credential.
credentials_type=client_key
## The path of the client Key.
client_key_private_key_path=#your client key private key file path#
## 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 (dedicated gateway)
The cache_client_dkms_config_info parameter uses JSON array format. You can configure multiple KMS instances to improve service availability and disaster recovery capabilities. cache_client_dkms_config_info
cache_client_dkms_config_info
Method 1: Obtain the client key password from an environment variable
The configuration file content is:
cache_client_dkms_config_info=[{"regionId":"<your dkms regionId >","endpoint":"<your dkms endpoint>","passwordFromEnvVariable":"<YOUR_PASSWORD_ENV_VARIABLE>","clientKeyFile":"<your ClientKey file path>","ignoreSslCerts":false,"caFilePath":"<your CA certificate file path>"}]
With this method, you also need to save the content of the Client Key Password (ClientKeyPassword) to an environment variable. You can customize the variable name, and after configuration, replace
<YOUR_PASSWORD_ENV_VARIABLE>
with your variable name. Example:cache_client_dkms_config_info=[{"regionId":"cn-hangzhou","endpoint":"kst-hzz634e67d126u9p9****.cryptoservice.kms.aliyuncs.com","passwordFromEnvVariable":"passwordFromEnvVariable","clientKeyFile":"C:\RamSecretPlugin\src\main\resources\clientKey_KAAP.json","ignoreSslCerts":false,"caFilePath":"C:\RamSecretPlugin\src\main\resources\PrivateKmsCA_kst-hzz634e67d126u9p9****.pem"}]
Method 2: Obtain the client key password from a file
The default filename for the Client Key Password (ClientKeyPassword) after download is
clientKey_****_Password.txt
. You can rename the file, but you'll need to replace<your Client Key file path>
in the cache_client_dkms_config_info value with the new file path.The configuration file content is:
cache_client_dkms_config_info=[{"regionId":"<your dkms regionId >","endpoint":"<your dkms endpoint>","passwordFromFilePath":"< your password file path >","clientKeyFile":"<your Client Key file path>","ignoreSslCerts":false,"caFilePath":"<your CA certificate file path>"}]
Example:
cache_client_dkms_config_info=[{"regionId":"cn-hangzhou","endpoint":"kst-hzz634e67d126u9p9****.cryptoservice.kms.aliyuncs.com","passwordFromFilePath":"C:\RamSecretPlugin\src\main\resources\clientKeyPassword.txt","clientKeyFile":"C:\RamSecretPlugin\src\main\resources\clientKey_KAAP.json","ignoreSslCerts":false,"caFilePath":"C:\RamSecretPlugin\src\main\resources\PrivateKmsCA_kst-hzz634e67d126u9p9****.pem"}]
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 value 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; } }