All Products
Search
Document Center

Tair (Redis® OSS-Compatible):Use KMS to manage instance credentials

Last Updated:Jun 02, 2026

Store Tair (Redis OSS-compatible) instance credentials in KMS so your application retrieves passwords dynamically through the SDK instead of embedding static credentials. You can also enable credential rotation to reduce leak risk.

How it works

With KMS-managed credentials for Tair (Redis OSS-compatible) instances, your application no longer needs static passwords. An administrator creates an instance credential in KMS, and the application calls the GetSecretValue operation to retrieve the account and password at runtime.

For example, if the credential name is username, KMS creates both username and username_clone accounts on the instance. This dual-account approach provides higher availability and security. You can set a rotation policy in the KMS console. By default, KMS rotates accounts every 24 hours, switching which account is active. Redis/Tair credentials.

Important

Do not modify or delete KMS-managed account passwords in the Tair (Redis OSS-compatible) console. This prevents service disruptions.

image

Limitations

  • You cannot change a KMS-managed account password in the Tair console. Rotate it manually or configure automatic rotation in the KMS console. Rotate Redis/Tair credentials.

  • You cannot delete a KMS-managed account in the Tair console. Delete it in the KMS console instead. Delete Redis credentials.

  • You cannot modify the description of a KMS-managed account in the Tair console.

Prerequisites

  • An ECS instance that can connect to the Tair instance. This topic uses Alibaba Cloud Linux 3.2104 LTS 64-bit with Java 1.8.0.

  • If you use a RAM user or RAM role to manage instance credentials, attach the AliyunKMSSecretAdminAccess system policy to the user or role. Grant permissions.

Procedure

  1. Create and enable a KMS instance. Create and enable a KMS instance.

    Select the same VPC as the ECS instance when creating the KMS instance.

    If you already have a KMS instance, add the ECS instance VPC to it. Configure a VPC.

  2. Create an application access point (AAP). Create an application access point.

    After creation, the browser downloads the application identity credential content (ClientKeyContent, a JSON file) and the credential security token (ClientKeyPassword). Store these securely.

  3. Download the CA certificate of the KMS instance from the Instance Management page. Obtain the CA certificate of a KMS instance.

  4. Create a customer master key (CMK). Getting started with key management.

  5. Create a credential for the Tair (Redis OSS-compatible) instance. Create a Redis/Tair credential.

  6. Write Java test code.

    1. Add the following Maven dependencies. The <build> section packages all dependencies into a single JAR.

          <dependencies>
              <dependency>
                  <groupId>redis.clients</groupId>
                  <artifactId>jedis</artifactId>
                  <version>5.1.0</version>
              </dependency>
              <dependency>
                  <groupId>com.aliyun</groupId>
                  <artifactId>alibabacloud-dkms-gcs-sdk</artifactId>
                  <version>0.5.2</version>
              </dependency>
              <dependency>
                  <groupId>com.aliyun</groupId>
                  <artifactId>tea</artifactId>
                  <version>1.2.3</version>
              </dependency>
              <dependency>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-api</artifactId>
                  <version>1.7.10</version>
              </dependency>
              <dependency>
                  <groupId>ch.qos.logback</groupId>
                  <artifactId>logback-classic</artifactId>
                  <version>1.2.9</version>
              </dependency>
          </dependencies>
      
          <build>
              <plugins>
                  <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-assembly-plugin</artifactId>
                      <version>3.3.0</version>
                      <configuration>
                          <archive>
                              <manifest>
                                  <mainClass>
                                      com.aliyun.KMSJedisTest
                                  </mainClass>
                              </manifest>
                          </archive>
                          <descriptorRefs>
                              <descriptorRef>jar-with-dependencies</descriptorRef>
                          </descriptorRefs>
                      </configuration>
                      <executions>
                          <execution>
                              <id>assemble-all</id>
                              <phase>package</phase>
                              <goals>
                                  <goal>single</goal>
                              </goals>
                          </execution>
                      </executions>
                  </plugin>
                  <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-compiler-plugin</artifactId>
                      <configuration>
                          <source>1.8</source>
                          <target>1.8</target>
                      </configuration>
                  </plugin>
              </plugins>
          </build>
    2. Write the main code in KMSJedisTest.java.

      Note

      This example caches credentials for 600 seconds (configurable via setCredentialCacheTime) to avoid calling KMS on every new connection. A cache duration of at least 10 minutes is recommended.

      package com.aliyun;
      
      import java.time.Duration;
      
      import redis.clients.jedis.DefaultJedisClientConfig;
      import redis.clients.jedis.HostAndPort;
      import redis.clients.jedis.Jedis;
      import redis.clients.jedis.JedisPool;
      
      public class KMSJedisTest {
          public static void main(String[] args) throws Exception {
              if (args.length < 2) {
                  System.out.println(
                      "Please input kmsEndpoint, clientKeyFilePath, clientKeyPass, caCertPath, secretName, redisHost");
                  return;
              }
      
              String endpoint = args[0];
              String clientKeyFilePath = args[1];
              String clientKeyPass = args[2];
              String caCertPath = args[3];
              String secretName = args[4];
              KMSRedisCredentialsProvider kmsRedisCredentialsProvider = new KMSRedisCredentialsProvider(endpoint,
                  clientKeyFilePath, clientKeyPass, caCertPath, secretName);
              kmsRedisCredentialsProvider.setCredentialCacheTime(Duration.ofSeconds(10)); // Set the cache duration to prevent frequent requests to KMS.
      
              String redisHost = args[5];
              JedisPool jedisPool = new JedisPool(HostAndPort.from(redisHost),
                  DefaultJedisClientConfig.builder().credentialsProvider(kmsRedisCredentialsProvider).build());
      
              for (int i = 0; i < Integer.MAX_VALUE; i++) {
                  Thread.sleep(1000);
                  try (Jedis jedis = jedisPool.getResource()) {
                      System.out.println(jedis.set("" + i, "" + i));
                      System.out.println(jedis.get("" + i));
                  } catch (Exception e) {
                      System.out.println(e);
                  }
              }
          }
      }
      
    3. Write the code for KMSRedisCredentialsProvider.java.

      package com.aliyun;
      
      import java.time.Duration;
      import java.time.LocalDateTime;
      import java.time.format.DateTimeFormatter;
      
      import org.json.JSONObject;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import redis.clients.jedis.DefaultRedisCredentials;
      import redis.clients.jedis.RedisCredentials;
      import redis.clients.jedis.RedisCredentialsProvider;
      
      import com.aliyun.dkms.gcs.openapi.models.Config;
      import com.aliyun.dkms.gcs.sdk.Client;
      import com.aliyun.dkms.gcs.sdk.models.*;
      
      public class KMSRedisCredentialsProvider implements RedisCredentialsProvider {
          private static final Logger logger = LoggerFactory.getLogger(KMSRedisCredentialsProvider.class);
      
          private final String endpoint;
          private final String clientKeyFilePath;
          private final String clientKeyPass;
          private final String caCertPath;
          private final String secretName;
          private static Client client = null;
      
          // credential cache time
          private Duration credentialCacheTime = Duration.ofSeconds(600);
          private DefaultRedisCredentials cachedCredentials = null;
          private LocalDateTime credentialsExpiration = null;
      
          public KMSRedisCredentialsProvider(String endpoint, String clientKeyFilePath, String clientKeyPass,
              String caCertPath, String secretName) {
              this.endpoint = endpoint;
              this.clientKeyFilePath = clientKeyFilePath;
              this.clientKeyPass = clientKeyPass;
              this.caCertPath = caCertPath;
              this.secretName = secretName;
              createClientInstance(endpoint, clientKeyFilePath, clientKeyPass, caCertPath);
          }
      
          public void setCredentialCacheTime(Duration credentialCacheTime) {
              this.credentialCacheTime = credentialCacheTime;
          }
      
          private static synchronized void createClientInstance(String endpoint, String clientKeyFilePath,
              String clientKeyPass, String caCertPath) {
              if (client == null) {
                  try {
                      client = new Client(new Config()
                          .setProtocol("https")
                          .setEndpoint(endpoint)
                          .setCaFilePath(caCertPath)
                          .setClientKeyFile(clientKeyFilePath)
                          .setPassword(clientKeyPass));
                  } catch (Exception e) {
                      logger.error("Init kms client failed", e);
                      throw new RuntimeException(e);
                  }
              }
          }
      
          @Override
          public RedisCredentials get() {
              try {
                  LocalDateTime now = LocalDateTime.now();
                  // Check cache
                  if (cachedCredentials != null && now.isBefore(credentialsExpiration)) {
                      return cachedCredentials;
                  }
      
                  GetSecretValueRequest request = new GetSecretValueRequest().setSecretName(secretName);
                  GetSecretValueResponse getSecretValueResponse = client.getSecretValue(request);
                  logger.debug("Now: " + now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) +
                      ", getSecretValueRequest: " + request);
                  String secretData = getSecretValueResponse.getSecretData();
                  JSONObject secretObject = new JSONObject(secretData);
                  if (secretObject.get("AccountName") == null || secretObject.get("AccountPassword") == null) {
                      throw new IllegalArgumentException("secretData must contain AccountName and AccountPassword");
                  }
                  cachedCredentials = new DefaultRedisCredentials(secretObject.get("AccountName").toString(),
                      secretObject.get("AccountPassword").toString());
                  credentialsExpiration = now.plusSeconds(credentialCacheTime.getSeconds());
                  return cachedCredentials;
              } catch (Exception e) {
                  logger.error("get secret failed", e);
                  throw new RuntimeException(e);
              }
          }
      
          @Override
          public void prepare() {
              // do nothing
          }
      
          @Override
          public void cleanUp() {
              // do nothing
          }
      }
      
    4. Package the entire project into a JAR file by running the following command: mvn package.

  7. Run the JAR on the ECS instance to connect to Tair.

    Syntax:

    java -jar <kms-redis-jar-with-dependencies.jar> <kmsEndpoint> <clientKeyFilePath> <clientKeyPass> <caCertPath> <secretName> <redisHost>

    Parameters:

    • kms-redis-jar-with-dependencies.jar: The packaged JAR with all dependencies.

    • kmsEndpoint: The VPC endpoint of the KMS instance, available on the instance details page.

    • clientKeyFilePath: The AAP identity credential JSON file downloaded in Step 2.

    • clientKeyPass: The credential security token (TXT file) downloaded in Step 2.

    • caCertPath: The KMS instance CA certificate (PEM file) downloaded in Step 3.

    • secretName: The instance credential name created in Step 5.

    • redisHost: The VPC connection address and port, for example, r-bp1g727yrai5yh****.redis.rds.aliyuncs.com:6379.

    Example:

    java -jar kms-redis-samples-1.0-SNAPSHOT-jar-with-dependencies.jar kst-hzz6674e7fbw21x9x****.cryptoservice.kms.aliyuncs.com /root/clientKey_KAAP.6432ddc6-f23a-4d78-ac84-****4598206b.json 267d1****1cda4415058e1d72ec49e0a /root/PrivateKmsCA_kst-hzz6674e7fbw21x9x****.pem kms-redis r-bp1g727yrai5yh****.redis.rds.aliyuncs.com:6379

    Expected output on successful connection:

    0
    OK
    1
    OK
    2
    OK
    3
    OK
    4
    OK
  8. Test immediate credential rotation in the KMS console. Rotate Redis/Tair credentials.

    Rotation switches the active account between username and username_clone.

    If the ECS connection remains stable, rotation is working correctly.

    ...
    30
    OK
    31
    OK
    32
    OK
    33
    OK
  9. Perform a master-replica HA switchover test on the instance and monitor the client.

    The following output shows a transient disconnection during the HA switchover, followed by a successful reconnection after KMS updated the credential.

    138
    OK
    139
    redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream.
    OK
    142
    OK
    143
    OK

References