本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 驗證 IAM
概觀
使用IAM身分驗證時,當您的叢集設定為使用 Valkey 或 Redis 第 7 OSS版或更新版本時,您可以使用身分驗證與 MemoryDB AWS IAM 的連線。這可讓您強化安全模型,並簡化許多管理安全任務。透過IAM身分驗證,您可以為每個個別 MemoryDB 叢集和 MemoryDB 使用者設定精細存取控制,並遵循最低權限許可原則。IAM 在 或 命令中提供短期身分驗證權杖,而非長期的 MemoryDB 使用者密碼,即可進行 MemoryDB 身分驗證。 IAM MemoryDB AUTH
HELLO
如需有關IAM身分驗證權杖的詳細資訊,請參閱 AWS 一般參考指南中的簽章第 4 版簽署程序,以及下列程式碼範例。
您可以使用身分及其相關政策來進一步限制 Valkey IAM 或 Redis OSS的存取。您也可以將使用者從聯合身分提供者直接授予 MemoryDB 叢集的存取權。
若要搭配 MemoryDB 使用 AWS IAM ,您必須先建立身分驗證模式設定為 的 MemoryDB 使用者IAM,然後才能建立或重複使用IAM身分。IAM 身分需要相關聯的政策,才能將memorydb:Connect
動作授予 MemoryDB 叢集和 MemoryDB 使用者。設定完成後,您可以使用IAM使用者或角色的 AWS 憑證建立IAM身分驗證權杖。最後,您需要在連線至 MemoryDB 叢集節點時,在 Valkey 或 Redis OSS用戶端中提供短期IAM身分驗證權杖作為密碼。支援憑證提供者的用戶端可以為每個新連線自動產生臨時憑證。MemoryDB 將對IAM啟用 的 MemoryDB 使用者的連線請求執行IAM身分驗證,並將使用 驗證連線請求IAM。
限制
使用IAM身分驗證時,適用下列限制:
IAM 使用 Valkey 或 Redis OSS引擎 7.0 版或更新版本時,可以使用身分驗證。
IAM 驗證權杖的有效期為 15 分鐘。對於長時間連線,我們建議您使用支援憑證提供者介面的 Redis OSS用戶端。
經過IAM身分驗證的 MemoryDB 連線會在 12 小時後自動中斷連線。使用新的IAM身分驗證權杖傳送
AUTH
或HELLO
命令,可以延長連線 12 小時。IAM
MULTI EXEC
命令不支援身分驗證。目前,IAM身分驗證不支援所有全域條件內容金鑰。如需全域條件內容索引鍵的詳細資訊,請參閱 IAM 使用者指南中的AWS 全域條件內容索引鍵。
設定
若要設定IAM身分驗證:
建立叢集
aws memorydb create-cluster \ --cluster-name cluster-01 \ --description "MemoryDB IAM auth application" --node-type db.r6g.large \ --engine-version 7.0 \ --acl-name open-access
為您的角色建立IAM信任政策文件,允許您的帳戶擔任新角色,如下所示。將政策儲存到名為 trust-policy.json 的檔案。
{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "sts:AssumeRole" } }
建立IAM政策文件,如下所示。將政策儲存到名為 policy.json 的檔案。
{ "Version": "2012-10-17", "Statement": [ { "Effect" : "Allow", "Action" : [ "memorydb:connect" ], "Resource" : [ "arn:aws:memorydb:us-east-1:123456789012:cluster/cluster-01", "arn:aws:memorydb:us-east-1:123456789012:user/iam-user-01" ] } ] }
建立 IAM 角色。
aws iam create-role \ --role-name "memorydb-iam-auth-app" \ --assume-role-policy-document file://trust-policy.json
建立IAM政策。
aws iam create-policy \ --policy-name "memorydb-allow-all" \ --policy-document file://policy.json
將IAM政策連接至角色。
aws iam attach-role-policy \ --role-name "memorydb-iam-auth-app" \ --policy-arn "arn:aws:iam::123456789012:policy/memorydb-allow-all"
建立新的IAM啟用 的使用者。
aws memorydb create-user \ --user-name iam-user-01 \ --authentication-mode Type=iam \ --access-string "on ~* +@all"
建立 ACL並連接使用者。
aws memorydb create-acl \ --acl-name iam-acl-01 \ --user-names iam-user-01 aws memorydb update-cluster \ --cluster-name cluster-01 \ --acl-name iam-acl-01
連接
以字符做為密碼進行連線
您首先需要使用 AWS SigV4 預先簽署的請求 產生短期IAM身分驗證字符。之後,您在連線至 MemoryDB 叢集時提供IAM驗證權杖做為密碼,如以下範例所示。
String userName = "insert user name" String clusterName = "insert cluster name" String region = "insert region" // Create a default AWS Credentials provider. // This will look for AWS credentials defined in environment variables or system properties. AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain(); // Create an IAM authentication token request and signed it using the AWS credentials. // The pre-signed request URL is used as an IAM authentication token for MemoryDB. IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userName, clusterName, region); String iamAuthToken = iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.getCredentials()); // Construct URL with IAM Auth credentials provider RedisURI redisURI = RedisURI.builder() .withHost(host) .withPort(port) .withSsl(ssl) .withAuthentication(userName, iamAuthToken) .build(); // Create a new Lettuce client RedisClusterClient client = RedisClusterClient.create(redisURI); client.connect();
以下是 IAMAuthTokenRequest
的定義。
public class IAMAuthTokenRequest { private static final HttpMethodName REQUEST_METHOD = HttpMethodName.GET; private static final String REQUEST_PROTOCOL = "http://"; private static final String PARAM_ACTION = "Action"; private static final String PARAM_USER = "User"; private static final String ACTION_NAME = "connect"; private static final String SERVICE_NAME = "memorydb"; private static final long TOKEN_EXPIRY_SECONDS = 900; private final String userName; private final String clusterName; private final String region; public IAMAuthTokenRequest(String userName, String clusterName, String region) { this.userName = userName; this.clusterName = clusterName; this.region = region; } public String toSignedRequestUri(AWSCredentials credentials) throws URISyntaxException { Request<Void> request = getSignableRequest(); sign(request, credentials); return new URIBuilder(request.getEndpoint()) .addParameters(toNamedValuePair(request.getParameters())) .build() .toString() .replace(REQUEST_PROTOCOL, ""); } private <T> Request<T> getSignableRequest() { Request<T> request = new DefaultRequest<>(SERVICE_NAME); request.setHttpMethod(REQUEST_METHOD); request.setEndpoint(getRequestUri()); request.addParameters(PARAM_ACTION, Collections.singletonList(ACTION_NAME)); request.addParameters(PARAM_USER, Collections.singletonList(userName)); return request; } private URI getRequestUri() { return URI.create(String.format("%s%s/", REQUEST_PROTOCOL, clusterName)); } private <T> void sign(SignableRequest<T> request, AWSCredentials credentials) { AWS4Signer signer = new AWS4Signer(); signer.setRegionName(region); signer.setServiceName(SERVICE_NAME); DateTime dateTime = DateTime.now(); dateTime = dateTime.plus(Duration.standardSeconds(TOKEN_EXPIRY_SECONDS)); signer.presignRequest(request, credentials, dateTime.toDate()); } private static List<NameValuePair> toNamedValuePair(Map<String, List<String>> in) { return in.entrySet().stream() .map(e -> new BasicNameValuePair(e.getKey(), e.getValue().get(0))) .collect(Collectors.toList()); } }
使用憑證提供者進行連線
下列程式碼說明如何使用身分驗證憑證提供者來使用 MemoryDB 進行IAM身分驗證。
String userName = "insert user name" String clusterName = "insert cluster name" String region = "insert region" // Create a default AWS Credentials provider. // This will look for AWS credentials defined in environment variables or system properties. AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain(); // Create an IAM authentication token request. Once this request is signed it can be used as an // IAM authentication token for MemoryDB. IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userName, clusterName, region); // Create a credentials provider using IAM credentials. RedisCredentialsProvider redisCredentialsProvider = new RedisIAMAuthCredentialsProvider( userName, iamAuthTokenRequest, awsCredentialsProvider); // Construct URL with IAM Auth credentials provider RedisURI redisURI = RedisURI.builder() .withHost(host) .withPort(port) .withSsl(ssl) .withAuthentication(redisCredentialsProvider) .build(); // Create a new Lettuce cluster client RedisClusterClient client = RedisClusterClient.create(redisURI); client.connect();
以下是 Lettuce 叢集用戶端的範例,該用戶端會在憑證提供者IAMAuthTokenRequest中包裝 ,以在需要時自動產生臨時憑證。
public class RedisIAMAuthCredentialsProvider implements RedisCredentialsProvider { private static final long TOKEN_EXPIRY_SECONDS = 900; private final AWSCredentialsProvider awsCredentialsProvider; private final String userName; private final IAMAuthTokenRequest iamAuthTokenRequest; private final Supplier<String> iamAuthTokenSupplier; public RedisIAMAuthCredentialsProvider(String userName, IAMAuthTokenRequest iamAuthTokenRequest, AWSCredentialsProvider awsCredentialsProvider) { this.userName = userName; this.awsCredentialsProvider = awsCredentialsProvider; this.iamAuthTokenRequest = iamAuthTokenRequest; this.iamAuthTokenSupplier = Suppliers.memoizeWithExpiration(this::getIamAuthToken, TOKEN_EXPIRY_SECONDS, TimeUnit.SECONDS); } @Override public Mono<RedisCredentials> resolveCredentials() { return Mono.just(RedisCredentials.just(userName, iamAuthTokenSupplier.get())); } private String getIamAuthToken() { return iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.getCredentials()); }