View a markdown version of this page

以 IAM 進行身分驗證 - Amazon ElastiCache

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

以 IAM 進行身分驗證

概觀

透過 IAM 身分驗證,當您的快取設定為使用 Valkey 或 Redis OSS 第 7 版或更新版本時,您可以使用 AWS IAM 身分驗證 ElastiCache for Valkey 或 Redis OSS 的連線。這可讓您強化安全模型,並簡化許多管理安全任務。您也可以使用 IAM 身分驗證為個別 ElastiCache 快取和 ElastiCache 使用者設定精細的存取控制,並遵循最低權限許可原則。ElastiCache 的 IAM 身分驗證的運作方式是在 Valkey 或 Redis OSS AUTHHELLO命令中提供短期 IAM 身分驗證字符,而非長期 ElastiCache 使用者密碼。如需 IAM 身分驗證字符的詳細資訊,請參閱《 AWS 一般參考指南》中的 Signature 第 4 版簽署程序,以及下面的程式碼範例。

您可以使用 IAM 身分及其相關政策來進一步限制 Valkey 或 Redis OSS 存取。您也可以將使用者從聯合身分提供者的存取權直接授予 Valkey 或 Redis OSS 快取。

若要將 AWS IAM 與 ElastiCache 搭配使用,您必須先建立身分驗證模式設定為 IAM 的 ElastiCache 使用者。然後,您可以建立或重複使用 IAM 身分。IAM 身分需有相關政策,才能將 elasticache:Connect 動作授予 ElastiCache 快取和使用者。設定完成後,您可以使用 IAM 使用者或角色的 AWS 登入資料建立 IAM 身分驗證字符。最後,您需要在連線至快取時,在 Valkey 或 Redis OSS 用戶端中提供短期 IAM 身分驗證字符做為密碼。支援登入資料的 Valkey 或 Redis OSS 用戶端可以為每個新連線自動產生臨時登入資料。ElastiCache 將對啟用 IAM 的 ElastiCache 使用者的連線請求執行 IAM 身分驗證,並將使用 IAM 驗證連線請求。

限制

使用 IAM 身分驗證,會套用以下限制:

  • 使用 ElastiCache for Valkey 7.2 及更高版本或 Redis OSS 7.0 及更高版本時,可使用 IAM 身分驗證。

  • IAM 身分驗證需要在快取上啟用傳輸中加密 (TLS)。如需詳細資訊,請參閱ElastiCache 傳輸中加密 (TLS)

  • 針對已啟用 IAM 的 ElastiCache 使用者,使用者名稱和使用者 ID 屬性必須相同。

  • IAM 身分驗證字符的有效期限為 15 分鐘。如果使用過期的字符重新驗證連線,則會拒絕身分驗證請求。對於長期連線,我們建議使用支援登入資料提供者界面的 Valkey 或 Redis OSS 用戶端,在過期之前自動產生新的字符。

  • IAM 驗證的 ElastiCache for Valkey 或 Redis OSS 連線會在 12 小時後自動中斷連線。可以傳送包含新 IAM 身分驗證字符的 AUTHHELLO 命令,將連線再延長 12 小時。

  • MULTI/EXEC 或 Lua 指令碼區塊不支援 IAM 重新驗證 (AUTHHELLO命令)。不過,您可以在 IAM 驗證連線的 MULTI/EXEC 區塊內執行一般資料命令。

  • 目前,IAM 身分驗證支援下列全域條件內容金鑰:

    • 使用 IAM 身分驗證搭配無伺服器快取時,可支援 aws:VpcSourceIpaws:SourceVpcaws:SourceVpceaws:CurrentTimeaws:EpochTimeaws:ResourceTag/%s (來自相關聯的無伺服器快取和使用者)。

    • 使用 IAM 身分驗證搭配複寫群組時,可支援 aws:SourceIpaws:ResourceTag/%s (來自相關聯的複寫群組和使用者)。

    如需有關全域條件內容索引鍵的詳細資訊,請參閱《IAM 使用者指南》中的 AWS 全域條件內容索引鍵

注意

在快取建立時間,快取名稱會轉換為小寫。確保驗證程式碼以小寫形式提供快取名稱,以避免身分驗證錯誤。

設定

設定 IAM 身分驗證:

  1. 建立快取

    aws elasticache create-serverless-cache \ --serverless-cache-name cache-01 \ --description "ElastiCache IAM auth application" \ --engine redis
  2. 為您的角色建立如下所示的 IAM 信任政策文件,讓您的帳戶擔任新角色。將政策儲存到名為 trust-policy.json 的檔案。

    JSON
    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/my-application-role" }, "Action": "sts:AssumeRole" } ] }
    注意

    my-application-role 將 取代為需要連線至快取的 IAM 角色或使用者。使用最低權限的主體,而不是帳戶根來限制哪些身分可以擔任此角色。

  3. 建立 IAM 政策文件,如下所示。將政策儲存到名為 policy.json 的檔案。

    JSON
    { "Version":"2012-10-17", "Statement": [ { "Effect" : "Allow", "Action" : [ "elasticache:Connect" ], "Resource" : [ "arn:aws:elasticache:us-east-1:123456789012:serverlesscache:cache-01", "arn:aws:elasticache:us-east-1:123456789012:user:iam-user-01" ] } ] }
  4. 建立 IAM 角色。

    aws iam create-role \ --role-name "elasticache-iam-auth-app" \ --assume-role-policy-document file://trust-policy.json
  5. 建立 IAM 政策。

    aws iam create-policy \ --policy-name "elasticache-allow-all" \ --policy-document file://policy.json
  6. 將 IAM 政策連接至角色。

    aws iam attach-role-policy \ --role-name "elasticache-iam-auth-app" \ --policy-arn "arn:aws:iam::123456789012:policy/elasticache-allow-all"
  7. 建立已啟用 IAM 的新使用者。

    aws elasticache create-user \ --user-name iam-user-01 \ --user-id iam-user-01 \ --authentication-mode Type=iam \ --engine redis \ --access-string "on ~* +@all"
  8. 建立使用者群組並連接使用者。

    aws elasticache create-user-group \ --user-group-id iam-user-group-01 \ --engine redis \ --user-ids default iam-user-01 aws elasticache modify-serverless-cache \ --serverless-cache-name cache-01 \ --user-group-id iam-user-group-01

連接

以字符做為密碼進行連線

首先,您需要使用 AWS SigV4 預先簽章的請求,產生短期 IAM 身分驗證字符。之後,您在連線至 Valkey 或 Redis OSS 快取時提供 IAM 身分驗證字符做為密碼,如以下範例所示。

String userId = "insert user id"; String cacheName = "insert cache name"; boolean isServerless = true; 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 = DefaultCredentialsProvider.create(); // 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 ElastiCache with Redis OSS. IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userId, cacheName, region, isServerless); String iamAuthToken = iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.resolveCredentials()); // Construct Redis OSS URL with IAM Auth credentials provider RedisURI redisURI = RedisURI.builder() .withHost(host) .withPort(port) .withSsl(ssl) .withAuthentication(userId, iamAuthToken) .build(); // Create a new Lettuce Redis OSS client RedisClient client = RedisClient.create(redisURI); client.connect();

以下是 IAMAuthTokenRequest 的定義。

public class IAMAuthTokenRequest { private static final SdkHttpMethod REQUEST_METHOD = SdkHttpMethod.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 PARAM_RESOURCE_TYPE = "ResourceType"; private static final String RESOURCE_TYPE_SERVERLESS_CACHE = "ServerlessCache"; private static final String ACTION_NAME = "connect"; private static final String SERVICE_NAME = "elasticache"; private static final Duration TOKEN_EXPIRY_DURATION = Duration.ofSeconds(900); private final String userId; private final String cacheName; private final String region; private final boolean isServerless; public IAMAuthTokenRequest(String userId, String cacheName, String region, boolean isServerless) { this.userId = userId; this.cacheName = cacheName; this.region = region; this.isServerless = isServerless; } public String toSignedRequestUri(AwsCredentials credentials) { SdkHttpFullRequest request = getSignableRequest(); SdkHttpFullRequest signedRequest = sign(request, credentials); return signedRequest.getUri().toString().replace(REQUEST_PROTOCOL, ""); } private SdkHttpFullRequest getSignableRequest() { SdkHttpFullRequest.Builder builder = SdkHttpFullRequest.builder() .method(REQUEST_METHOD) .uri(getRequestUri()) .appendRawQueryParameter(PARAM_ACTION, ACTION_NAME) .appendRawQueryParameter(PARAM_USER, userId); if (isServerless) { builder.appendRawQueryParameter(PARAM_RESOURCE_TYPE, RESOURCE_TYPE_SERVERLESS_CACHE); } return builder.build(); } private URI getRequestUri() { return URI.create(String.format("%s%s/", REQUEST_PROTOCOL, cacheName)); } private SdkHttpFullRequest sign(SdkHttpFullRequest request, AwsCredentials credentials) { AwsV4HttpSigner signer = AwsV4HttpSigner.create(); SignedRequest signedRequest = signer.sign(r -> r.identity(credentials) .request(request) .putProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, SERVICE_NAME) .putProperty(AwsV4HttpSigner.REGION_NAME, region) .putProperty(AwsV4HttpSigner.AUTH_LOCATION, AwsV4HttpSigner.AuthLocation.QUERY_STRING) .putProperty(AwsV4HttpSigner.EXPIRATION_DURATION, TOKEN_EXPIRY_DURATION) .build() ); return (SdkHttpFullRequest) signedRequest.request(); } }

使用憑證提供者進行連線

以下程式碼說明如何使用 IAM 身分驗證憑證提供者向 ElastiCache 進行身分驗證。

String userId = "insert user id"; String cacheName = "insert cache name"; boolean isServerless = true; 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 = DefaultCredentialsProvider.create(); // Create an IAM authentication token request. Once this request is signed it can be used as an // IAM authentication token for ElastiCache with Redis OSS. IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userId, cacheName, region, isServerless); // Create a Redis OSS credentials provider using IAM credentials. RedisCredentialsProvider redisCredentialsProvider = new RedisIAMAuthCredentialsProvider( userId, iamAuthTokenRequest, awsCredentialsProvider); // Construct Redis OSS URL with IAM Auth credentials provider RedisURI redisURI = RedisURI.builder() .withHost(host) .withPort(port) .withSsl(ssl) .withAuthentication(redisCredentialsProvider) .build(); // Create a new Lettuce Redis OSS client RedisClient client = RedisClient.create(redisURI); client.connect();

以下是 Lettuce Redis OSS 用戶端的範例,該用戶端會在登入資料提供者中包裝 IAMAuthTokenRequest,以在需要時自動產生臨時登入資料。

public class RedisIAMAuthCredentialsProvider implements RedisCredentialsProvider { private static final long TOKEN_EXPIRY_SECONDS = 900; private final AwsCredentialsProvider awsCredentialsProvider; private final String userId; private final IAMAuthTokenRequest iamAuthTokenRequest; private final Supplier<String> iamAuthTokenSupplier; public RedisIAMAuthCredentialsProvider(String userId, IAMAuthTokenRequest iamAuthTokenRequest, AwsCredentialsProvider awsCredentialsProvider) { this.userId = userId; 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(userId, iamAuthTokenSupplier.get())); } private String getIamAuthToken() { return iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.resolveCredentials()); } }