

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 身份和访问管理
<a name="identity-and-access-management"></a>

**提示**  
 通过 Amazon EKS 研讨会@@ [探索](https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el)最佳实践。

 Id@@ [entity and Access Managem](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) ent (IAM) 是一项 AWS 服务，它执行两个基本功能：身份验证和授权。身份验证涉及身份验证，而授权则控制 AWS 资源可以执行的操作。在 AWS 中，资源可以是其他 AWS 服务（例如 EC2），也可以是 AWS [委托人](https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html#intro-structure-principal)（例如 I [AM 用户](https://docs.aws.amazon.com/IAM/latest/UserGuide/id.html#id_iam-users)或[角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id.html#id_iam-roles)）。管理允许资源执行的操作的规则以 [IAM 策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html)的形式表达。

## 控制 EKS 集群的访问权限
<a name="_controlling_access_to_eks_clusters"></a>

Kubernetes 项目支持各种不同的策略来验证对 kube-apiserver 服务的请求，例如不记名令牌、X.509 证书、OIDC 等。EKS 目前原生支持 [webhook 令牌身份验证](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication)、[服务账户令牌](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens)以及截至 2021 年 2 月 21 日的 OIDC 身份验证。

Webhook 身份验证策略调用一个 webhook 来验证不记名令牌。在 EKS 上，这些不记名令牌是在您运行`kubectl`命令时由 AWS CLI 或[aws-iam-authenticator](https://github.com/kubernetes-sigs/aws-iam-authenticator)客户端生成的。当你执行命令时，令牌会被传递给 kube-apiserver，kube-apiserver 会将其转发到身份验证 webhook。如果请求格式正确，则 webhook 会调用嵌入在令牌正文中的预签名 URL。此 URL 会验证请求的签名，并返回有关用户的信息，例如用户的账户、Arn 和 UserId kube-apiserver。

要手动生成身份验证令牌，请在终端窗口中键入以下命令：

```
aws eks get-token --cluster-name <cluster_name> --region <region>
```

输出应如下所示：

```
{
    "kind": "ExecCredential",
    "apiVersion": "client.authentication.k8s.io/v1alpha1",
    "spec": {},
    "status": {
        "expirationTimestamp": "2024-12-20T17:38:48Z",
        "token": "k8s-aws-v1.aHR0cHM6Ly9zdHMudXMtd2VzdC0yLmFtYXpvbmF3cy5jb20vP0FjdGlvbj1HZ...."
    }
}
```

您也可以通过编程方式获取代币。以下是用 Go 编写的示例：

```
package main

import (
  "fmt"
  "log"
  "sigs.k8s.io/aws-iam-authenticator/pkg/token"
)

func main()  {
  g, _ := token.NewGenerator(false, false)
  tk, err := g.Get("<cluster_name>")
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(tk)
}
```

输出应如下所示：

```
{
  "kind": "ExecCredential",
  "apiVersion": "client.authentication.k8s.io/v1alpha1",
  "spec": {},
  "status": {
    "expirationTimestamp": "2020-02-19T16:08:27Z",
    "token": "k8s-aws-v1.aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8_QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNSZYLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFKTkdSSUxLTlNSQzJXNVFBJTJGMjAyMDAyMTklMkZ1cy1lYXN0LTElMkZzdHMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDIwMDIxOVQxNTU0MjdaJlgtQW16LUV4cGlyZXM9NjAmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JTNCeC1rOHMtYXdzLWlkJlgtQW16LVNpZ25hdHVyZT0yMjBmOGYzNTg1ZTMyMGRkYjVlNjgzYTVjOWE0MDUzMDFhZDc2NTQ2ZjI0ZjI4MTExZmRhZDA5Y2Y2NDhhMzkz"
  }
}
```

每个标记以开头，`k8s-aws-v1.`后跟一个 base64 编码的字符串。解码后的字符串应类似于以下内容：

```
https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXJPFRILKNSRC2W5QA%2F20200219%2Fus-xxxx-1%2Fsts%2Faws4_request&X-Amz-Date=20200219T155427Z&X-Amz-Expires=60&X-Amz-SignedHeaders=host%3Bx-k8s-aws-id&X-Amz-Signature=XXXf8f3285e320ddb5e683a5c9a405301ad76546f24f28111fdad09cf648a393
```

该令牌由包含亚马逊凭证和签名的预签名 URL 组成。有关更多详细信息，请参阅 https://docs.aws.amazon.com/STS/ latest/APIReference/API \$1 GetCallerIdentity .html。

代币的存活时间 (TTL) 为 15 分钟，之后需要生成一个新代币。当您使用客户端时，会自动处理此问题`kubectl`，但是，如果您使用的是 Kubernetes 控制面板，则每次令牌到期时都需要生成新令牌并重新进行身份验证。

AWS IAM 服务对用户的身份进行身份验证后，kube-apiserver 就会读取`kube-system`命名空间`aws-auth` ConfigMap 中的内容，以确定要与该用户关联的 RBAC 组。用于在 `aws-auth` ConfigMap IAM 委托人（即 IAM 用户和角色）与 Kubernetes RBAC 组之间创建静态映射。可以在 Kub RoleBindings ernetes 中引用 RBAC 群组，或者。ClusterRoleBindings它们与 IAM 角色类似，因为它们定义了一组可以对 Kubernetes 资源（对象）集合执行的操作（动词）。

### CloudWatch 查询可帮助用户识别向全局 STS 端点发送请求的客户端
<a name="_cloudwatch_query_to_help_users_identify_clients_sending_requests_to_global_sts_endpoint"></a>

运行下面的 CloudWatch 查询以获取 sts 端点。如果 stsendpoint 等于 “sts.amazonaws.com”，则它是全局 STS 终端节点。如果 stsendpoint 等于 “sts. <region>.amazonaws.com”，那么它就是一个区域 STS 终端节点。

```
fields @timestamp, @message, @logStream, @log,stsendpoint
| filter @logStream like /authenticator/
| filter @message like /stsendpoint/
| sort @timestamp desc
| limit 10000
```

### 集群访问管理器
<a name="_cluster_access_manager"></a>

集群访问管理器现在是管理 AWS IAM 委托人对 Amazon EKS 集群的访问的首选方式，它是 AWS API 的一项功能，也是 EKS v1.23 及更高版本集群（新集群或现有集群）的可选功能。它简化了 AWS IAM 和 Kubernetes 之间的身份映射RBACs，无需在 AWS 和 Kubernetes 之间切换 APIs 或编辑访问管理，从而减少了`aws-auth` ConfigMap 运营开销，并有助于解决配置错误的问题。该工具还允许集群管理员撤销或完善自动授予用于创建集群的 AWS IAM 委托人的`cluster-admin`权限。

此 API 依赖于两个概念：
+  **访问条目：**直接关联到允许向 Amazon EKS 集群进行身份验证的 AWS IAM 委托人（用户或角色）的集群身份。
+  **访问策略：**是 Amazon EKS 的特定策略，它为访问条目提供在 Amazon EKS 集群中执行操作的授权。

在启动时，Amazon EKS 仅支持预定义策略和 AWS 托管策略。访问策略不是 IAM 实体，由 Amazon EKS 定义和管理。

集群访问管理器允许将上游 RBAC 与支持允许和通过（但不拒绝）有关 API 服务器请求的 Kubernetes AuthZ 决策的访问策略相结合。当上游 RBAC 和 Amazon EKS 授权机构都无法确定请求评估的结果时，就会做出拒绝决定。

借助此功能，Amazon EKS 支持三种身份验证模式：

1.  `CONFIG_MAP`继续仅使用`aws-auth`配置地图。

1.  `API_AND_CONFIG_MAP`从 EKS Access Entry 和 ConfigMa `aws-auth` p 中获取经过身份验证的 IAM 委托人，优先考虑访问条目 APIs 。非常适合将现有`aws-auth`权限迁移到访问条目。

1.  `API`完全依赖 EKS Access Entr APIs y。这是新**推荐的方法**。

首先，集群管理员可以创建或更新 Amazon EKS 集群，将首选身份验证设置为`API_AND_CONFIG_MAP`或`API`方法，并定义访问条目以授予所需的 AWS IAM 委托人访问权限。

```
$ aws eks create-cluster \
    --name <CLUSTER_NAME> \
    --role-arn <CLUSTER_ROLE_ARN> \
    --resources-vpc-config subnetIds=<value>,endpointPublicAccess=true,endpointPrivateAccess=true \
    --logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}' \
    --access-config authenticationMode=API_AND_CONFIG_MAP,bootstrapClusterCreatorAdminPermissions=false
```

上面的命令是在没有集群创建者管理员权限的情况下创建 Amazon EKS 集群的示例。

可以使用命令更新 Amazon EKS 集群配置以启用 A `API` uthenticationMod `update-cluster-config` e，要使用该命令在现有集群上执行此操作，`CONFIG_MAP`则必须先更新到，`API_AND_CONFIG_MAP`然后再更新到。`API`**这些操作无法恢复**，这意味着无法从或切换`API`到`API_AND_CONFIG_MAP`或`CONFIG_MAP`，也无法从切换`API_AND_CONFIG_MAP`到`CONFIG_MAP`。

```
$ aws eks update-cluster-config \
    --name <CLUSTER_NAME> \
    --access-config authenticationMode=API
```

API 支持添加和撤消对集群的访问权限以及验证指定集群的现有访问策略和访问条目的命令。创建的默认策略是为了匹配 KubernetesRBACs ，如下所示。


| EKS 访问政策 | Kubernetes RBAC | 
| --- | --- | 
|  Amazon EKSCluster AdminPolicy  |  集群管理员  | 
|  亚马逊EKSAdmin政策  |  admin  | 
|  亚马逊EKSEdit政策  |  编辑  | 
|  亚马逊EKSView政策  |  查看  | 

```
$ aws eks list-access-policies
{
    "accessPolicies": [
        {
            "name": "AmazonEKSAdminPolicy",
            "arn": "arn:aws:eks::aws:cluster-access-policy/AmazonEKSAdminPolicy"
        },
        {
            "name": "AmazonEKSClusterAdminPolicy",
            "arn": "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy"
        },
        {
            "name": "AmazonEKSEditPolicy",
            "arn": "arn:aws:eks::aws:cluster-access-policy/AmazonEKSEditPolicy"
        },
        {
            "name": "AmazonEKSViewPolicy",
            "arn": "arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy"
        }
    ]
}

$ aws eks list-access-entries --cluster-name <CLUSTER_NAME>

{
    "accessEntries": []
}
```

在没有集群创建者管理员权限的情况下创建集群时，没有访问条目可用，这是默认情况下创建的唯一条目。

### `aws-auth` ConfigMap *（已弃用*）
<a name="_the_aws_auth_configmap_deprecated"></a>

Kubernetes 与 AWS 身份验证集成的一种方法是通过 `aws-auth` ConfigMap，它位于命名空间中。`kube-system`它负责将 AWS IAM 身份（用户、群组和角色）身份验证映射到 Kubernetes 基于角色的访问控制 (RBAC) 授权。`aws-auth` ConfigMap 是在您的 Amazon EKS 集群的预配置阶段自动创建的。它最初是为了允许节点加入您的集群而创建的，但如前所述，您也可以使用它 ConfigMap 来添加对 IAM 委托人的 RBACs 访问权限。

要检查您的集群 `aws-auth` ConfigMap，您可以使用以下命令。

```
kubectl -n kube-system get configmap aws-auth -o yaml
```

这是的默认配置示例`aws-auth`ConfigMap。

```
apiVersion: v1
data:
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      - system:node-proxier
      rolearn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/kube-system-<SELF_GENERATED_UUID>
      username: system:node:{{SessionName}}
kind: ConfigMap
metadata:
  creationTimestamp: "2023-10-22T18:19:30Z"
  name: aws-auth
  namespace: kube-system
```

它的主会话位于`mapRoles`区块下方`data`，它基本上由 3 个参数组成。 ConfigMap
+  **群组：**要将 IAM 角色映射 group/groups 到的 Kubernetes。这可以是默认群组，也可以是或中指定的自定义群组`rolebinding`。`clusterrolebinding`在上面的例子中，我们只声明了系统组。
+  **rolearn：**使用以下格式将 AWS IAM 角色的 ARN 映射到 Kubernetes 群组/群组添加。`arn:<PARTITION>:iam::<AWS_ACCOUNT_ID>:role/role-name`
+  **用户名：**Kubernetes 中要映射到 AWS IAM 角色的用户名。这可以是任何自定义名称。

也可以映射 AWS IAM 用户的权限，`data`在下面为`mapUsers`替换 userarn 的 **rolearn** **参数定义一个新的配置块，但作为**最佳实践**，始终建议用户**改为使用它。`aws-auth` ConfigMap `mapRoles`

要管理权限，您可以编辑`aws-auth` ConfigMap 添加或移除对 Amazon EKS 集群的访问权限。尽管可以`aws-auth` ConfigMap 手动编辑，但建议使用诸如此类的工具，因为这是一个非常敏感的配置`eksctl`，不准确的配置可能会将您锁定在 Amazon EKS 集群之外。有关更多详细信息，请查看 ConfigMap下面的 “[使用工具对 aws-auth 进行更改](https://docs.aws.amazon.com/eks/latest/best-practices/identity-and-access-management.html#_cluster_access_recommendations)” 小节。

### 与 ConfigMap基于基础的访问管理相比的优势
<a name="_benefits_over_configmap_based_access_management"></a>

1.  **降低配置错误的风险**：基于 API 的直接管理可消除与手动编辑相关的常见错误。 ConfigMap 这有助于防止意外删除或语法错误，这些错误可能会将用户锁定在集群之外。

1.  **增强的最低权限原则**：不再需要集群创建者身份中的集群管理员权限，并允许进行更精细和适当的权限分配。您可以选择为破碎玻璃用例添加此权限。

1.  **增强的安全模型**：在应用访问条目之前提供对访问条目的内置验证。此外，还提供与 AWS IAM 更紧密的集成以进行身份验证。

1.  **简化操作**：通过 AWS 原生工具提供更直观的权限管理方式。

## 集群访问建议
<a name="_cluster_access_recommendations"></a>

### 将 IAM 身份中心与 CAM API 相结合
<a name="_combine_iam_identity_center_with_cam_api"></a>
+  **简化管理**：通过将集群访问管理 API 与 IAM Identity Center 配合使用，管理员可以管理 EKS 集群访问权限以及其他 AWS 服务，从而减少了在不同界面之间切换或 ConfigMaps 手动编辑的需求。
+ 使用访问条目管理集群外的 IAM 主体的 Kubernetes 权限。您可以使用 EKS API、AWS 命令行界面、AWS、AWS 和 AWS SDKs 管理控制台来添加和管理对集群的访问权限。 CloudFormation这意味着您可以使用与创建集群相同的工具来管理用户。
+ 利用[本示例](https://github.com/aws-ia/terraform-aws-eks-blueprints/tree/main/patterns/sso-iam-identity-center)中演示的自动化来部署以 AWS IAM 身份中心作为身份提供商、将 CAM API 作为入口点的集群。
+ 可以通过访问条目和访问策略将 Kubernetes 用户或群组映射到与 SSO 身份关联的 IAM 委托人，从而应用精细的 Kubernetes 权限。
+ 首先，请按照[更改身份验证模式使用访问条目](https://docs.aws.amazon.com/eks/latest/userguide/setting-up-access-entries.html#access-entries-setup-console)，然后按照[迁移现有的 aws-auth ConfigMap 条目来访问条目](https://docs.aws.amazon.com/eks/latest/userguide/migrating-access-entries.html)。

### 将 EKS 集群终端节点设为私有
<a name="_make_the_eks_cluster_endpoint_private"></a>

默认情况下，当您配置 EKS 集群时，API 集群终端节点设置为公用，即可以从互联网进行访问。尽管可以从互联网访问，但终端节点仍然被认为是安全的，因为它要求所有 API 请求都必须通过 IAM 进行身份验证，然后由 Kubernetes RBAC 授权。也就是说，如果您的公司安全策略要求您限制从 Internet 访问 API 或禁止您在集群 VPC 之外路由流量，则您可以：
+ 将 EKS 集群终端节点配置为私有终端节点。有关此主题的更多信息，请参阅[修改集群终端节点访问权限](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html)。
+ 将集群终端节点保持为公用状态，并指定哪些 CIDR 块可以与集群终端节点通信。这些区块实际上是一组被列入白名单的公有 IP 地址，允许访问集群终端节点。
+ 使用一组列入白名单的 CIDR 块配置公共访问并将私有终端节点访问权限设置为已启用。这将允许来自特定范围的公共群体的公共访问， IPs 同时强制 kubelets（工作程序）和 Kubernetes API 之间的所有网络流量都通过跨账户，ENIs 这些跨账户在配置控制平面时会配置到集群 VPC 中。

### 请勿使用服务帐号令牌进行身份验证
<a name="_dont_use_a_service_account_token_for_authentication"></a>

服务帐号令牌是一种长期存在的静态凭证。如果该令牌遭到入侵、丢失或被盗，攻击者可能能够执行与该令牌相关的所有操作，直到服务帐户被删除。有时，对于必须从集群外部使用 Kubernetes API 的应用程序，例如 CI/CD 管道应用程序，您可能需要允许例外。如果此类应用程序在 AWS 基础设施（如 EC2 实例）上运行，请考虑使用实例配置文件并将其映射到 Kubernetes RBAC 角色。

### 采用 AWS 资源的最低特权访问权限
<a name="_employ_least_privileged_access_to_aws_resources"></a>

IAM 用户无需获得 AWS 资源的权限即可访问 Kubernetes API。如果您需要授予 IAM 用户访问 EKS 集群的权限，请在中`aws-auth` ConfigMap 为该用户创建一个映射到特定 Kubernetes RBAC 组的条目。

### 从集群创建者主体中移除集群管理员权限
<a name="iam-cluster-creator"></a>

默认情况下，Amazon EKS 集群是使用绑定到集群创建者主体的永久`cluster-admin`权限创建的。使用集群访问管理器 API，在使用`API_AND_CONFIG_MAP`或`API`身份验证模式时`false`，无需将此权限设置为，`--access-config bootstrapClusterCreatorAdminPermissions`即可创建集群。撤消此访问权限被认为是最佳实践，可以避免对集群配置进行任何不必要的更改。撤消此访问权限的过程与撤消对集群的任何其他访问权限的过程相同。

API 允许您灵活地仅解除 IAM 委托人与访问策略的关联，在本例中`AmazonEKSClusterAdminPolicy`为。

```
$ aws eks list-associated-access-policies \
    --cluster-name <CLUSTER_NAME> \
    --principal-arn <IAM_PRINCIPAL_ARN>

$ aws eks disassociate-access-policy --cluster-name <CLUSTER_NAME> \
    --principal-arn <IAM_PRINCIPAL_ARN. \
    --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy
```

或者完全删除与该`cluster-admin`权限关联的访问条目。

```
$ aws eks list-access-entries --cluster-name <CLUSTER_NAME>

{
    "accessEntries": []
}

$ aws eks delete-access-entry --cluster-name <CLUSTER_NAME> \
  --principal-arn <IAM_PRINCIPAL_ARN>
```

在事件、紧急情况或无法访问集群的情况下，如果需要，可以再次授予此访问权限。

如果集群仍配置了`CONFIG_MAP`身份验证方法，则应通过向所有其他用户授予访问集群的权限 `aws-auth` ConfigMap，配置完成后 `aws-auth` ConfigMap ，可以删除分配给创建集群的实体的角色，并且只能在发生事件、紧急情况或破碎情形，或者群集损坏而无法访问集群时才可以删除并重新创建。`aws-auth` ConfigMap 这在生产集群中可能特别有用。

### 当多个用户需要相同的集群访问权限时，请使用 IAM 角色
<a name="_use_iam_roles_when_multiple_users_need_identical_access_to_the_cluster"></a>

与其为每个 IAM 用户创建条目，不如允许这些用户担任 IAM 角色并将该角色映射到 Kubernetes RBAC 群组。这将更易于维护，尤其是在需要访问权限的用户数量增加的情况下。

**重要**  
访问映射为 IAM 实体的 EKS 集群时 `aws-auth` ConfigMap，所描述的用户名会记录在 Kubernetes 审计日志的用户字段中。如果您使用的是 IAM 角色，则不会记录担任该角色的实际用户，也无法对其进行审计。

如果仍使用 `aws-auth` ConfigMap 作为身份验证方法，则在向 IAM 角色分配 K8s RBAC 权限时，应在用户名中包含\$1 \$1\$1SessionName\$1\$1。这样，审核日志将记录会话名称，这样您就可以跟踪实际用户是谁担任此角色以及日 CloudTrail 志。

```
- rolearn: arn:aws:iam::XXXXXXXXXXXX:role/testRole
  username: testRole:{{SessionName}}
  groups:
    - system:masters
```

在 Kubernetes 1.20 及更高版本中，不再需要进行此更改，因为`user.extra.sessionName.0`此更改已添加到 Kubernetes 审计日志中。

### 创建时使用最低特权访问权限 RoleBindings 和 ClusterRoleBindings
<a name="_employ_least_privileged_access_when_creating_rolebindings_and_clusterrolebindings"></a>

就像前面关于授予 AWS 资源访问权限的观点一样，RoleBindings 并且 ClusterRoleBindings 应仅包括执行特定功能所需的权限集。除非绝对必要， ClusterRoles 否则请避免`["*"]`在角色中使用。如果你不确定要分配什么权限，可以考虑使用像 a [udit2rbac 这样的工具，根据在 Kubernetes 审计](https://github.com/liggitt/audit2rbac)日志中观察到的 API 调用自动生成角色和绑定。

### 使用自动流程创建集群
<a name="_create_cluster_using_an_automated_process"></a>

如前面的步骤所示，在创建 Amazon EKS 集群时，如果不使用使用`API_AND_CONFIG_MAP`或`API`身份验证模式，并且不选择向集群创建者委派`cluster-admin`权限，则在集群的 RBAC 配置中，IAM 实体用户或角色（例如创建集群的联合用户）将自动获得`system:masters`权限。[即使是移除此权限的最佳实践，如本文所述，如果使用`CONFIG_MAP`身份验证方法 `aws-auth` ConfigMap，则无法撤消此访问权限。](#iam-cluster-creator)因此，最好使用与专用 IAM 角色绑定的基础设施自动化管道创建集群，其他用户或实体不具备任何权限，并定期审计该角色的权限、策略以及有权触发管道的人员。此外，不应使用此角色在集群上执行例行操作，而应专门用于由管道触发的集群级别操作，例如，通过 SCM 代码更改触发。

### 使用专用 IAM 角色创建集群
<a name="_create_the_cluster_with_a_dedicated_iam_role"></a>

创建 Amazon EKS 集群时，会自动向 IAM 实体用户或角色（例如创建集群的联合用户）授予该集群的 RBAC `system:masters` 配置中的权限。此访问权限无法删除，也不能通过进行管理`aws-auth` ConfigMap。因此，最好创建具有专用 IAM 角色的集群，并定期审计谁可以担任此角色。不应使用此角色在群集上执行例行操作，而是应为此向其他用户授予访问群集`aws-auth` ConfigMap 的权限。配置完成后，应保护该角色，并且仅在临时提升的权限模式下使用/break glass，以其他方式无法访问集群。`aws-auth` ConfigMap 这在未配置直接用户访问权限的集群中特别有用。

### 定期审核对集群的访问权限
<a name="_regularly_audit_access_to_the_cluster"></a>

谁需要访问权限可能会随着时间的推移而发生变化。计划定期审计，`aws-auth` ConfigMap 以查看谁获得了访问权限以及他们被分配了哪些权限。您还可以使用开源工具（例如 [kubectl-who-can](https://github.com/aquasecurity/kubectl-who-can)，或 [rbac-lookup](https://github.com/FairwindsOps/rbac-lookup)）来检查绑定到特定服务帐号、用户或群组的角色。当我们进入[审计](auditing-and-logging.md)部分时，我们将进一步探讨这个话题。其他想法可以在NCC集团的这[篇文章](https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2019/august/tools-and-methods-for-auditing-kubernetes-rbac-policies/?mkt_tok=eyJpIjoiWWpGa056SXlNV1E0WWpRNSIsInQiOiJBT1hyUTRHYkg1TGxBV0hTZnRibDAyRUZ0VzBxbndnRzNGbTAxZzI0WmFHckJJbWlKdE5WWDdUQlBrYVZpMnNuTFJ1R3hacVYrRCsxYWQ2RTRcL2pMN1BtRVA1ZFZcL0NtaEtIUDdZV3pENzNLcE1zWGVwUndEXC9Pb2tmSERcL1pUaGUifQ%3D%3D)中找到。

### 如果依赖 `aws-auth` ConfigMap，请使用工具进行更改
<a name="_if_relying_on_aws_auth_configmap_use_tools_to_make_changes"></a>

格式不正确的 aws-auth ConfigMap 可能会导致您无法访问集群。如果您需要对进行更改 ConfigMap，请使用工具。

 **eksctl** CL `eksctl` I 包含一个用于向 aws-auth 添加身份映射的命令。 ConfigMap

查看 CLI 帮助：

```
$ eksctl create iamidentitymapping --help
...
```

检查映射到您的 Amazon EKS 集群的身份。

```
$ eksctl get iamidentitymapping --cluster $CLUSTER_NAME --region $AWS_REGION
ARN                                                                   USERNAME                        GROUPS                                                  ACCOUNT
arn:aws:iam::788355785855:role/kube-system-<SELF_GENERATED_UUID>      system:node:{{SessionName}}     system:bootstrappers,system:nodes,system:node-proxier
```

将 IAM 角色设为集群管理员：

```
$ eksctl create iamidentitymapping --cluster  <CLUSTER_NAME> --region=<region> --arn arn:aws:iam::123456:role/testing --group system:masters --username admin
...
```

如需了解更多信息，请查看[`eksctl`文档](https://eksctl.io/usage/iam-identity-mappings/) 

 **keikoproj 的 [aws-auth](https://github.com/keikoproj/aws-auth)** 

 `aws-auth`by keikoproj 包括一个 cli 和 go 库。

下载并查看帮助 CLI 帮助：

```
$ go get github.com/keikoproj/aws-auth
...
$ aws-auth help
...
```

或者，`aws-auth`使用适用于 kubectl 的 ku [rew 插件管理器](https://krew.sigs.k8s.io)进行安装。

```
$ kubectl krew install aws-auth
...
$ kubectl aws-auth
...
```

 [请查看 aws-auth 文档 GitHub以](https://github.com/keikoproj/aws-auth/blob/master/README.md)获取更多信息，包括 go 库。

 **[AWS IAM Authenticator IAM Auth](https://github.com/kubernetes-sigs/aws-iam-authenticator/tree/master/cmd/aws-iam-authenticator)** 

该`aws-iam-authenticator`项目包括用于更新的 CLI ConfigMap。

 [在上下载发行版](https://github.com/kubernetes-sigs/aws-iam-authenticator/releases) GitHub。

向 IAM 角色添加集群权限：

```
$ ./aws-iam-authenticator add role --rolearn arn:aws:iam::185309785115:role/lil-dev-role-cluster --username lil-dev-user --groups system:masters --kubeconfig ~/.kube/config
...
```

### 身份验证和访问管理的替代方法
<a name="_alternative_approaches_to_authentication_and_access_management"></a>

[虽然 IAM 是对需要访问 EKS 集群的用户进行身份验证的首选方式，但也可以使用 OIDC 身份提供商，例如GitHub 使用身份验证代理和 Kubernetes 模拟。](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation)AWS 开源博客上已经发布了两个此类解决方案的文章：
+  [使用带传送的 GitHub 凭证向 EKS 进行身份验证](https://aws.amazon.com/blogs/opensource/authenticating-eks-github-credentials-teleport/) 
+  [使用在多个 EKS 集群之间进行一致的 OIDC 身份验证 kube-oidc-proxy](https://aws.amazon.com/blogs/opensource/consistent-oidc-authentication-across-multiple-eks-clusters-using-kube-oidc-proxy/) 

**重要**  
EKS 原生支持 OIDC 身份验证，无需使用代理。如需了解更多信息，请阅读发布博客 “[Amazon EKS 的 OIDC 身份提供商身份验证简介](https://aws.amazon.com/blogs/containers/introducing-oidc-identity-provider-authentication-amazon-eks/)”。有关如何使用 Dex（一种流行的开源 OIDC 提供商，具有用于各种不同身份验证方法的连接器）配置 EKS 的示例，请参阅[使用 Dex 和 dex-k8s-authenticator 向 Amazon EKS](https://aws.amazon.com/blogs/containers/using-dex-dex-k8s-authenticator-to-authenticate-to-amazon-eks/) 进行身份验证。如博客中所述，经过 OIDC 提供商认证 username/group 的用户将显示在 Kubernetes 审计日志中。

您还可以使用 [AWS SSO 将 AW](https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html) S 与外部身份提供商（例如 Azure AD）联合起来。如果您决定使用此功能，AWS CLI v2.0 包含一个用于创建命名配置文件的选项，可轻松将 SSO 会话与您当前的 CLI 会话关联并担任 IAM 角色。请注意，在运行*之前*，您必须代入一个角色，`kubectl`因为 IAM 角色用于确定用户的 Kubernetes RBAC 组。

## EKS 容器的身份和凭证
<a name="_identities_and_credentials_for_eks_pods"></a>

在 Kubernetes 集群中运行的某些应用程序需要获得调用 Kubernetes API 的权限才能正常运行。例如，[AWS Load Balancer 控制器](https://github.com/kubernetes-sigs/aws-load-balancer-controller)需要能够列出服务的终端节点。控制器还需要能够调用 AWS APIs 来配置和配置 ALB。在本节中，我们将探讨为 Pod 分配权限和权限的最佳实践。

### Kubernetes 服务账号
<a name="_kubernetes_service_accounts"></a>

服务账号是一种特殊类型的对象，允许你为容器分配 Kubernetes RBAC 角色。系统会自动为集群中的每个命名空间创建一个默认服务帐户。当您在不引用特定服务帐户的情况下将 Pod 部署到命名空间时，该命名空间的默认服务帐户将自动分配给该 Pod，而 Secret（即该服务帐户的服务帐户 (JWT) 令牌）将作为卷安装到该 Pod 上。`/var/run/secrets/kubernetes.io/serviceaccount`解码该目录中的服务账号令牌将显示以下元数据：

```
{
  "iss": "kubernetes/serviceaccount",
  "kubernetes.io/serviceaccount/namespace": "default",
  "kubernetes.io/serviceaccount/secret.name": "default-token-5pv4z",
  "kubernetes.io/serviceaccount/service-account.name": "default",
  "kubernetes.io/serviceaccount/service-account.uid": "3b36ddb5-438c-11ea-9438-063a49b60fba",
  "sub": "system:serviceaccount:default:default"
}
```

默认服务账号对 Kubernetes API 具有以下权限。

```
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2020-01-30T18:13:25Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:discovery
  resourceVersion: "43"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/system%3Adiscovery
  uid: 350d2ab8-438c-11ea-9438-063a49b60fba
rules:
- nonResourceURLs:
  - /api
  - /api/*
  - /apis
  - /apis/*
  - /healthz
  - /openapi
  - /openapi/*
  - /version
  - /version/
  verbs:
  - get
```

此角色授权未经身份验证和经过身份验证的用户读取 API 信息，并且被认为是安全的，可以公开访问。

当在 Pod 中运行的应用程序调用 Kubernetes 时 APIs，需要为该 Pod 分配一个服务账户，明确授予其调用这些服务的权限。 APIs与用户访问指南类似，角色或 ClusterRole 绑定到服务帐号的权限应仅限于应用程序运行所需的 API 资源和方法，仅限于其他任何内容。要使用非默认服务帐号，只需将 Pod 的`spec.serviceAccountName`字段设置为您要使用的服务帐号的名称即可。有关创建服务帐号的更多信息，请参阅 https://kubernetes。 io/docs/reference/access-authn-authz/rbac/\$1 service-account-permissions。

**注意**  
在 Kubernetes 1.24 之前，Kubernetes 会自动为每个服务账户创建一个密钥。此密钥已安装到位于/的 pod 上var/run/secrets/kubernetes.io/serviceaccount，Pod 将使用该密钥向 Kubernetes API 服务器进行身份验证。在 Kubernetes 1.24 中，服务账号令牌是在容器运行时动态生成的，默认情况下仅在一小时内有效。不会为服务帐号创建密钥。如果您有一个在集群之外运行的应用程序需要向 Kubernetes API 进行身份验证，例如 Jenkins，则需要创建一个类型的密钥`kubernetes.io/service-account-token`以及一个引用服务帐户的注释，例如。`metadata.annotations.kubernetes.io/service-account.name: <SERVICE_ACCOUNT_NAME>`以这种方式创建的密钥不会过期。

### 服务账户的 IAM 角色 (IRSA)
<a name="_iam_roles_for_service_accounts_irsa"></a>

IRSA 是一项允许您为 Kubernetes 服务账户分配 IAM 角色的功能。它通过利用名为[服务账户代币](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection)量投影的 Kubernetes 功能来工作。当 Pod 配置了引用 IAM 角色的服务账户时，Kubernetes API 服务器将在启动时调用集群的公共 OIDC 发现终端节点。端点对由 Kubernetes 发行的 OIDC 令牌进行加密签名，并将生成的令牌作为一个卷挂载。此签名令牌允许 Pod 调用 AWS APIs 关联的 IAM 角色。调用 AWS API 时，AWS 会 SDKs 调用`sts:AssumeRoleWithWebIdentity`。验证令牌的签名后，IAM 将 Kubernetes 颁发的令牌交换为临时的 AWS 角色证书。

使用 IRSA 时，务必[重复使用 AWS 开发工具包会话](#iam-reuse-sessions)，以避免不必要地调用 AWS STS。

解码 IRSA 的（JWT）令牌将生成与以下示例类似的输出：

```
{
  "aud": [
    "sts.amazonaws.com"
  ],
  "exp": 1582306514,
  "iat": 1582220114,
  "iss": "https://oidc.eks.us-west-2.amazonaws.com/id/D43CF17C27A865933144EA99A26FB128",
  "kubernetes.io": {
    "namespace": "default",
    "pod": {
      "name": "alpine-57b5664646-rf966",
      "uid": "5a20f883-5407-11ea-a85c-0e62b7a4a436"
    },
    "serviceaccount": {
      "name": "s3-read-only",
      "uid": "a720ba5c-5406-11ea-9438-063a49b60fba"
    }
  },
  "nbf": 1582220114,
  "sub": "system:serviceaccount:default:s3-read-only"
}
```

此特定令牌通过担任 IAM 角色向 S3 授予 Pod 仅限查看的权限。当应用程序尝试从 S3 读取时，会将该令牌交换为一组临时的 IAM 证书，如下所示：

```
{
    "AssumedRoleUser": {
        "AssumedRoleId": "AROA36C6WWEJULFUYMPB6:abc",
        "Arn": "arn:aws:sts::123456789012:assumed-role/eksctl-winterfell-addon-iamserviceaccount-de-Role1-1D61LT75JH3MB/abc"
    },
    "Audience": "sts.amazonaws.com",
    "Provider": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/D43CF17C27A865933144EA99A26FB128",
    "SubjectFromWebIdentityToken": "system:serviceaccount:default:s3-read-only",
    "Credentials": {
        "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "SessionToken": "FwoGZXIvYXdzEGMaDMLxAZkuLpmSwYXShiL9A1S0X87VBC1mHCrRe/pB2oesl1eXxUYnPJyC9ayOoXMvqXQsomq0xs6OqZ3vaa5Iw1HIyA4Cv1suLaOCoU3hNvOIJ6C94H1vU0siQYk7DIq9Av5RZeuE2FnOctNBvYLd3i0IZo1ajjc00yRK3v24VRq9nQpoPLuqyH2jzlhCEjXuPScPbi5KEVs9fNcOTtgzbVf7IG2gNiwNs5aCpN4Bv/Zv2A6zp5xGz9cWj2f0aD9v66vX4bexOs5t/YYhwuwAvkkJPSIGvxja0xRThnceHyFHKtj0Hbi/PWAtlI8YJcDX69cM30JAHDdQHltm/4scFptW1hlvMaPWReCAaCrsHrATyka7ttw5YlUyvZ8EPogj6fwHlxmrXM9h1BqdikomyJU00gm1FJelfP1zAwcyrxCnbRl3ARFrAt8hIlrT6Vyu8WvWtLxcI8KcLcJQb/LgkWsCTGlYcY8z3zkigJMbYn07ewTL5Ss7LazTJJa758I7PZan/v3xQHd5DEc5WBneiV3iOznDFgup0VAMkIviVjVCkszaPSVEdK2NU7jtrh6Jfm7bU/3P6ZGCkyDLIa8MBn9KPXeJd/yjTk5IifIwO/mDpGNUribg6TPxhzZ8b/XdZO1kS1gVgqjXyVCM+BRBh6C4H21w/eMzjCtDIpoxt5rGKL6Nu/IFMipoC4fgx6LIIHwtGYMG7SWQi7OsMAkiwZRg0n68/RqWgLzBt/4pfjSRYuk=",
        "Expiration": "2020-02-20T18:49:50Z",
        "AccessKeyId": "ASIAIOSFODNN7EXAMPLE"
    }
}
```

作为 EKS 控制平面一部分运行的变异 webhook 将 AWS 角色 ARN 和网络身份令牌文件的路径作为环境变量注入 Pod。这些值也可以手动提供。

```
AWS_ROLE_ARN=arn:aws:iam::AWS_ACCOUNT_ID:role/IAM_ROLE_NAME
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token
```

当预计代币超过其总TTL的80％或24小时后，kubelet将自动轮换该代币。AWS 负责 SDKs 在令牌轮换时重新加载代币。有关 IRSA 的更多信息，请参阅 https://docs.aws.amazon.com/eks/ latest/userguide/iam-roles-for-service-accounts-technical-overview.html。

### EKS 容器组身份
<a name="_eks_pod_identities"></a>

 [EKS Pod](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html) Identities 是 re: Invent 2023 上推出的一项功能，允许您为 kubernetes 服务账户分配 IAM 角色，而无需为 AWS 账户中的每个集群配置 Open Id Connect (OIDC) 身份提供商 (IDP)。要使用 EKS Pod Identity，您必须在每个符合条件的工作节点上部署一个作为 DaemonSet Pod 运行的代理。此代理作为 EKS 附加组件提供给您，并且是使用 EKS Pod 身份功能的先决条件。您的应用程序必须使用[支持版本的 AWS 开发工具包](https://docs.aws.amazon.com/eks/latest/userguide/pod-id-minimum-sdk.html)才能使用此功能。

为 Pod 配置 EKS Pod 身份后，EKS 将在上安装并刷新容器身份令牌`/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token`。AWS 开发工具包将使用此令牌与 EKS Pod Identity Agent 通信，后者使用 pod 身份令牌和代理的 IAM 角色通过调用 [AssumeRoleForPodIdentityAPI](https://docs.aws.amazon.com/eks/latest/APIReference/API_auth_AssumeRoleForPodIdentity.html) 为您的容器创建临时证书。交付给您的 pod 的 pod 身份令牌是从您的 EKS 集群颁发的 JWT，并经过加密签名，并带有相应的 JWT 声明，可与 EKS Pod 身份一起使用。

要了解有关 EKS Pod 身份的更多信息，请参阅[此博客](https://aws.amazon.com/blogs/containers/amazon-eks-pod-identity-a-new-way-for-applications-on-eks-to-obtain-iam-credentials/)。

您无需对应用程序代码进行任何修改即可使用 EKS Pod 身份。支持的 AWS 开发工具包版本将使用凭证提供[者链自动发现通过 EKS Pod 身份提供的证书](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html)。与 IRSA 一样，EKS Pod 身份会在您的 pod 中设置变量，以指导他们如何查找 AWS 证书。

#### 使用 EKS Pod 身份的 IAM 角色
<a name="_working_with_iam_roles_for_eks_pod_identities"></a>
+ EKS Pod Identitions 只能直接担任与 EKS 集群属于同一 AWS 账户的 IAM 角色。要访问其他 AWS 账户中的 IAM 角色，您必须通过[在软件开发工具包配置或应用程序代码中配置配置文件](https://docs.aws.amazon.com/sdkref/latest/guide/feature-assume-role-credentials.html)[来代入该](https://docs.aws.amazon.com/IAM/latest/UserGuide/sts_example_sts_AssumeRole_section.html)角色。
+ 为服务账户配置 EKS Pod 身份时，配置 Pod 身份关联的人员或进程必须拥有该角色的`iam:PassRole`权限。
+ 每个服务账户只能通过 EKS Pod Identities 关联一个 IAM 角色，但是您可以将相同的 IAM 角色与多个服务账户相关联。
+ 与 EKS Pod 身份一起使用的 IAM 角色必须允许`pods.eks.amazonaws.com`服务主体代入这些角色*并*设置会话标签。以下是允许 EKS Pod 身份使用 IAM 角色的角色信任策略示例：

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "pods.eks.amazonaws.com"
      },
      "Action": [
        "sts:AssumeRole",
        "sts:TagSession"
      ],
      "Condition": {
        "StringEquals": {
          "aws:SourceOrgId": "${aws:ResourceOrgId}"
        }
      }
    }
  ]
}
```

AWS 建议使用诸如此类的条件键`aws:SourceOrgId`来帮助防范[跨服务混乱的副手问题](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html#cross-service-confused-deputy-prevention)。在上面的角色信任策略示例中，`ResourceOrgId`是一个变量，等于 AWS 账户所属的 AWS 组织的 AWS 组织标识。EKS 将传入一个与担任 EKS Pod Identitions 角色时的值`aws:SourceOrgId`相等的值。

#### ABAC 和 EKS Pod 身份
<a name="_abac_and_eks_pod_identities"></a>

当 EKS Pod 身份担任 IAM 角色时，它会设置以下会话标签：


| EKS Pod 身份会话标签 | 值 | 
| --- | --- | 
|  kubernetes 命名空间  |  与 EKS Pod 身份关联的 pod 运行的命名空间。  | 
|  kubernetes-service-account  |  与 EKS Pod 身份关联的 kubernetes 服务账户的名称  | 
|  eks-cluster-arn  |  EKS 集群的 ARN，例如 `arn:${Partition}:eks:${Region}:${Account}:cluster/${ClusterName}` 集群 ARN 是唯一的，但是如果在同一区域、同一 AWS 账户中删除并重新创建具有相同名称的集群，则该集群将具有相同的 ARN。  | 
|  eks-cluster-name  |  EKS 集群的名称。请注意，您的 AWS 账户中的 EKS 集群名称可以相同，其他 AWS 账户中的 EKS 集群名称可以相同。  | 
|  kubernetes-pod-name  |  EKS 中吊舱的名称。  | 
|  kubernetes-pod-uid  |  EKS 中吊舱的 UID。  | 

这些会话标签允许您使用[基于属性的访问控制 (ABAC)](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction_attribute-based-access-control.html)，仅向特定的 kubernetes 服务账户授予对您的 AWS 资源的访问权限。这样做时，*必须*明白 kubernetes 服务帐户仅在命名空间中是唯一的，而 kubernetes 命名空间仅在 EKS 集群中是唯一的。可以使用`aws:PrincipalTag/<tag-key>`全局条件密钥在 AWS 策略中访问这些会话标签，例如 `aws:PrincipalTag/eks-cluster-arn` 

例如，如果您只想向特定的服务账户授予访问权限，以便通过 IAM 或资源策略访问您账户中的 AWS 资源，则需要检查`eks-cluster-arn`并`kubernetes-namespace`标记，并确保只有目标集群中的服务账户才能访问该资源，因为其他集群可能具有相同的`kubernetes-service-accounts`和`kubernetes-namespaces`。`kubernetes-service-account`

此示例 S3 存储桶策略仅在`eks-cluster-arn`所有对象都满足预期值时才授予访问其所连接的 S3 存储桶中的对象的权限，其中 EKS 集群托管在 AWS 账户中`111122223333`。`kubernetes-service-account` `kubernetes-namespace`

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:root"
            },
            "Action": "s3:*",
            "Resource":            [
                "arn:aws:s3:::ExampleBucket/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:PrincipalTag/kubernetes-service-account": "s3objectservice",
                    "aws:PrincipalTag/eks-cluster-arn": "arn:aws:eks:us-west-2:111122223333:cluster/ProductionCluster",
                    "aws:PrincipalTag/kubernetes-namespace": "s3datanamespace"
                }
            }
        }
    ]
}
```

### EKS Pod 身份与 IRSA 的比较
<a name="_eks_pod_identities_compared_to_irsa"></a>

EKS Pod 身份和 IRSA 都是向 EKS 容器提供临时 AWS 证书的首选方式。除非您有 IRSA 的特定用例，否则我们建议您在使用 EKS 时使用 EKS Pod 身份。此表有助于比较这两个功能。


| \$1 | EKS 容器组身份 | IRSA | 
| --- | --- | --- | 
|  需要权限才能在您的 AWS 账户中创建 OIDC IDP？  |  否  |  是  | 
|  每个集群需要唯一的 IDP 设置  |  否  |  是  | 
|  设置与 ABAC 一起使用的相关会话标签  |  是  |  否  | 
|  需要一个 iam：PassRole 支票？  |  是  |  否  | 
|  使用您的 AWS 账户中的 AWS STS 配额？  |  否  |  是  | 
|  可以访问其他 AWS 账户  |  间接使用角色链  |  直接使用 sts：AssumeRoleWithWebIdentity  | 
|  与 AWS 兼容 SDKs  |  支持  |  是  | 
|  需要在节点上安装 Pod 身份代理守护程序吗？  |  是  |  否  | 

## EKS pod 的身份和凭证推荐
<a name="_identities_and_credentials_for_eks_pods_recommendations"></a>

### 更新 aws-node 守护程序集以使用 IRSA
<a name="_update_the_aws_node_daemonset_to_use_irsa"></a>

目前，aws-node 守护程序集已配置为使用分配给 EC2 实例的角色来分配给 pod。 IPs 该角色包括多个 AWS 托管策略，例如 Amazoneks\$1cni\$1policy，这些策略实际上**允许**节点上运行的所有 pod 访问EC2ContainerRegistryReadOnly 、IP 地址或从 ECR 中提取映像。 attach/detach ENIs assign/unassign 由于这会给您的集群带来风险，因此建议您更新 aws-node 守护程序集以使用 IRSA。可以在本指南的[存储库](https://github.com/aws/aws-eks-best-practices/tree/master/projects/enable-irsa/src)中找到执行此操作的脚本。

aws-node 守护程序集支持 v1.15.5 及更高版本中的 EKS Pod 身份。

### 限制访问分配给工作节点的实例配置文件
<a name="_restrict_access_to_the_instance_profile_assigned_to_the_worker_node"></a>

当你使用 IRSA 或 EKS Pod Identitions 时，它会先更新 Pod 的凭证链以使用 IRSA 或 EKS Pod 身份，但是，Pod *仍然可以继承分配给工作节点的实例配置文件的权限*。对于不需要这些权限的 Pod，您可以阻止对[实例元数据的](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)访问，以帮助确保您的应用程序仅拥有所需的权限，而不是其节点。

**警告**  
阻止对实例元数据的访问将阻止不使用 IRSA 或 EKS Pod 身份的 Pod 继承分配给工作节点的角色。

您可以通过要求实例 IMDSv2 仅使用并将跳数更新为 1 来阻止对实例元数据的访问，如下例所示。您也可以将这些设置包含在节点组的启动模板中。请**勿**禁用实例元数据，因为这将阻止诸如节点终止处理程序之类的组件和其他依赖实例元数据的组件正常运行。

```
$ aws ec2 modify-instance-metadata-options --instance-id <value> --http-tokens required --http-put-response-hop-limit 1
...
```

如果您使用 Terraform 创建用于托管节点组的启动模板，请添加元数据块以配置跳数，如以下代码片段所示：

 `tf hl_lines="7" resource "aws_launch_template" "foo" { name = "foo" …​ metadata_options { http_endpoint = "enabled" http_tokens = "required" http_put_response_hop_limit = 1 instance_metadata_tags = "enabled" } …​` 

您还可以通过操作节点上的 iptables 来阻止容器对 EC2 元数据的访问。有关此方法的更多信息，请参阅[限制对实例元数据服务的访问](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#instance-metadata-limiting-access)。

如果您的应用程序使用的是不支持 IRSA 或 EKS Pod 身份的旧版 AWS 开发工具包，则应更新软件开发工具包版本。

### 将 IRSA 角色的 IAM 角色信任策略范围限定为服务账户名称、命名空间和集群
<a name="_scope_the_iam_role_trust_policy_for_irsa_roles_to_the_service_account_name_namespace_and_cluster"></a>

信任策略的范围可以限定为命名空间或命名空间中的特定服务帐号。使用 IRSA 时，最好通过包含服务帐户名称来使角色信任策略尽可能明确。这将有效地防止同一个命名空间中的其他 Pod 担任该角色。当您使用 CLI `eksctl` 创建服务 accounts/IAM 角色时，它会自动执行此操作。见 https://eksctl。 io/usage/iamserviceaccounts/了解更多信息。

直接使用 IAM 时，这就是在角色的信任策略中添加条件，该策略使用条件来确保`:sub`声明是您期望的命名空间和服务账号。举个例子，之前我们有一个 IRSA 代币，其子声明为 “system: serviceaccount: default: s3-只读”。这是`default`命名空间，服务帐号是`s3-read-only`。你可以使用如下条件来确保只有集群中给定命名空间中的服务账号才能担任该角色：

```
  "Condition": {
      "StringEquals": {
          "oidc.eks.us-west-2.amazonaws.com/id/D43CF17C27A865933144EA99A26FB128:aud": "sts.amazonaws.com",
          "oidc.eks.us-west-2.amazonaws.com/id/D43CF17C27A865933144EA99A26FB128:sub": "system:serviceaccount:default:s3-read-only"
      }
  }
```

### 每个应用程序使用一个 IAM 角色
<a name="_use_one_iam_role_per_application"></a>

对于 IRSA 和 EKS Pod Identity，最佳做法是为每个应用程序分配自己的 IAM 角色。这提高了隔离性，因为您可以在不影响另一个应用程序的情况下修改一个应用程序，并且允许您通过仅向应用程序授予所需的权限来应用权限最小的主体。

将 ABAC 与 EKS Pod Identity 配合使用时，您可以在多个服务账户中使用通用 IAM 角色，并依靠其会话属性进行访问控制。这在大规模运营时特别有用，因为 ABAC 允许您使用更少的 IAM 角色进行操作。

### 当您的应用程序需要访问 IMDS 时，请使用 imdsv2 并将 EC2 实例的跳跃限制增加到 2
<a name="_when_your_application_needs_access_to_imds_use_imdsv2_and_increase_the_hop_limit_on_ec2_instances_to_2"></a>

 [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)需要您使用 PUT 请求来获取会话令牌。初始 PUT 请求必须包含会话令牌的 TTL。较新版本的 AWS SDK 将自动处理此问题以及上述令牌的续订。同样重要的是要注意，EC2 实例的默认跳数限制被故意设置为 1，以防止 IP 转发。因此，请求在 EC2 实例上运行的会话令牌的 Pod 最终可能会超时并回退到使用IMDSv1 数据流。EKS IMDSv2 通过同时*启用* v1 和 v2 并将由 eksctl 或官方模板配置的节点上的跳跃限制更改为 2 来增加支持。 CloudFormation 

### 禁用自动挂载服务账号令牌
<a name="_disable_auto_mounting_of_service_account_tokens"></a>

如果您的应用程序不需要调用 Kubernetes API，请将应用程序的`automountServiceAccountToken`属性设置为，或者`false`在每个命名空间中修补默认服务帐户，使其不再自动挂载到 pod 上。 PodSpec例如：

```
kubectl patch serviceaccount default -p $'automountServiceAccountToken: false'
```

### 为每个应用程序使用专用服务帐户
<a name="_use_dedicated_service_accounts_for_each_application"></a>

每个应用程序都应有自己的专用服务帐户。这适用于 Kubernetes API 的服务账户以及 IRSA 和 EKS Pod Identity。

**重要**  
如果您在使用 IRSA 时采用集群升级 blue/green 方法而不是执行就地集群升级，则需要使用新集群的 OIDC 终端节点更新每个 IRSA IAM 角色的信任策略。 blue/green 集群升级是指创建一个在旧集群旁边运行较新版本的 Kubernetes 的集群，并使用负载均衡器或服务网格将流量从在旧集群上运行的服务无缝转移到新集群。在 EKS Pod Identity 中使用 blue/green 集群升级时，您将在新集群中的 IAM 角色和服务账户之间创建 Pod 身份关联。如果您有`sourceArn`条件，请更新 IAM 角色信任策略。

### 以非 root 用户身份运行应用程序
<a name="_run_the_application_as_a_non_root_user"></a>

默认情况下，容器以 root 用户身份运行。虽然这允许他们读取 Web 身份令牌文件，但以 root 用户身份运行容器并不是最佳实践。作为替代方案，可以考虑将`spec.securityContext.runAsUser`属性添加到 PodSpec。的值`runAsUser`是任意值。

在以下示例中，Pod 中的所有进程都将在`runAsUser`字段中指定的用户 ID 下运行。

```
apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
  containers:
  - name: sec-ctx-demo
    image: busybox
    command: [ "sh", "-c", "sleep 1h" ]
```

当你以非 root 用户身份运行容器时，它会阻止容器读取 IRSA 服务账户令牌，因为默认情况下，该令牌被分配了 0600 [root] 权限。如果你更新容器的 SecurityContext 以包含 fsgroup=65534 [Nobody]，它将允许容器读取令牌。

```
spec:
  securityContext:
    fsGroup: 65534
```

在 Kubernetes 1.19 及更高版本中，不再需要进行此更改，应用程序无需将其添加到 Nobody 组即可读取 IRSA 服务账户令牌。

### 授予对应用程序的最低特权访问权限
<a name="_grant_least_privileged_access_to_applications"></a>

 Acti@@ [on Hero](https://github.com/princespaghetti/actionhero) 是一个实用工具，您可以与应用程序一起运行，以识别应用程序正常运行所需的 AWS API 调用和相应的 IAM 权限。它与 [IAM Access Advisor](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html) 类似，因为它可以帮助您逐步限制分配给应用程序的 IAM 角色的范围。有关更多信息，请参阅有关授予对 AWS 资源[的最低权限访问权限](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)的文档。

考虑为与 IRSA 和 Pod 身份一起使用的 IAM 角色设置[权限边界](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html)。您可以使用权限边界来确保 IRSA 或 Pod Identities 使用的角色不能超过最大权限级别。有关权限边界入门的示例指南以及权限边界策略示例，请参阅此 [github 存储库](https://github.com/aws-samples/example-permissions-boundary)。

### 查看并撤消对您的 EKS 集群的不必要的匿名访问权限
<a name="_review_and_revoke_unnecessary_anonymous_access_to_your_eks_cluster"></a>

理想情况下，应禁用所有 API 操作的匿名访问权限。匿名访问权限是通过为 Kubernetes 内置用户系统:ClusterRoleBinding anonymous 创建 RoleBinding 或来授予的。你可以使用 [rbac-lookup](https://github.com/FairwindsOps/rbac-lookup) 工具来识别 system: anonymous 用户对你的集群拥有的权限：

```
./rbac-lookup | grep -P 'system:(anonymous)|(unauthenticated)'
system:anonymous               cluster-wide        ClusterRole/system:discovery
system:unauthenticated         cluster-wide        ClusterRole/system:discovery
system:unauthenticated         cluster-wide        ClusterRole/system:public-info-viewer
```

public-info-viewer 不应将任何角色或 system: 以 ClusterRole 外的角色绑定到 system: anonymous 用户或 system: 未经身份验证的群组。

可能有一些正当理由在特定情况下启用匿名访问 APIs。如果您的集群是这种情况，请确保匿名用户只能访问特定的 APIs 群集，而公开APIs 未经身份验证的群集不会使您的集群容易受到攻击。

在 Kubernetes/EKS 版本 1.14 之前，默认情况下，system: 未经身份验证的组与 system: discovery 和 system: basic-user 相关联。 ClusterRoles 请注意，即使您已将集群更新到 1.14 或更高版本，这些权限仍可能在您的集群上启用，因为集群更新不会撤消这些权限。要检查除了 system: 之外哪些ClusterRoles 有 “system: unautificated”，public-info-viewer 你可以运行以下命令（需要 jq util）：

```
kubectl get ClusterRoleBinding -o json | jq -r '.items[] | select(.subjects[]?.name =="system:unauthenticated") | select(.metadata.name != "system:public-info-viewer") | .metadata.name'
```

而且，可以使用：从除 “system:” 之外的所有角色中删除 “system: unauthentified”：public-info-viewer

```
kubectl get ClusterRoleBinding -o json | jq -r '.items[] | select(.subjects[]?.name =="system:unauthenticated") | select(.metadata.name != "system:public-info-viewer") | del(.subjects[] | select(.name =="system:unauthenticated"))' | kubectl apply -f -
```

或者，你可以通过 kubectl describe 和 kubectl edit 手动检查和删除它。要检查 system: 未经身份验证的组是否在您的集群上拥有 system: discovery 权限，请运行以下命令：

```
kubectl describe clusterrolebindings system:discovery

Name:         system:discovery
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
Role:
  Kind:  ClusterRole
  Name:  system:discovery
Subjects:
  Kind   Name                    Namespace
  ----   ----                    ---------
  Group  system:authenticated
  Group  system:unauthenticated
```

要检查 system: 未经身份验证的组在您的集群上是否拥有 system: basic-user 权限，请运行以下命令：

```
kubectl describe clusterrolebindings system:basic-user

Name:         system:basic-user
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
Role:
  Kind:  ClusterRole
  Name:  system:basic-user
Subjects:
  Kind   Name                    Namespace
  ----   ----                    ---------
  Group  system:authenticated
  Group  system:unauthenticated
```

如果 system: 未经身份验证的组绑定到集群 ClusterRoles 上的 system: discovery 和/或 system: basic-user，则应取消这些角色与 system: 未经身份验证的组的关联。ClusterRoleBinding 使用以下命令编辑 system: discovery：

```
kubectl edit clusterrolebindings system:discovery
```

上面的命令将在编辑器中打开 system: discovery ClusterRoleBinding 的当前定义，如下所示：

```
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2021-06-17T20:50:49Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:discovery
  resourceVersion: "24502985"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/system%3Adiscovery
  uid: b7936268-5043-431a-a0e1-171a423abeb6
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:discovery
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:authenticated
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:unauthenticated
```

从上述编辑器屏幕的 “主题” 部分中删除 system: 未认证群组的条目。

对 system: ClusterRoleBinding basic-user 重复相同的步骤。

### 在 IRSA 中重复使用 AWS 开发工具包会话
<a name="iam-reuse-sessions"></a>

当您使用 IRSA 时，使用 AWS 开发工具包编写的应用程序会使用传送到您的 pod 的令牌`sts:AssumeRoleWithWebIdentity`来调用生成临时 AWS 证书。这与其他 AWS 计算服务不同，在这些服务中，计算服务直接向 AWS 计算资源（例如 lambda 函数）提供临时 AWS 证书。这意味着，每次初始化 AWS 开发工具包会话时，都会调用 AWS STS f `AssumeRoleWithWebIdentity` or。如果您的应用程序快速扩展并初始化了许多 AWS SDK 会话，则可能会遇到来自 AWS STS 的限制，因为您的代码会发出很多调用。`AssumeRoleWithWebIdentity`

为避免出现这种情况，我们建议您在应用程序中重复使用 AWS 开发工具包会话，这样就不会对进行`AssumeRoleWithWebIdentity`不必要的调用。

在以下示例代码中，使用 boto3 python SDK 创建了一个会话，该会话用于创建客户端并与 Amazon S3 和 Amazon SQS 进行交互。 `AssumeRoleWithWebIdentity`仅调用一次，AWS 开发工具包将自动刷新证书到期`my_session`时的证书。

```
import boto3

= Create your own session

my_session = boto3.session.Session()

= Now we can create low-level clients from our session

sqs = my_session.client('`sqs`') s3 = my_session.client('`s3`')

s3response = s3.list_buckets() sqsresponse = sqs.list_queues()

#print the response from the S3 and SQS APIs print("`s3 response:`")
print(s3response) print("`—`") print("`sqs response:`")
print(sqsresponse)
```

如果您要使用 IRSA 将应用程序从其他 AWS 计算服务（例如 EC2）迁移到 EKS，则这是一个特别重要的细节。在其他计算服务上，除非您指示，否则初始化 AWS 开发工具包会话不会调用 AWS STS。

### 替代方法
<a name="_alternative_approaches"></a>

虽然 IRSA 和 EKS Pod 身份是向容器分配 AWS 身份的*首选方式*，但它们要求您在应用程序 SDKs 中包含最新版本的 AWS。有关当前支持 IRSA 的完整列表 SDKs，请参阅 https://docs.aws.amazon.com/eks/ latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html, for EKS Pod Identities, see https://docs.aws.amazon.com/eks/latest/userguide/pod-id-minimum-sdk .html。[https://github.com/jtblin/kube2iam](https://github.com/jtblin/kube2iam)尽管 AWS 不认可、宽恕也不支持这些解决方案的使用，但整个社区经常使用它们来实现与 IRSA 和 EKS Pod Identities 相似的结果。

如果您需要使用这些非 AWS 提供的解决方案，请进行尽职调查，并确保您了解这样做可能带来的安全影响。

## 工具和资源
<a name="_tools_and_resources"></a>
+  [Amazon EKS 安全沉浸式研讨会——Identity and Access Management](https://catalog.workshops.aws/eks-security-immersionday/en-US/2-identity-and-access-management) 
+  [Terraform EKS 蓝图模式——完全私有的亚马逊 EKS 集群](https://github.com/aws-ia/terraform-aws-eks-blueprints/tree/main/patterns/fully-private-cluster) 
+  [Terraform EKS 蓝图模式——亚马逊 EKS 集群的 IAM 身份中心单点登录](https://github.com/aws-ia/terraform-aws-eks-blueprints/tree/main/patterns/sso-iam-identity-center) 
+  [Terraform EKS 蓝图模式——亚马逊 EKS 集群的 Okta 单点登录](https://github.com/aws-ia/terraform-aws-eks-blueprints/tree/main/patterns/sso-okta) 
+  [audit2rbac](https://github.com/liggitt/audit2rbac) 
+  [rbac.dev](https://github.com/mhausenblas/rbac.dev) Kubernetes RBAC 的其他资源清单，包括博客和工具
+  [动作英雄](https://github.com/princespaghetti/actionhero) 
+  [kube2iam](https://github.com/jtblin/kube2iam) 
+  [kiam](https://github.com/uswitch/kiam) 