

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

# 身分和存取權管理
<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)最佳實務。

 [Identity and Access Management](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) (IAM) 是一種 AWS 服務，可執行兩項基本功能：身分驗證和授權。身分驗證涉及身分驗證，而授權會管理 AWS 資源可執行的動作。在 AWS 中，資源可以是另一個 AWS 服務，例如 EC2 或 AWS [委託人](https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html#intro-structure-principal)，例如 [IAM 使用者](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 服務的請求，例如 Bearer Tokens、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，再將其轉送至身分驗證 Webhook。如果請求格式正確，Webhook 會呼叫內嵌在字符內文中的預先簽章 URL。此 URL 會驗證請求的簽章，並將使用者的相關資訊傳回 kube-apiserver，例如使用者帳戶、Arn 和 UserId。

若要手動產生身分驗證字符，請在終端機視窗中輸入下列命令：

```
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，其中包含 Amazon 登入資料和簽章。如需其他詳細資訊，請參閱 https：//https://docs.aws.amazon.com/STS/latest/APIReference/API\$1GetCallerIdentity.html。

字符的存留時間 (TTL) 為 15 分鐘，之後需要產生新的字符。當您使用類似 的用戶端時，系統會自動處理此問題，`kubectl`不過，如果您使用 Kubernetes 儀表板，則需要產生新的權杖，並在每次權杖過期時重新驗證。

一旦 AWS IAM 服務已驗證使用者的身分，kube-apiserver 就會讀取`kube-system`命名空間中的 `aws-auth` ConfigMap，以決定要與使用者建立關聯的 RBAC 群組。ConfigMap `aws-auth` 用於在 IAM 主體之間建立靜態映射，即 IAM 使用者和角色，以及 Kubernetes RBAC 群組。您可以在 Kubernetes RoleBindings 或 ClusterRoleBindings 中參考 RBAC 群組。它們類似於 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>

Cluster Access Manager 現在是管理 AWS IAM 主體對 Amazon EKS 叢集的存取的偏好方式，是 AWS API 的功能，也是 EKS v1.23 和更新版本叢集 （全新或現有） 的選擇加入功能。它簡化了 AWS IAM 和 Kubernetes RBACs 之間的身分映射，無需在 AWS 和 Kubernetes APIs 之間切換或編輯 `aws-auth` ConfigMap 以進行存取管理、降低營運開銷，並協助解決設定錯誤。此工具也可讓叢集管理員撤銷或精簡自動授予用於建立叢集之 AWS IAM 主體的`cluster-admin`許可。

此 API 依賴兩個概念：
+  **存取項目：**直接連結至 AWS IAM 主體 （使用者或角色） 的叢集身分，允許對 Amazon EKS 叢集進行身分驗證。
+  **存取政策：** 是 Amazon EKS 特定政策，提供存取項目在 Amazon EKS 叢集中執行動作的授權。

在啟動時，Amazon EKS 僅支援預先定義和 AWS 受管政策。存取政策不是 IAM 實體，並由 Amazon EKS 定義和管理。

Cluster Access Manager 允許將上游 RBAC 與支援允許和傳遞 （但不拒絕） API 伺服器請求之 Kubernetes AuthZ 決策的存取政策結合。當上游 RBAC 和 Amazon EKS 授權方無法判斷請求評估的結果時，就會發生拒絕決策。

透過此功能，Amazon EKS 支援三種身分驗證模式：

1.  `CONFIG_MAP` 以僅繼續使用 `aws-auth` configMap。

1.  `API_AND_CONFIG_MAP` 從 EKS 存取項目 APIs和 `aws-auth` configMap 中來源已驗證的 IAM 主體，優先考慮存取項目。將現有`aws-auth`許可遷移至存取項目的理想選擇。

1.  `API` 完全依賴 EKS Access Entry APIs。這是新的**建議方法**。

若要開始使用，叢集管理員可以建立或更新 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 叢集組態，以使用 `update-cluster-config`命令啟用 `API` authenticationMode，在現有的叢集上使用 執行此操作`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 支援命令來新增和撤銷對叢集的存取，以及驗證指定叢集的現有存取政策和存取項目。系統會建立預設政策以符合 Kubernetes RBACs如下所示。


| EKS 存取政策 | Kubernetes RBAC | 
| --- | --- | 
|  AmazonEKSClusterAdminPolicy  |  cluster-admin  | 
|  AmazonEKSAdminPolicy  |  admin  | 
|  AmazonEKSEditPolicy  |  編輯  | 
|  AmazonEKSViewPolicy  |  檢視  | 

```
$ 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": []
}
```

在沒有叢集建立者管理員許可的情況下建立叢集時，沒有可用的存取項目，這是預設建立的唯一項目。

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

Kubernetes 與 AWS 身分驗證整合的其中一種方法是透過位於 `kube-system` 命名空間中的 `aws-auth` ConfigMap。它負責將 AWS IAM 身分 （使用者、群組和角色） 身分驗證映射至 Kubernetes 角色型存取控制 (RBAC) 授權。ConfigMap `aws-auth` 會在佈建階段自動在您的 Amazon EKS 叢集中建立。它最初是為了允許節點加入叢集而建立，但如上所述，您也可以使用此 ConfigMap 將 RBACs存取權新增至 IAM 主體。

若要檢查叢集的 `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
```

此 ConfigMap 的主要工作階段位於 `mapRoles`區塊`data`的 下，基本上由 3 個參數組成。
+  **群組：**要映射 IAM 角色的 Kubernetes 群組。這可以是預設群組，或在 `clusterrolebinding`或 中指定的自訂群組`rolebinding`。在上述範例中，我們只宣告了系統群組。
+  **rolearn：**使用下列格式 ，將 AWS IAM 角色的 ARN 映射至 Kubernetes 群組/群組新增`arn:<PARTITION>:iam::<AWS_ACCOUNT_ID>:role/role-name`。
+  **username：**Kubernetes 中對應至 AWS IAM 角色的使用者名稱。這可以是任何自訂名稱。

您也可以映射 AWS IAM 使用者的許可，在 `aws-auth`ConfigMap `data`的 `mapUsers`下定義 的新組態區塊，取代 **userarn** 的 **rolearn** 參數，但作為**最佳實務**，一律建議使用者`mapRoles`使用。

若要管理許可，您可以編輯 `aws-auth` ConfigMap 新增或移除對 Amazon EKS 叢集的存取權。雖然可以手動編輯 `aws-auth` ConfigMap，但建議使用 等工具`eksctl`，因為這是非常敏感的組態，不正確的組態可能會將您鎖定在 Amazon EKS 叢集之外。如需詳細資訊，請參閱以下子節 [使用工具對 aws-auth ConfigMap 進行變更](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 Identity Center 與 CAM API
<a name="_combine_iam_identity_center_with_cam_api"></a>
+  **簡化管理**：透過使用叢集存取管理 API 搭配 IAM Identity Center，管理員可以與其他 AWS 服務一起管理 EKS 叢集存取，減少在不同介面之間切換或手動編輯 ConfigMaps 的需求。
+ 使用存取項目，從叢集外部管理 IAM 主體的 Kubernetes 許可。您可以使用 EKS API、AWS 命令列界面、AWS SDKs來新增和管理對叢集的存取。 AWS CloudFormation 這意味著您可以使用建立叢集時使用的工具來管理使用者。
+ 如[本範例](https://github.com/aws-ia/terraform-aws-eks-blueprints/tree/main/patterns/sso-iam-identity-center)所示，利用自動化來部署具有 AWS IAM Identity Center 做為 IdP 的叢集，並將 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 叢集端點會設定為公有，也就是可以從網際網路存取。雖然可從網際網路存取，但端點仍被視為安全，因為它需要 IAM 驗證所有 API 請求，然後由 Kubernetes RBAC 授權。也就是說，如果您的公司安全政策要求您限制從網際網路存取 API，或防止您將流量路由到叢集 VPC 外部，您可以：
+ 將 EKS 叢集端點設定為私有。如需本主題的詳細資訊，請參閱[修改叢集端點存取](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html)。
+ 將叢集端點保持為公有，並指定哪些 CIDR 區塊可與叢集端點通訊。這些區塊實際上是允許存取叢集端點的一組列入允許清單的公有 IP 地址。
+ 使用一組列入允許清單的 CIDR 區塊設定公開存取，並將私有端點存取設定為已啟用。這將允許從特定範圍的公有 IPs 公開存取，同時透過在佈建控制平面時佈建至叢集 VPC 的跨帳戶 ENIs，強制 kubelet （工作者） 和 Kubernetes API 之間的所有網路流量。

### 請勿使用服務帳戶字符進行身分驗證
<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 叢集的存取權，請在 ConfigMap `aws-auth` 中為該使用者建立對應至特定 Kubernetes RBAC 群組的項目。

### 從叢集建立者主體移除叢集管理員許可
<a name="iam-cluster-creator"></a>

根據預設，Amazon EKS 叢集會使用繫結至叢集建立者主體的永久`cluster-admin`許可來建立。透過 Cluster Access Manager 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 群組。這將更容易維護，尤其是隨著需要存取的使用者數量增加。

**重要**  
使用 ConfigMap 映射的 IAM `aws-auth` 實體存取 EKS 叢集時，所描述的使用者名稱會記錄在 Kubernetes 稽核日誌的使用者欄位中。如果您使用的是 IAM 角色，則不會記錄擔任該角色的實際使用者，也無法稽核。

如果仍然使用 `aws-auth` configMap 做為身分驗證方法，則在將 K8s RBAC 許可指派給 IAM 角色時，您應該在使用者名稱中包含 \$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 `["*"]`中使用 。如果您不確定要指派哪些許可，請考慮使用 [audit2rbac](https://github.com/liggitt/audit2rbac) 之類的工具，根據 Kubernetes 稽核日誌中觀察到的 API 呼叫自動產生角色和繫結。

### 使用自動化程序建立叢集
<a name="_create_cluster_using_an_automated_process"></a>

如先前步驟所示，建立 Amazon EKS 叢集時，如果未使用 `API_AND_CONFIG_MAP`或 `API` 身分驗證模式，且未選擇退出將`cluster-admin`許可委派給叢集建立者，IAM 實體使用者或角色，例如建立叢集的聯合身分使用者，會在叢集的 RBAC 組態中自動授予`system:masters`許可。即使是移除此許可的最佳實務，如[此處](#iam-cluster-creator)所述，如果使用身分`CONFIG_MAP`驗證方法依賴 `aws-auth` ConfigMap，則無法撤銷此存取權。因此，最好使用連接到專用 IAM 角色的基礎設施自動化管道建立叢集，而沒有其他使用者或實體擔任的許可，並定期稽核此角色的許可、政策，以及有權觸發管道的人員。此外，此角色不應用於在叢集上執行例行動作，並僅用於透過 SCM 程式碼變更等管道觸發的叢集層級動作。

### 使用專用 IAM 角色建立叢集
<a name="_create_the_cluster_with_a_dedicated_iam_role"></a>

當您建立 Amazon EKS 叢集時，IAM 實體使用者或角色，例如建立叢集的聯合身分使用者，會在叢集的 RBAC 組態中自動授予`system:masters`許可。此存取權無法移除，也不會透過 ConfigMap `aws-auth` 進行管理。因此，最好使用專用 IAM 角色建立叢集，並定期稽核誰可以擔任此角色。此角色不應用於在叢集上執行例行動作，而是應為此目的透過 ConfigMap `aws-auth` 授予其他使用者對叢集的存取權。設定 `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** `eksctl`CLI 包含一個命令，用於將身分映射新增至 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` 作者 keikoproj 包含 cli 和 go 程式庫。

下載並檢視說明 CLI 說明：

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

或者，`aws-auth`使用適用於 kubectl 的 [krew 外掛程式管理員](https://krew.sigs.k8s.io)安裝 。

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

 [如需詳細資訊，請參閱 GitHub 上的 aws-auth 文件](https://github.com/keikoproj/aws-auth/blob/master/README.md)，包括 go 程式庫。

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

`aws-iam-authenticator` 專案包含用於更新 ConfigMap 的 CLI。

 在 GitHub 下載[版本](https://github.com/kubernetes-sigs/aws-iam-authenticator/releases)。

將叢集許可新增至 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 叢集的使用者進行身分驗證的首選方式，但可以使用身分驗證代理和 Kubernetes [模擬](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation)來使用 OIDC 身分提供者，例如 GitHub。兩個這類解決方案的文章已發佈在 AWS Open Source 部落格上：
+  [透過 Teleport 使用 GitHub 登入資料向 EKS 驗證](https://aws.amazon.com/blogs/opensource/authenticating-eks-github-credentials-teleport/) 
+  [使用 kube-oidc-proxy 跨多個 EKS 叢集進行一致的 OIDC 身分驗證](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 設定 EKS 的範例，Dex 是熱門的開放原始碼 OIDC 供應商，具有各種不同截斷方法的連接器，請參閱[使用 Dex & dex-k8s-authenticator 向 Amazon EKS](https://aws.amazon.com/blogs/containers/using-dex-dex-k8s-authenticator-to-authenticate-to-amazon-eks/) 驗證。如部落格所述，由 OIDC 供應商驗證的使用者名稱/使用者群組會顯示在 Kubernetes 稽核日誌中。

您也可以使用 [AWS SSO](https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html) 與外部身分提供者聯合 AWS，例如 Azure AD。如果您決定使用此功能，AWS CLI 2.0 版包含建立具名設定檔的選項，可讓您輕鬆地將 SSO 工作階段與目前的 CLI 工作階段建立關聯，並擔任 IAM 角色。知道您在執行 *之前*必須擔任角色，`kubectl`因為 IAM 角色用於判斷使用者的 Kubernetes RBAC 群組。

## EKS Pod 的身分和登入資料
<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 部署到命名空間時，該命名空間的預設服務帳戶會自動指派給 Pod，而秘密，即該服務帳戶的服務帳戶 (JWT) 字符，會掛載為 中的磁碟區`/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：//https://kubernetes.io/docs/reference/access-authn-authz/rbac/\$1service-account-permissions。

**注意**  
在 Kubernetes 1.24 之前，Kubernetes 會自動為每個服務帳戶建立秘密。此秘密掛載到位於 /var/run/secrets/kubernetes.io/serviceaccount 的 Pod，並由 Pod 用來向 Kubernetes API 伺服器進行身分驗證。在 Kubernetes 1.24 中，服務帳戶權杖會在 Pod 執行時動態產生，且預設僅有效一小時。將不會建立服務帳戶的秘密。如果您有在叢集外部執行的應用程式需要向 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 是一種功能，可讓您將 IAM 角色指派給 Kubernetes 服務帳戶。它的運作方式是利用稱為[服務帳戶字符磁碟區投影](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection)的 Kubernetes 功能。使用參考 IAM 角色的服務帳戶設定 Pod 時，Kubernetes API 伺服器會在啟動時呼叫叢集的公有 OIDC 探索端點。端點以密碼編譯方式簽署 Kubernetes 發行的 OIDC 權杖，並將產生的權杖掛載為磁碟區。此簽章權杖可讓 Pod 呼叫與 IAM 角色相關聯的 AWS APIs。叫用 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 角色，將 Pod 檢視限定權限授予 S3。當應用程式嘗試從 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 和 Web 身分字符檔案的路徑作為環境變數注入 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
```

kubelet 會在超過總 TTL 的 80% 或 24 小時後自動輪換投影的權杖。AWS SDKs負責在權杖輪換時重新載入權杖。如需 IRSA 的詳細資訊，請參閱 https：//https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html。

### EKS Pod 身分識別
<a name="_eks_pod_identities"></a>

 [EKS Pod 身分](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html)是在 re：Invent 2023 上啟動的一項功能，可讓您將 IAM 角色指派給 kubernetes 服務帳戶，而無需為 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 會在 掛載和重新整理 Pod 身分字符`/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token`。AWS 開發套件將使用此字符與 EKS Pod 身分代理程式通訊，該代理程式使用 Pod 身分字符和代理程式的 IAM 角色，透過呼叫 [AssumeRoleForPodIdentity API](https://docs.aws.amazon.com/eks/latest/APIReference/API_auth_AssumeRoleForPodIdentity.html) 來為您的 Pod 建立臨時憑證。交付至 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 身分只能直接擔任與 EKS 叢集屬於相同 AWS 帳戶的 IAM 角色。若要存取另一個 AWS 帳戶中的 IAM 角色，您必須在 [SDK 組態或應用程式的程式碼中設定設定檔](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](https://docs.aws.amazon.com/IAM/latest/UserGuide/sts_example_sts_AssumeRole_section.html)
+ 為服務帳戶設定 EKS Pod 身分時，設定 Pod 身分關聯的人員或程序必須具有該角色`iam:PassRole`的權限。
+ 每個服務帳戶只能有一個透過 EKS Pod 身分與其相關聯的 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 Organizations Organization ID 的變數。當擔任具有 EKS Pod 身分的角色時，EKS 會傳入`aws:SourceOrgId`等於 的值。

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

當 EKS Pod 身分擔任 IAM 角色時，它會設定下列工作階段標籤：


| EKS Pod 身分工作階段標籤 | Value | 
| --- | --- | 
|  kubernetes-namespace  |  與 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 叢集的名稱。請注意，EKS 叢集名稱在您的 AWS 帳戶中可以相同，在其他 AWS 帳戶中也可以是 EKS 叢集。  | 
|  kubernetes-pod-name  |  EKS 中 Pod 的名稱。  | 
|  kubernetes-pod-uid  |  EKS 中 Pod 的 UID。  | 

這些工作階段標籤可讓您使用[屬性型存取控制 (ABAC)](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction_attribute-based-access-control.html)，僅將對 AWS 資源的存取權授予特定 kubernetes 服務帳戶。這樣做時，*請務必*了解 kubernetes 服務帳戶在命名空間中是唯一的，而 kubernetes 命名空間在 EKS 叢集中是唯一的。您可以使用 `aws:PrincipalTag/<tag-key>`全域條件金鑰，在 AWS 政策中存取這些工作階段標籤，例如 `aws:PrincipalTag/eks-cluster-arn` 

例如，如果您只想授予特定服務帳戶的存取權，以使用 IAM 或資源政策存取您帳戶中的 AWS 資源，則需要檢查 `eks-cluster-arn` 和 `kubernetes-namespace` 標籤以及 ，`kubernetes-service-account`以確保只有來自預期叢集的服務帳戶可以存取該資源，因為其他叢集可以具有相同的 `kubernetes-service-accounts`和 `kubernetes-namespaces`。

此範例 S3 儲存貯體政策只會授予其連接之 S3 儲存貯體中物件的存取權，前提是 `kubernetes-service-account`、 `kubernetes-namespace``eks-cluster-arn`全都符合其預期值，其中 EKS 叢集託管於 AWS 帳戶 `111122223333`。

```
{
    "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"
                }
            }
        }
    ]
}
```

### 相較於 IRSA 的 EKS Pod 身分
<a name="_eks_pod_identities_compared_to_irsa"></a>

EKS Pod 身分和 IRSA 都是將臨時 AWS 登入資料交付至 EKS Pod 的偏好方式。除非您有 IRSA 的特定使用案例，否則我們建議您在使用 EKS 時使用 EKS Pod 身分。此資料表有助於比較這兩個功能。


| \$1 | EKS Pod 身分識別 | IRSA | 
| --- | --- | --- | 
|  需要在您的 AWS 帳戶中建立 OIDC IDP 的許可？  |  否  |  是  | 
|  每個叢集需要唯一的 IDP 設定  |  否  |  是  | 
|  設定與 ABAC 搭配使用的相關工作階段標籤  |  是  |  否  | 
|  需要 iam：PassRole 檢查？  |  是  |  否  | 
|  從您的 AWS 帳戶使用 AWS STS Quota？  |  否  |  是  | 
|  可以存取其他 AWS 帳戶  |  間接使用角色鏈結  |  直接使用 sts：AssumeRoleWithWebIdentity  | 
|  與 AWS SDKs相容  |  是  |  是  | 
|  節點上需要 Pod Identity Agent Daemonset？  |  是  |  否  | 

## 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 執行個體的角色，將 IPs 指派給 Pod。此角色包含數個 AWS 受管政策，例如 AmazonEKS\$1CNI\$1Policy 和 EC2ContainerRegistryReadOnly，可有效允許節點上執行**的所有** Pod 連接/提取 ENIs、指派/取消指派 IP 地址，或從 ECR 提取映像。由於這會對您的叢集造成風險，建議您更新 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 身分時，它會先更新 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" } …​` 

您也可以在節點上操作 iptable，以封鎖 Pod 對 EC2 中繼資料的存取。如需此方法的詳細資訊，請參閱[限制對執行個體中繼資料服務的存取](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#instance-metadata-limiting-access)。

如果您有應用程式正在使用不支援 IRSA 或 EKS Pod 身分的舊版 AWS 開發套件，則應更新 SDK 版本。

### 將 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 來建立服務帳戶/IAM 角色時，CLI `eksctl`會自動執行此操作。如需詳細資訊，請參閱 https://eksctl.io/usage/iamserviceaccounts/：//。

直接使用 IAM 時，這會將條件新增至角色的信任政策，該政策使用條件來確保`:sub`宣告是您預期的命名空間和服務帳戶。例如，在我們擁有的 IRSA 字符具有「system：serviceaccount：default：s3-read-only」的子宣告之前。這是 `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 角色。這可讓您改善隔離，因為您可以修改一個應用程式而不影響另一個應用程式，並只授予應用程式所需的許可，以套用最低權限的主體。

搭配 EKS Pod Identity 使用 ABAC 時，您可以在多個服務帳戶中使用常見的 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 SDKs會自動處理此問題和該權杖的續約。也請務必注意，EC2 執行個體的預設跳轉限制刻意設定為 1，以防止 IP 轉送。因此，請求在 EC2 執行個體上執行的工作階段字符的 Pod 最終可能會逾時，並回復為使用 IMDSv1 資料流程。EKS 新增支援 IMDSv2，方法是*啟用* v1 和 v2，並將 eksctl 或使用官方 CloudFormation 範本佈建的節點上的跳轉限制變更為 2。

### 停用服務帳戶字符的自動掛載
<a name="_disable_auto_mounting_of_service_account_tokens"></a>

如果您的應用程式不需要呼叫 Kubernetes API，請在應用程式的 PodSpec `false`中將 `automountServiceAccountToken` 屬性設定為 ，或修補每個命名空間中的預設服務帳戶，使其不再自動掛載至 Pod。例如：

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

### 為每個應用程式使用專用服務帳戶
<a name="_use_dedicated_service_accounts_for_each_application"></a>

每個應用程式都應有自己的專用服務帳戶。這適用於 Kubernetes API 的服務帳戶，以及 IRSA 和 EKS Pod 身分。

**重要**  
如果您在使用 IRSA 時採用藍/綠方法來叢集升級，而不是執行就地叢集升級，則需要使用新叢集的 OIDC 端點更新每個 IRSA IAM 角色的信任政策。藍/綠叢集升級可讓您建立與舊叢集一起執行較新 Kubernetes 版本的叢集，並使用負載平衡器或服務網格，將流量從舊叢集上執行的服務順暢地轉移到新叢集。搭配 EKS Pod Identity 使用藍/綠叢集升級時，您可以在新叢集的 IAM 角色和服務帳戶之間建立 Pod 身分關聯。如果您有`sourceArn`條件，請更新 IAM 角色信任政策。

### 以非根使用者身分執行應用程式
<a name="_run_the_application_as_a_non_root_user"></a>

根據預設，容器會以根身分執行。雖然這允許他們讀取 Web 身分字符檔案，但將容器作為根執行不會被視為最佳實務。或者，請考慮將 `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" ]
```

當您以非根使用者身分執行容器時，它會防止容器讀取 IRSA 服務帳戶權杖，因為權杖預設為指派 0600 【根】 許可。如果您將容器的 securityContext 更新為包含 fsgroup=65534 【無】，則會允許容器讀取字符。

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

在 Kubernetes 1.19 及更高版本中，不再需要此變更，應用程式可以讀取 IRSA 服務帳戶字符，而無需將其新增至沒有人群組。

### 授予最低權限的應用程式存取權
<a name="_grant_least_privileged_access_to_applications"></a>

 [Action 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 角色範圍。如需詳細資訊，請參閱授予[最低權限存取](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege) AWS 資源的文件。

考慮在與 IRSA 和 Pod 身分搭配使用的 IAM 角色上設定[許可界限](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html)。您可以使用許可界限，以確保 IRSA 或 Pod 身分使用的角色不得超過許可的最大層級。如需使用範例許可界限政策開始使用許可界限的範例指南，請參閱此 [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 內建使用者系統建立 RoleBinding 或 ClusterRoleBinding 來授予：匿名。您可以使用 [rbac-lookup](https://github.com/FairwindsOps/rbac-lookup) 工具來識別叢集上 system：anonymous user 的許可：

```
./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
```

system：public-info-viewer 以外的任何角色或 ClusterRole 都不應繫結至 system：anonymous user or system：unuthenticated group。

在特定 APIs上啟用匿名存取可能有某些合法原因。如果您的叢集發生這種情況，請確保匿名使用者只能存取這些特定 APIs而且在沒有身分驗證的情況下公開這些 APIs 不會讓您的叢集容易受到攻擊。

在 Kubernetes/EKS 1.14 版之前，System：未驗證的群組預設與 system：discovery 和 system：basic-user ClusterRoles 相關聯。請注意，即使您已將叢集更新至 1.14 版或更新版本，叢集上仍可能啟用這些許可，因為叢集更新不會撤銷這些許可。若要檢查哪些 ClusterRoles 具有 "system：unauthenticated"，Systems：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：public-info-viewer」之外，所有角色都可以使用下列方式移除「system：unauthenticated」：

```
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 描述和 kubectl 編輯來手動檢查和移除它。若要檢查未驗證的 群組是否具有叢集上的 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：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：未驗證的群組繫結至叢集上的 system：discovery 和/或 system：basic-user ClusterRoles，您應該取消這些角色與 system：未驗證群組的關聯。使用下列命令編輯 system：discovery ClusterRoleBinding：

```
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：unuthenticated 群組的項目。

對 system：basic-user ClusterRoleBinding 重複相同的步驟。

### 將 AWS 開發套件工作階段與 IRSA 重複使用
<a name="iam-reuse-sessions"></a>

當您使用 IRSA 時，使用 AWS 開發套件寫入的應用程式會使用交付至 Pod 的字符來呼叫 `sts:AssumeRoleWithWebIdentity` 來產生臨時 AWS 登入資料。這與其他 AWS 運算服務不同，其中運算服務會將臨時 AWS 登入資料直接交付至 AWS 運算資源，例如 lambda 函數。這表示每次初始化 AWS 開發套件工作階段時，`AssumeRoleWithWebIdentity`都會呼叫 的 AWS STS。如果您的應用程式快速擴展並初始化許多 AWS 開發套件工作階段，您可能會遇到來自 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)
```

如果您要將應用程式從另一個 AWS 運算服務遷移EC2到具有 IRSA 的 EKS，這是特別重要的詳細資訊。在其他初始化 AWS 開發套件工作階段的運算服務上，除非您指示，否則不會呼叫 AWS STS。

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

雖然 IRSA 和 EKS Pod 身分是將 AWS 身分指派給 Pod 的*偏好方式*，但它們會要求您在應用程式中包含最新版本的 AWS SDKs。如需目前支援 IRSA 的SDKs完整清單，請參閱 https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html：// EKS Pod 身分，請參閱 https://docs.aws.amazon.com/eks/latest/userguide/pod-id-minimum-sdk.html：//。如果您有應用程式無法立即使用相容的 SDK 更新，有數個社群建置的解決方案可用來將 IAM 角色指派給 Kubernetes Pod，包括 [kube2iam](https://github.com/jtblin/kube2iam) 和 [kiam](https://github.com/uswitch/kiam)。雖然 AWS 不認可、寬容或支援使用這些解決方案，但社群經常使用這些解決方案來達到與 IRSA 和 EKS Pod 身分類似的結果。

如果您需要使用這些非 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 藍圖模式 - 全私有 Amazon EKS 叢集](https://github.com/aws-ia/terraform-aws-eks-blueprints/tree/main/patterns/fully-private-cluster) 
+  [Terraform EKS 藍圖模式 - 適用於 Amazon EKS 叢集的 IAM Identity Center 單一登入](https://github.com/aws-ia/terraform-aws-eks-blueprints/tree/main/patterns/sso-iam-identity-center) 
+  [Terraform EKS 藍圖模式 - Okta Amazon EKS 叢集單一登入](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 的其他資源清單，包括部落格和工具
+  [Action Hero](https://github.com/princespaghetti/actionhero) 
+  [kube2iam](https://github.com/jtblin/kube2iam) 
+  [kiam](https://github.com/uswitch/kiam) 