基于适用于服务账户的RAM角色(RAM Roles for Service Accounts,简称RRSA)功能,可以在集群内实现Pod维度的OpenAPI权限隔离。本文主要介绍RRSA功能的使用方法。

前提条件

RRSA功能目前只支持1.22及以上版本的集群(即ACK标准版、ACK Pro版、ASK标准版和ASK Pro版)。

背景信息

ECS实例元数据包含了ECS实例在阿里云系统中的信息,您可以在运行中的实例内查看实例元数据,并基于实例元数据配置或管理实例。基于这个特性,Kubernetes集群内应用也可以通过实例元数据来获取节点RAM角色策略所生成的STS临时凭证,然后通过该临时凭证访问云资源OpenAPI。更多信息,请参见ECS实例元数据概述

1

ECS实例元数据无法满足多租场景下集群内应用Pod间的云资源访问权限隔离需求。对此,阿里云容器服务ACK联合RAM访问控制服务推出了适用于服务账户的RAM角色功能,旨在实现多租场景下集群内应用Pod间云资源访问权限的细粒度隔离。

阿里云容器服务ACK联合RAM访问控制服务一起推出了适用于服务账户的RAM角色功能。基于RRSA功能,您可以在集群内实现应用隔离的RAM角色功能。各个应用扮演独立的RAM角色并使用获取的临时凭证去访问云资源,以实现应用RAM权限最小化以及多租等场景下集群内应用Pod间云资源访问权限的细粒度隔离的需求。

关于ACK如何实现RRSA功能,请参见部署服务账户令牌卷投影OIDC角色SSO概览

3
整个功能用户侧视角的工作流程如下:
  1. 用户提交使用了服务账户令牌卷投影功能的应用Pod。
  2. 集群将为该应用Pod创建和挂载相应的服务账户OIDC Token文件。
  3. Pod内程序使用挂载的OIDC Token文件访问STS服务的AssumeRoleWithOIDC接口获取扮演指定RAM角色的临时凭证(需要事先创建OIDC身份提供商以及修改RAM角色配置允许Pod使用的服务账户扮演该RAM角色)。更多信息,请参见AssumeRoleWithOIDC
  4. Pod内程序使用获取到的临时凭证访问云资源OpenAPI。

启用RRSA功能

方式一:通过容器服务控制台开启

  1. 登录容器服务管理控制台
  2. 在控制台左侧导航栏中,单击集群
  3. 集群列表页面中,单击目标集群名称或者目标集群右侧操作列下的详情
  4. 在集群详情页面,单击基本信息页签,单击RRSA OIDC提供商URL右侧的启用RRSA
  5. 在弹出的启用RRSA对话框中,单击确定
    当集群状态由更新中变为运行中时,说明该集群的RRSA特性已变更完成,RRSA OIDC提供商URL右侧会显示OIDC提供商的URL链接。

方式二:通过命令行工具ack-ram-tool开启

您也可以使用命令行工具ack-ram-tool来启用RRSA功能,更多信息,请参见ack-ram-tool

当您为集群开启RRSA功能时,ACK将在后台执行如下操作:

  1. 自动创建一个集群专用的OIDC Issuer服务(这个服务托管在ACK侧,不需要您来运维)。更多信息,请参见OIDC Issuer
  2. 为您的集群开启服务账户令牌卷投影功能(如果您的集群在之前已开启服务账户令牌卷投影功能,此操作将使用上一步创建的OIDC Issuer配置覆盖您之前设置的service-account-issuer参数的值)。更多信息,请参见部署服务账户令牌卷投影
  3. 同时会在您的账号下创建一个使用该OIDC Issuer的RAM角色SSO身份提供商(名称为ack-rrsa-<cluster_id>,其中 <cluster_id>是您的集群ID)。更多信息,请参见管理OIDC身份提供商

使用RRSA功能

集群开启RRSA功能后,按照以下步骤来赋予集群内应用通过RRSA功能获取访问云资源OpenAPI的临时凭证的能力。

  1. 创建RAM角色。

    您需要为应用所使用的服务账户(Service Account)创建一个RAM角色。后续应用将获取一个扮演这个RAM角色的临时凭证。更多信息,请参见创建可信实体为阿里云账号的RAM角色

  2. 修改RAM角色信任策略。

    您需要修改RAM角色的信任策略,确保使用指定的服务账户的应用有权限获取一个扮演这个RAM角色的临时凭证。更多信息,请参见修改RAM角色的信任策略

    RAM角色信任策略内容示例如下,您也可以使用命令行工具ack-ram-tool通过自动化的方式配置这个策略。

    注意 需要替换如下字段:
    • <oidc_issuer_url>替换为当前集群的OIDC提供商URL,该URL可以在集群详情的基本信息页签获取。
    • <namespace>替换为应用所在的命名空间。
    • <service_account>替换为应用使用的服务账户。
    • <account_uid>替换为阿里云主账号UID。
    • <cluster_id>替换为ACK集群ID。
    {
      "Statement": [
        {
          "Action": "sts:AssumeRole",
          "Condition": {
            "StringEquals": {
              "oidc:aud": "sts.aliyuncs.com",
              "oidc:iss": "<oidc_issuer_url>",
              "oidc:sub": "system:serviceaccount:<namespace>:<service_account>"
            }
          },
          "Effect": "Allow",
          "Principal": {
            "Federated": [
              "acs:ram::<account_uid>:oidc-provider/ack-rrsa-<cluster_id>"
            ]
          }
        }
      ],
      "Version": "1"
    }
  3. 为RAM角色授权。

    您可以通过为这个RAM角色授权的方式,指定这个RAM角色可以访问的云资源。更多信息,请参见为RAM角色授权

  4. 部署应用。

    部署应用时,需要修改应用的模板内容,自动生成OIDC Token。具体操作,请参见部署服务账户令牌卷投影

    注意
    • audience字段的值必须是 sts.aliyuncs.com
    • expirationSeconds 的值必须小于43200(12小时),如果设置的值比该值大,实际的OIDC Token会使用12小时作为过期时间。

    应用模板示例:

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-rrsa
    spec:
      containers:
      - image: alpine:3.14
        command:
        - sh
        - -c
        - 'sleep inf'
        name: test
        volumeMounts:
        - mountPath: /var/run/secrets/tokens
          name: oidc-token
      serviceAccountName: build-robot
      volumes:
      - name: oidc-token     # 新增的配置项。
        projected:
          sources:
          - serviceAccountToken:
              path: oidc-token
              expirationSeconds: 7200    # oidc token过期时间(单位:秒)。
              audience: "sts.aliyuncs.com"

    此时,您的应用就可以使用容器内挂载的OIDC Token(上面示例中的/var/run/secrets/tokens/oidc-token文件内容)调用STS的AssumeRoleWithOIDC接口来获取一个扮演前面创建的RAM角色的STS临时凭证,然后使用临时凭证访问云资源OpenAPI。更多信息,请参见AssumeRoleWithOIDC

支持使用RRSA OIDC Token认证的阿里云官方SDK

目前部分阿里云官方SDK已经内置了对于使用RRSA OIDC Token进行OpenAPI认证的支持,支持此功能的SDK版本信息如下:

编程语言 支持认证的SDK版本 使用示例
Go Alibaba Cloud Credentials for Go 1.2.2及以上版本 GO SDK使用示例
Java Alibaba Cloud Credentials for Java 0.2.8及以上版本 Java SDK使用示例
Node.js和TypeScript Alibaba Cloud Credentials for TypeScript/Node.js 2.2.1及以上版本 Node.js和TypeScript使用示例