Todos os produtos
Search
Central de documentação

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

Última atualização: Jun 26, 2026

Armazene as credenciais de instância do Tair (Redis OSS-compatible) no KMS para que sua aplicação recupere senhas dinamicamente via SDK, eliminando a necessidade de credenciais estáticas incorporadas ao código. Ative também a rotação automática de credenciais para reduzir o risco de vazamento.

Como funciona

Com credenciais de instância gerenciadas pelo KMS para instâncias do Tair (Redis OSS-compatible), sua aplicação não precisa mais de senhas estáticas. Um administrador crie uma credencial de instância no KMS, e a aplicação chama a operação GetSecretValue para recuperar a conta e a senha em tempo de execução.

Por exemplo, se o nome da credencial for username, o KMS crie as contas username e username_clone na instância. Essa abordagem de conta dupla oferece maior disponibilidade e segurança. Defina uma política de rotação no console do KMS. Por padrão, o KMS rotaciona as contas a cada 24 horas, alternando qual conta está ativa. Credenciais Redis/Tair.

Importante

Não modifique nem exclua senhas de contas gerenciadas pelo KMS no console do Tair (Redis OSS-compatible). Isso evita interrupções no serviço.

image

Limitações

  • Não é possível alterar a senha de uma conta gerenciada pelo KMS no console do Tair. Faça a rotação manualmente ou configure a rotação automática no console do KMS. Rotacionar credenciais Redis/Tair.

  • Não é possível exclua uma conta gerenciada pelo KMS no console do Tair. Exclua-a no console do KMS. Excluir credenciais Redis.

  • Não é possível modifique a descrição de uma conta gerenciada pelo KMS no console do Tair.

Pré-requisitos

  • Uma instância ECS capaz de se conectar à instância Tair. Este tópico utiliza Alibaba Cloud Linux 3.2104 LTS 64-bit com Java 1.8.0.

  • Caso utilize um usuário RAM ou uma função RAM para gerencie credenciais de instância, anexe a política de sistema AliyunKMSSecretAdminAccess ao usuário ou à função. Conceder permissões.

Procedimento

  1. Crie e ative uma instância KMS. Criar e ativar uma instância KMS.

    Selecione a mesma vpc da instância ECS ao criar a instância KMS.

    Se você já possui uma instância KMS, adicione a vpc da instância ECS a ela. Configure uma vpc.

  2. Crie um application access point (AAP). Criar um application access point.

    Após a criação, o navegador baixa o application identity credential content (ClientKeyContent, a JSON file) e o credential security token (ClientKeyPassword). Armazene-os em local seguro.

  3. Baixe o certificado CA da instância KMS na página Instance Management. Obter o certificado CA de uma instância KMS.

  4. Crie uma customer master key (CMK). Introdução ao gerenciamento de chaves.

  5. Crie uma credencial para a instância do Tair (Redis OSS-compatible). Criar uma credencial Redis/Tair.

  6. Escreva o código de teste em Java.

    1. Adicione as seguintes dependências Maven. A seção <build> empacota todas as dependências em um único 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. Escreva o código principal em KMSJedisTest.java.

      Nota

      Este exemplo armazena credenciais em cache por 600 segundos (configurável via setCredentialCacheTime) para evitar chamadas ao KMS a cada nova conexão. Recomenda-se um tempo de cache de pelo menos 10 minutos.

      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. Escreva o código para 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. Empacote o projeto inteiro em um arquivo JAR executando o seguinte comando: mvn package.

  7. Execute o JAR na instância ECS para conectar-se ao Tair.

    Sintaxe:

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

    Parâmetros:

    • kms-redis-jar-with-dependencies.jar: O JAR empacotado com todas as dependências.

    • kmsEndpoint: O endpoint vpc da instância KMS, disponível na página de detalhes da instância.

    • clientKeyFilePath: O arquivo JSON de credencial de identidade do AAP baixado no Passo 2.

    • clientKeyPass: O token de segurança da credencial (arquivo TXT) baixado no Passo 2.

    • caCertPath: O certificado CA da instância KMS (arquivo PEM) baixado no Passo 3.

    • secretName: O nome da credencial de instância criada no Passo 5.

    • redisHost: O endereço de conexão vpc e a porta, por exemplo, r-bp1g727yrai5yh.redis.rds.aliyuncs.com:6379.

    Exemplo:

    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

    Saída esperada em caso de conexão bem-sucedida:

    0
    OK
    1
    OK
    2
    OK
    3
    OK
    4
    OK
  8. Teste a rotação imediata de credenciais no console do KMS. Rotacionar credenciais Redis/Tair.

    A rotação alterna a conta ativa entre username e username_clone.

    Se a conexão da instância ECS permanecer estável, a rotação está funcionando corretamente.

    ...
    30
    OK
    31
    OK
    32
    OK
    33
    OK
  9. Execute um teste de switchover de alta disponibilidade (master-replica) na instância e monitore o cliente.

    A saída a seguir mostra uma desconexão transitória durante o switchover de alta disponibilidade, seguida de uma reconexão bem-sucedida após o KMS atualizar a credencial.

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

Referências