Simpan kredensial instans Tair (Redis OSS-compatible) di KMS agar aplikasi Anda dapat mengambil password secara dinamis melalui SDK, bukan menyematkan kredensial statis. Anda juga dapat mengaktifkan rotasi kredensial untuk mengurangi risiko kebocoran.
Cara kerja
Dengan kredensial yang dikelola oleh KMS untuk instans Tair (Redis OSS-compatible), aplikasi Anda tidak lagi memerlukan password statis. Administrator membuat kredensial instans di KMS, dan aplikasi memanggil operasi GetSecretValue untuk mengambil akun dan password saat waktu proses.
Sebagai contoh, jika nama kredensial adalah username, KMS membuat akun username dan username_clone pada instans tersebut. Pendekatan dua akun ini meningkatkan ketersediaan dan keamanan. Anda dapat mengatur kebijakan rotasi di Konsol KMS. Secara default, KMS merotasi akun setiap 24 jam dengan mengalihkan akun aktif. Kredensial Redis/Tair.
Jangan mengubah atau menghapus password akun yang dikelola oleh KMS di Konsol Tair (Redis OSS-compatible). Hal ini dapat menyebabkan gangguan layanan.
Batasan
-
Anda tidak dapat mengubah password akun yang dikelola oleh KMS di Konsol Tair. Lakukan rotasi secara manual atau konfigurasikan rotasi otomatis di Konsol KMS. Rotasi kredensial Redis/Tair.
-
Anda tidak dapat menghapus akun yang dikelola oleh KMS di Konsol Tair. Hapus akun tersebut di Konsol KMS. Hapus kredensial Redis.
-
Anda tidak dapat mengubah deskripsi akun yang dikelola oleh KMS di Konsol Tair.
Prasyarat
-
Instans ECS yang dapat terhubung ke instans Tair. Topik ini menggunakan Alibaba Cloud Linux 3.2104 LTS 64-bit dengan Java 1.8.0.
-
Jika Anda menggunakan RAM user atau RAM role untuk mengelola kredensial instans, sambungkan kebijakan sistem AliyunKMSSecretAdminAccess ke pengguna atau peran tersebut. Berikan izin.
Prosedur
-
Buat dan aktifkan instans KMS. Buat dan aktifkan instans KMS.
Pilih VPC yang sama dengan instans ECS saat membuat instans KMS.
Jika Anda sudah memiliki instans KMS, tambahkan VPC instans ECS ke dalamnya. Konfigurasikan VPC.
-
Buat titik akses aplikasi (AAP). Buat titik akses aplikasi.
Setelah pembuatan, browser akan mengunduh application identity credential content (ClientKeyContent, a JSON file) dan credential security token (ClientKeyPassword). Simpan keduanya secara aman.
-
Unduh sertifikat CA dari instans KMS dari halaman Instance Management. Dapatkan sertifikat CA instans KMS.
-
Buat customer master key (CMK). Memulai manajemen kunci.
-
Buat kredensial untuk instans Tair (Redis OSS-compatible). Buat kredensial Redis/Tair.
-
Tulis kode uji Java.
-
Tambahkan dependensi Maven berikut. Bagian <build> mengemas semua dependensi ke dalam satu file 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> -
Tulis kode utama dalam KMSJedisTest.java.
CatatanContoh ini menyimpan kredensial dalam cache selama 600 detik (dapat dikonfigurasi melalui setCredentialCacheTime) untuk menghindari pemanggilan KMS pada setiap koneksi baru. Durasi cache minimal 10 menit direkomendasikan.
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); } } } } -
Tulis kode untuk 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 } } -
Kemas seluruh proyek menjadi file JAR dengan menjalankan perintah berikut:
mvn package.
-
-
Jalankan file JAR pada instans ECS untuk terhubung ke Tair.
Sintaks:
java -jar <kms-redis-jar-with-dependencies.jar> <kmsEndpoint> <clientKeyFilePath> <clientKeyPass> <caCertPath> <secretName> <redisHost>Parameter:
-
kms-redis-jar-with-dependencies.jar: File JAR yang telah dikemas beserta semua dependensinya.
-
kmsEndpoint: Titik akhir VPC dari instans KMS, tersedia di halaman detail instans.
-
clientKeyFilePath: File JSON kredensial identitas AAP yang diunduh pada Langkah 2.
-
clientKeyPass: Token keamanan kredensial (file TXT) yang diunduh pada Langkah 2.
-
caCertPath: Sertifikat CA instans KMS (file PEM) yang diunduh pada Langkah 3.
-
secretName: Nama kredensial instans yang dibuat pada Langkah 5.
-
redisHost: Alamat koneksi VPC dan port, misalnya, r-bp1g727yrai5yh****.redis.rds.aliyuncs.com:6379.
Contoh:
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:6379Output yang diharapkan saat koneksi berhasil:
0 OK 1 OK 2 OK 3 OK 4 OK -
-
Uji rotasi kredensial segera di Konsol KMS. Rotasi kredensial Redis/Tair.
Rotasi mengalihkan akun aktif antara username dan username_clone.
Jika koneksi ECS tetap stabil, berarti rotasi berfungsi dengan benar.
... 30 OK 31 OK 32 OK 33 OK -
Lakukan uji alih bencana HA master-replika pada instans dan pantau klien.
Output berikut menunjukkan pemutusan sementara selama alih bencana HA, diikuti dengan koneksi ulang yang berhasil setelah KMS memperbarui kredensial.
138 OK 139 redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream. OK 142 OK 143 OK