
# 在CCE集群中使用OIDC实现工作负载身份认证（旧版IAM）
工作负载身份认证（Workload Identity）允许集群中的工作负载模拟IAM用户来访问云服务，从而无需直接使用IAM账号的AK/SK等信息，降低安全风险。
本文档介绍如何在CCE中使用工作负载Identity。
![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/caution_3.0-zh-cn.png)
本文方案仅适用于对接旧版IAM。
#### 约束与限制
支持1.19.16及以上版本集群。
#### 使用流程
1. 在CCE侧获取集群Service Account Token的签名公钥，操作步骤请参见[步骤一：获取CCE集群的签名公钥]。
2. 在IAM创建身份提供商，操作步骤请参见[步骤二：配置身份提供商]。
3. 在工作负载中获取IAM Token模拟IAM用户访问云服务，操作步骤请参见[步骤三：使用工作负载Identity]。
 
#### 工作原理
1. 获取集群签发的公钥，将集群Token控制器注册为IAM身份提供商。
   - 集群默认的身份提供商为**https://kubernetes.default.svc.cluster.local**
   
   - 如果集群"概览 \> 连接信息"中开启了"OpenID Connect 提供商"功能，则可前往集群"配置中心 \> Kubernetes原生配置"中的"服务账户令牌发行者 (service-account-issuer)"配置获取身份提供商URL。
    
2. 请求Service Account生成对应的OIDC Token。
3. 部署应用Pod并挂载OIDC Token。
4. Pod内程序使用挂载的OIDC Token访问IAM获取临时的IAM Token。
5. Pod内程序使用IAM Token访问其他云服务资源。
图1工作原理   
![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002651404582.png "点击放大")
 #### 步骤一：获取CCE集群的签名公钥
1. 使用kubectl连接集群。
2. 执行如下命令获取公钥。 
   ```
   kubectl get --raw /openid/v1/jwks
   ```
   返回的结果即集群的公钥，回显结果示例如下：
   ```
   {"keys":[{"use":"sig","kty":"RSA","kid":"*****","alg":"RS256","n":"*****","e":"AQAB"}]}
   ```
   ![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
   请保存此JSON内容，后续配置身份提供商时需要使用。
   
   
 
 #### 步骤二：配置身份提供商
1. 登录IAM控制台，在左侧导航栏选择"身份提供商"，在右上角单击"创建身份提供商"，协议选择OpenID Connect，类型选择虚拟用户SSO，单击"确定"。 
   ![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002649970260.png "点击放大")
   
   
   
2. 在身份提供商列表中找到新增的身份提供商，在操作列单击"修改"修改身份提供商信息。 
   **访问方式** ：选择**编程访问**。
   **配置信息**
   - 身份提供商URL：集群默认的身份提供商为 **https://kubernetes.default.svc.cluster.local**
     如果集群"概览 \> 连接信息"中开启了"OpenID Connect 提供商"功能，则可前往集群"配置中心 \> Kubernetes原生配置"中的"服务账户令牌发行者 (service-account-issuer)"配置获取身份提供商URL。
     
   
   - 客户端ID：填写一个ID，后续创建容器时使用。
     ![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/caution_3.0-zh-cn.png)
     客户端ID不建议填写为纯数字。如果客户端ID为纯数字，编辑工作负载yaml文件时需要将纯数字的客户端ID使用英文双引号包裹。示例：如果客户端ID为123456789，yaml文件的客户端ID需要填写为："123456789"。
     
   
   - 签名公钥：CCE集群的jwks，获取方法请参见[步骤一：获取CCE集群的签名公钥]。
   
   
   ![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002649810380.png "点击放大")
   **身份转换规则**
   身份映射规则是将工作负载的ServiceAccount和IAM用户做映射。
   - 方式一：单击"创建规则"。填写用户名，选择用户组，关联到demo用户组（后续使用身份提供商ID访问云服务就具有demo用户组的权限）。此处属性必须是**sub，** 值的格式为：**system:serviceaccount:\<命名空间\>:\<ServiceAccount名称\>** 。填写完成后单击"确定"。
     ![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002649970276.png "点击放大")
     
   
   - 方式二：单击"编辑规则"，使用JSON格式编辑规则。样例如下，编辑完成后单击"确定"。
     ```
     [
     {
     "remote": [
     {
     "type": "sub"
     }
     ],
     "local": [
     {
     "user": {
     "name": "FederationUser"
     }
     }
     ]
     },
     {
     "local": [
     {
     "user": {
     "name": "test"
     }
     },
     {
     "group": {
     "name": "demo"
     }
     }
     ],
     "remote": [
     {
     "type": "sub",
     "any_one_of": [
     "system:serviceaccount:default:oidc-token"
     ]
     }
     ]
     }
     ]
     ```
     表1身份转换规则字段说明 
     | 字段                | 说明                                                     |
     |:---|:---|
     | remote.type       | 匹配传入的OIDC Token中的声明，必须为sub。                            |
     | remote.any_one_of | 格式为system:serviceaccount:\<命名空间\>:\<ServiceAccount名称\> |
     | local.user.name   | IAM用户名，本示例中为test。                                      |
     | local.group.name  | 权限适用的IAM用户组，本示例中为demo。                                 |
        
     
   
   
   
   
3. 单击"确定"。
 
 #### 步骤三：使用工作负载Identity
1. 创建ServiceAccount，此处ServiceAccount的名称需要与[步骤二：配置身份提供商]时填写的ServiceAccountName保持一致。
   
   1. 创建一个文件sa.yaml，文件内容如下。
      ```
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: oidc-token  # ServiceAccount的名称
      ```
      
   
   2. 运行以下命令创建ServiceAccount。
      ```
      kubectl apply -f sa.yaml
      ```
      
   
   
   
   
2. 在工作负载中挂载身份提供商，获取OIDC Token文件。 
   1. 创建一个文件deployment.yaml，文件内容如下。
      ```
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: nginx
            version: v1
        template:
          metadata:
            labels:
              app: nginx
              version: v1
          spec:
            containers:
            - name: container-1
              image: nginx:latest
              volumeMounts:
              - mountPath: "/var/run/secrets/tokens"     # 将Kubernetes生成的serviceAccountToken挂载到/var/run/secrets/tokens/oidc-token文件内
                name: oidc-token
            imagePullSecrets:
            - name: default-secret
            serviceAccountName: oidc-token      # 前面创建的ServiceAccount的名称
            volumes:
            - name: oidc-token
              projected:
                defaultMode: 420
                sources:
                - serviceAccountToken:
                    audience: client_id   # 此处取值必须为身份提供商的客户端ID
                    expirationSeconds: 7200       # 过期时间
                    path: oidc-token              # 路径名称，可自定义
      ```
      
   
   2. 运行以下命令创建工作负载。
      ```
      kubectl apply -f deployment.yaml
      ```
      
   
   
   
   
3. 创建完成后登录到容器中，/var/run/secrets/tokens/oidc-token文件内容就是Kubernetes生成的serviceAccountToken。 
   ![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
   当serviceAccountToken超过24小时或超过80%的过期时间时，kubelet会主动轮转serviceAccountToken。
   
   
4. 使用OIDC Token调用[获取联邦认证token(OpenID Connect ID token方式)](https://support.huaweicloud.com/api-iam/iam_13_0605.html)接口，响应消息头中X-Subject-Token字段即为IAM Token，从而使用IAM Token访问云服务。
   
   接口调用示例如下：
   ```
   curl -iv --location --request POST 'https://{{iam endpoint}}/v3.0/OS-AUTH/id-token/tokens' \
    --header 'X-Idp-Id: workload_identity' \
    --header 'Content-Type: application/json' \
    --data @token_body.json
   ```
   其中：
   - **{{iam endpoint}}** 为IAM服务的Endpoint，具体请参见[地区和终端节点](https://developer.huaweicloud.com/endpoint)。
   
   - **workload_identity** 即为身份提供商名称，与[步骤二：配置身份提供商]中配置的名称相同。
   
   - **token_body.json** 为本地文件，内容如下所示：
     ```
     { 
        "auth" : { 
          "id_token" : { 
            "id" : "eyJhbGciOiJSU..."
          }, 
          "scope": { 
            "project" : { 
              "id" : "46419baef4324...",
              "name" : ******
            } 
          } 
        } 
      }
     ```
     - $.auth.id_token.id：此处取值为容器中/var/run/secrets/tokens/oidc-token文件的内容。
     
     - $.auth.scope.project.id：项目ID。获取方式请参见[获取项目ID](https://support.huaweicloud.com/api-cce/cce_02_0341.html)。
     
     - $.auth.scope.project.name：项目名称，例如cn-north-4。
      
   
   
   
   
 
#### 常见问题
- **集群证书更新后， OIDC身份认证失效**
  在集群证书更新后，继续使用老证书会出现验签失败，需要更新集群公钥。
  **解决方案：**
  参考本文[步骤一]重新获取CCE集群的签名公钥，并参考[步骤二]更新IAM中的身份提供商信息中的签名公钥。
  
 
