管理 IAM 身份验证

本页面介绍了 Memorystore for Redis 集群的 IAM 身份验证功能的常见任务。如需详细了解该功能,请参阅 IAM 身份验证简介

使用 IAM 身份验证创建实例

如需创建使用 IAM 身份验证的 Memorystore for Redis 集群实例,请运行 create 命令:

gcloud beta redis clusters create INSTANCE_ID --region=REGION_ID --network=NETWORK --shard-count=SHARD_COUNT --auth-mode=iam-auth

请替换以下内容:

  • INSTANCE_ID 是您正在创建的 Memorystore for Redis 集群实例的 ID。实例 ID 必须为 1 到 63 个字符,且只能使用小写字母、数字或连字符。并且必须以小写字母开头并以小写字母或数字结尾。

  • REGION_ID 是要将实例放置到的区域。

  • NETWORK 是用于创建实例的网络。它必须采用 projects/NETWORK_PROJECT_ID/global/networks/NETWORK_ID 格式。此处使用的网络 ID 必须与服务连接政策使用的网络 ID 一致。否则,create 操作将失败。如需了解详情,请参阅网络

  • SHARD_COUNT 用于确定您实例中 13 GB 的分片数量。分片计数决定了用于存储实例数据的总内存容量。如需详细了解实例规范,请参阅集群和分片规范

管理 IAM 身份验证的权限

为实例创建有限的 IAM 管理员角色

您可能需要创建一个可以修改实例连接 IAM 权限的角色,而无需授予完整的 IAM 管理员访问权限。为此,可以为“roles/redis.dbConnectionUser”角色创建受限 IAM 管理员。有关详情,请参阅创建受限 IAM 管理员

使用 IAM 授予对实例的访问权限

默认情况下,向主帐号授予 roles/redis.dbConnectionUser 角色可让主帐号访问项目中的所有实例。如需向项目中的部分资源授予访问权限,请为 roles/redis.dbConnectionUser 角色设置基于 IAM 资源的访问权限。有关详情,请参阅配置基于资源的访问权限

连接到使用 IAM 身份验证的实例

  1. 如果您还没有与 Redis 集群使用同一授权网络的 Compute Engine 虚拟机,请创建一个虚拟机并按照 Linux 虚拟机使用快速入门中的说明连接到该虚拟机。

  2. 通过 Compute Engine SSH 终端运行以下命令,在 Compute Engine 虚拟机上安装 redis-cli:

    sudo apt-get install redis-tools
    
  3. 运行以下命令以获取 IAM 用户的访问令牌:

    gcloud auth print-access-token
    
  4. 连接到实例的发现端点:

    redis-cli -h NETWORK_ADDRESS -p PORT -a ACCESS_TOKEN -c
    

    请替换以下内容:

    • NETWORK_ADDRESS 是实例的网络地址。如需查看网络地址,请参阅查看实例信息

    • PORT 是实例端口号。如需查看端口号,请参阅查看实例信息

    • ACCESS_TOKEN 是上一步中检索的 IAM 访问令牌。

  5. 运行 CLUSTER SHARDS 命令以查看集群拓扑。请记下该节点的 IP 地址和端口号。

  6. 运行以下命令,连接到您的所需节点:

    redis-cli -h NODE_IP_ADDRESS -p NODE_PORT -a ACCESS_TOKEN -c
    

    请替换以下内容:

    • NODE_IP_ADDRESS 是您在上一步中找到的节点 IP 地址。
    • NODE_PORT 是您在上一步中找到的节点的端口号。
  7. 运行 Redis SETGET 命令,验证您是否已与集群节点建立经过身份验证的连接。

  8. 完成与 Redis 实例的连接测试后,应考虑删除用于连接到 Redis 集群的 Compute Engine 虚拟机。这样做有助于避免系统向您的 Cloud Billing 帐号收取费用。

  9. 运行以下命令,使用 redis-cli 进行身份验证并连接到实例,注意将变量替换为适当的值:

    redis-cli -h NETWORK_ADDRESS -p PORT -a ACCESS_TOKEN -c
    

    请替换以下内容:

    • NETWORK_ADDRESS 是实例的网络地址。如需查看网络地址,请参阅查看实例信息

    • PORT 是实例端口号。如需查看端口号,请参阅查看实例信息

    • ACCESS_TOKEN 是上一步中检索的 IAM 访问令牌。

  10. 运行 Redis SETGET 命令以验证是否与实例建立了经过身份验证的连接。

  11. 完成与 Redis 集群的连接测试后,您应考虑删除用于连接到 Redis 集群的 Compute Engine 虚拟机。这样做有助于避免系统向您的 Cloud Billing 帐号收取费用。

自动检索访问令牌

建议您在应用中自动执行访问令牌检索操作,因为访问令牌的生命周期很短,无法轻松硬编码。

  1. (可选)为您的应用创建一个服务帐号(请参阅创建和管理服务帐号),如果您尚未创建。

    gcloud iam service-accounts create SA_NAME \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    请替换以下内容:

    • SA_NAME 是服务帐号的名称。
    • DESCRIPTION 是服务帐号的可选说明。
    • DISPLAY_NAME 是要在 Google Cloud 控制台中显示的服务帐号名称。
  2. 向您的服务帐号授予 redis.dbConnectionUser 权限。

    gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
    --role="redis.dbConnectionUser"
    

    请替换以下内容:

    • PROJECT_ID 是项目 ID。
    • SA_NAME 是服务帐号的名称。
    • ROLE_NAME 是角色名称,例如 roles/compute.osLogin
  3. 以给定服务帐号的身份对您的应用进行身份验证。如需了解详情,请参阅服务帐号

    如需查看代码示例,了解如何使用热门客户端库对应用进行身份验证,请参阅 IAM 身份验证客户端库代码示例

IAM 身份验证客户端库代码示例

本部分提供了客户端代码的示例,供您通过 Lettuce 客户端库使用 Memorystore 集群的 IAM 身份验证进行身份验证。

生菜


public void example() {
  String discoveryEndpointIp = "insert discovery endpoint ip"
  String discoveryEndpointPort = "insert discovery endpoint port"
  RedisCredentialsProvider provider =
     () ->
           Mono.just(RedisCredentials.just("default", retrieveAccessToken().toCharArray()));
  RedisURI redisUri =
     RedisURI.Builder.redis(discoveryEndpointIp, discoveryEndpointPort)
           .withAuthentication(provider)
           .build();
  ClientResources resources =
     DefaultClientResources.builder()
           .reconnectDelay(
              Delay.fullJitter(
                 Duration.ofMillis(100),
                 Duration.ofSeconds(5),
                 100,
                 TimeUnit.MILLISECONDS))
           .build();
  ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
     .enablePeriodicRefresh(1, TimeUnit.MINUTES)
     .enableAllAdaptiveRefreshTriggers()
     .dynamicRefreshSources(false)
     .closeStaleConnections(true)
     .build();

  SocketOptions socketOptions = SocketOptions.builder()
     .connectTimeout(Duration.ofSeconds(5))
     .keepAlive(true)
     .build();

  // Create Redis Cluster Client
  RedisClusterClient clusterClient = RedisClusterClient.create(resources, redisUri);
  clusterClient.setOptions(
     ClusterClientOptions.builder()
           .topologyRefreshOptions(topologyRefreshOptions)
           .socketOptions(socketOptions)
           .autoReconnect(true)
           .nodeFilter(
              it ->
                 !(it.is(RedisClusterNode.NodeFlag.FAIL)
                       || it.is(RedisClusterNode.NodeFlag.EVENTUAL_FAIL)
                       || it.is(RedisClusterNode.NodeFlag.NOADDR)))
           .validateClusterNodeMembership(false)
           .build());

  // Establish connection to Redis Cluster
  StatefulRedisClusterConnection connection = clusterClient.connect();
  // Retrieve synchronous Redis Cluster commands
  RedisAdvancedClusterCommands syncCommands = connection.sync();
  // Perform Redis operations
  syncCommands.set("key1", "value1");

  // Close the connection and shutdown the client
  connection.close();
  clusterClient.shutdown();
}