# IAM Role for EKS

Amazon EKS服务帐户令牌是一种长期存在的静态凭证。如果它被泄露、丢失或被盗，攻击者可能会执行与该令牌相关的所有操作，直到服务帐户被删除。因此建议在EKS上使用IAM 角色，获得以下好处：

**安全**&#x20;

* IAM 策略支持限制角色只能在 指定的Accounts 使用，隔离账号之间的权限；&#x20;
* 代码或者配置文件中无需写入明文的AK/SK，不容易泄漏；（即使简单加密也容易泄漏）
* 安全凭据自动轮换；&#x20;
* 集群的 signing key 自动轮换；&#x20;

**易于集成**

* 内置于 AWS 开发工具包和 CLI 中的默认凭证链中&#x20;
* 无需在代码中输入明文的AK/SK&#x20;

**可审计**&#x20;

* 通过AWS CloudTrail记录日志

AWS IAM Roles for Service Accounts (IRSA) is a feature within Amazon EKS (Elastic Kubernetes Service) that allows Kubernetes service accounts to be associated with AWS Identity and Access Management (IAM) roles. This mechanism grants applications running on EKS clusters the ability to assume an IAM role and thus securely access AWS services without requiring the management of IAM credentials. The principle behind IRSA is rooted in the integration between Kubernetes service accounts and AWS IAM roles, leveraging AWS's Secure Token Service (STS) for the secure delegation of permissions.

#### Key Components:

* **IAM Role**: A set of permissions that define access to AWS resources. When associated with a Kubernetes service account, it dictates what AWS services and actions the pods can access.
* **Kubernetes Service Account**: Used within Kubernetes to provide an identity for processes running in a Pod.
* **OIDC (OpenID Connect) Provider**: Amazon EKS can act as an OIDC identity provider. It authenticates Kubernetes service accounts so they can assume an associated IAM role.
* **AWS STS (Secure Token Service)**: Generates temporary, limited-privilege credentials for Kubernetes service accounts, enabling them to assume an IAM role.

#### How it Works:

1. **Association**: An IAM role is created with a trust relationship that allows it to be assumed by a Kubernetes service account via the OIDC provider.
2. **Annotation**: The Kubernetes service account includes an annotation specifying the ARN (Amazon Resource Name) of the IAM role it should assume.
3. **Authentication**: When a pod associated with the annotated service account attempts to access an AWS service, the EKS cluster’s OIDC provider issues a JWT (JSON Web Token) to the pod.
4. **Authorization**: The pod uses this token to call the AWS STS `AssumeRoleWithWebIdentity` action, obtaining temporary AWS credentials.
5. **Access**: These credentials are automatically used by the AWS SDK within the application running in the pod to securely access AWS services, following the permissions defined in the IAM role.

#### Advantages:

* **Security**: Eliminates the need to store AWS credentials within Kubernetes, reducing the risk of credential exposure.
* **Simplicity**: Simplifies the credential management lifecycle, as IAM roles can be centrally managed and rotated.
* **Granularity**: Enables fine-grained permission control, allowing different pods to have different permissions based on their specific needs.

IRSA bridges the identity management gap between Kubernetes and AWS, providing a secure and streamlined way to access AWS services from within EKS clusters.

## 配置IRSA的操作步骤

要在Amazon EKS上使用IAM角色，您需要完成以下步骤：

1. 创建IAM OIDC提供程序
2. 配置Kubernetes服务帐户以承担IAM角色
3. 配置Pod以使用Kubernetes服务帐户

前提条件:

1. EKS cluster ready
2. kubectl, eksctl, aws-cli installed on Local Machine

## 验证您的 Amazon EKS 集群是否有 IAM OIDC 身份提供商

如果您还没有此身份提供商，则[为集群创建 IAM OIDC 提供商](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html)。您必须具有集群的 OIDC 身份提供商才能使用服务账户的 IAM 角色。

然后验证 OIDC 身份提供商的配置是否正确：

1\.    打开 [IAM 控制台](https://console.aws.amazon.com/iam/)，然后从导航窗格中选择 **Identity providers**（身份提供商）。

2\.    在 **Provider**（提供商）列中，找到并记下 OIDC 提供商 URL。

3\.    在单独的选项卡或窗口中，打开 [Amazon EKS 控制台](https://console.aws.amazon.com/eks/)，然后从导航窗格中选择 **Clusters**（集群）。

4\.    选择您的集群，然后选择 **Configuration**（配置）选项卡。

5\.    在 **Details**（详细信息）部分中，记下 **OpenID Connect provider URL**（OpenID Connect 提供商 URL）属性的值。

6\.    验证 Amazon EKS 控制台中的 OIDC 提供商 URL（第 5 步）是否与 IAM 控制台中的 OIDC 提供商 URL 匹配（第 2 步）。

如果 Amazon EKS 集群的 OIDC 提供商 URL 与 IAM 控制台中的任何 OIDC 提供商 URL 都不匹配，则必须[创建一个新的 IAM OIDC 提供商](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html)。

## 验证您的 IAM 角色策略和信任策略配置

您的 IAM 角色可能不具有您希望分配给该角色的全部权限。如果您使用 [AWS 管理控制台或 AWS CLI](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) 创建了 IAM 角色，则您的 IAM 角色的信任关系策略也可能存在语法错误。

要验证您的 IAM 角色策略并检查信任策略中是否存在语法错误，请执行以下操作：

1\.    打开 [IAM console](https://console.aws.amazon.com/iam/)（IAM 控制台）。

2\.    在导航窗格中，选择 **Roles**（角色），然后选择您的角色。

3\.    选择角色页面上的 **Permissions**（权限）选项卡，然后验证是否已将所有需要的权限分配给该角色。

4\.    选择 **Trust Relationships**（信任关系）选项卡，然后选择 **Edit trust relationship**（编辑信任关系）。

5\.    在信任关系的策略文档中，验证策略的格式是否与以下 JSON 策略的格式一致：

```
"Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::your-account-id:oidc-provider/oidc.eks.your-region-code.amazonaws.com/id/EXAMPLE_OIDC_IDENTIFIER"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.your-region-code.amazonaws.com/id/EXAMPLE_OIDC_IDENTIFIER:sub": "system:serviceaccount:your-namespace:your-service-account"
        }
      }
    }
  ]
}
```

在上述 JSON 策略中，查看 **Federated** 属性行和 **StringEquals** 属性行的格式。在 **Federated** 行中，确认您的 AWS 区域代码（**your-region-code**）、账户 ID（**your-account-id**）和唯一 OIDC 标识符（**EXAMPLE\_OIDC\_IDENTIFIER**）的格式正确。在 **StringEquals** 行中，确认您的区域代码（**your-region-code**）、OIDC 唯一标识符（**EXAMPLE\_OIDC\_IDENTIFIER**）、Kubernetes 命名空间（**your-namespace**）和 Kubernetes 服务账户名称（**your-namespace**）的格式正确。

6\.    如果要编辑策略文档以更正格式错误，请选择 **Update Trust Policy**（更新信任策略）。

## 确认您的服务账户存在且具有格式正确的 IAM 角色 ARN 注释

1\.    确认您的 Kubernetes 服务账户存在：

```
$ kubectl get serviceaccount YOUR_ACCOUNT_NAME -n YOUR_NAMESPACE -o yaml
```

\*\*注意：\*\*请将 **YOUR\_ACCOUNT\_NAME** 替换为您的账户名称。将 **YOUR\_NAMESPACE** 替换为您的命名空间。

如果上述命令没有返回服务账户名称，则[创建一个服务账户](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-multiple-service-accounts)（从 Kubernetes 网站）。

2\.    确认您的服务账户具有您期望的名称，并且其 **role-arn** 注释的格式正确。例如：

```
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::012345678912:role/my-example-iam-role
  name: my-example-serviceaccount
  namespace: my-test-namespace
```

## 使用测试容器组验证服务账户工作正常

您可以通过运行测试容器组来验证服务账户是否正常工作。然后检查该容器组是否可以正确挂载环境变量并可以代入指定的 IAM 角色。

\*\*注意：\*\*即使服务账户的 IAM 角色功能正常运行，您也可能会遇到与应用程序凭证相关的问题。即使您的容器组具有正确的环境变量，您也可能会遇到这个问题。为防止出现此问题，您可以使用 AWS CLI 容器镜像进行验证。

1\.    创建一个名为 **awscli-pod.yaml** 的本地 YAML 文件。例如：

```
apiVersion: v1kind: Podmetadata:  name: awscli  labels:    app: awsclispec:  serviceAccountName: YOUR_SERVICE_ACCOUNT  containers:  - image: amazon/aws-cli    command:      - "sleep"      - "604800"    imagePullPolicy: IfNotPresent    name: awscli  restartPolicy: Always
```

\*\*注意：\*\*请将 **YOUR\_SERVICE\_ACCOUNT** 替换为您的 Kubernetes 服务账户名称。

2\.    在您的命名空间中创建测试容器组（从该 YAML 文件）：

```
$ kubectl apply -f ./awscli-pod.yaml -n YOUR_NAMESPACE
```

\*\*注意：\*\*将 **YOUR\_NAMESPACE** 替换为您的命名空间。

3\.    确认 **awscli** 容器组具有正确的[环境变量](https://docs.aws.amazon.com/eks/latest/userguide/pod-configuration.html)：

```
$ kubectl exec -n YOUR_NAMESPACE awscli env | grep AWS
```

输出：

```
AWS_ROLE_ARN=arn:aws:iam::ACCOUNT_ID:role/IAM_ROLE_NAMEAWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token
```

4\.    确认测试容器组使用的是正确的 IAM 角色：

```
$ kubectl exec -it awscli -n YOUR_NAMESPACE -- aws sts get-caller-identity
```

输出：

```
{    "UserId": "REDACTEDY471234567890:botocore-session-1632772568",    "Account": "012345678912",    "Arn": "arn:aws:sts::012345678912:assumed-role/your-iam-role/botocore-session-1632772568"}
```

记下在第 4 步的命令输出中收到的 **Arn** 值，包括 IAM 角色名称（**your-iam-role**）。

5\.    验证 IAM 角色后删除 **awscli** 容器组：

```
$ kubectl delete -f ./awscli-pod.yaml -n YOUR_NAMESPACE
```

如果 **awscli** 容器组显示正确的 IAM 角色，则表示服务账户的 IAM 角色功能正常工作。

上述步骤确认 IAM 令牌已正确挂载到容器中。如果您的应用程序仍然无法正确使用令牌文件，则可能存在应用程序或 SDK 级别的问题。此问题可能与应用程序如何摄取 AWS 凭证有关。有关更多信息，请参阅[使用默认凭证提供程序链](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#credentials-default)和[凭证](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html)（Boto3 网站）。

AWS SDK for Java 2.x中的`AwsCredentialsProvider`接口有几个常用实现类，它们分别代表不同的功能：

1. `StaticCredentialsProvider`：用于提供固定的AWS凭证，适用于不会改变的凭证情况。
2. `DefaultCredentialsProvider`：用于从主机环境中发现凭证，适用于自动发现凭证的情况。
3. `ProfileCredentialsProvider`：用于从配置文件中加载凭证，适用于从配置文件中获取凭证的情况。
4. `EnvironmentVariableCredentialsProvider`：用于从环境变量中加载凭证，适用于从环境变量获取凭证的情况。
5. `SystemPropertyCredentialsProvider`：用于从系统属性中加载凭证，适用于从系统属性获取凭证的情况。

这些实现类提供了不同的方式来获取AWS凭证，开发人员可以根据具体情况选择合适的实现类来加载凭证，以授权AWS请求。<br>

在AWS EKS环境中，如果已配置IAM Role，调用AWS SDK for Java 2.x获取授权的推荐方式是使用`DefaultCredentialsProvider`。这种方法能够自动识别和利用EKS为Pod分配的IAM Role。`DefaultCredentialsProvider`会自动检查环境，并寻找可用的凭证，这包括EKS环境中的IAM角色。因此，无需手动指定凭证，简化了凭证管理和应用程序配置。

示例代码如下：

```java
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.services.s3.S3Client;

public class MyApplication {
    public static void main(String[] args) {
        S3Client s3 = S3Client.builder()
                              .credentialsProvider(DefaultCredentialsProvider.create())
                              .build();

        // 使用S3Client执行操作
    }
}
```

在此示例中，`DefaultCredentialsProvider.create()`会负责寻找和使用分配给EKS Pod的IAM Role凭证，从而授权S3客户端与AWS服务进行交互。这种方法便于应用程序在EKS环境中无缝运行，而无需关心凭证的具体管理和存储方式。

在AWS SDK for Java 2.x中，存在多种凭证提供者（CredentialsProvider）用于处理不同凭证获取和管理场景。以下是一些关键的凭证提供者及其代表含义：

* `AnonymousCredentialsProvider`：用于创建一个匿名访问的凭证。
* `AwsCredentialsProviderChain`：通过一个链式结构尝试多种凭证提供者。
* `ContainerCredentialsProvider`：为在容器内运行的应用获取凭证。
* `DefaultCredentialsProvider`：默认凭证提供者，会依序尝试多种方式获取凭证。
* `EnvironmentVariableCredentialsProvider`：从环境变量中获取凭证。
* `InstanceProfileCredentialsProvider`：为EC2实例上的应用获取IAM角色凭证。
* `LazyAwsCredentialsProvider`：按需（懒加载）获取凭证。
* `ProcessCredentialsProvider`：通过执行外部进程获取凭证。
* `ProfileCredentialsProvider`：从AWS配置文件中读取凭证。
* `SsoCredentialsProvider`：用于支持AWS单点登录（SSO）凭证获取。
* `StaticCredentialsProvider`：使用静态凭证。
* `StsAssumeRoleCredentialsProvider`、`StsAssumeRoleWithSamlCredentialsProvider`、`StsAssumeRoleWithWebIdentityCredentialsProvider`：使用STS（Security Token Service）进行角色提权或身份委托的凭证提供者。
* `StsCredentialsProvider`：通过STS获取临时凭证。
* `StsGetFederationTokenCredentialsProvider`、`StsGetSessionTokenCredentialsProvider`：通过STS获取联合登录或会话凭证。
* `StsWebIdentityTokenFileCredentialsProvider`：通过Web身份令牌文件和STS获取凭证。
* `SystemPropertyCredentialsProvider`：从系统属性中获取凭证。
* `SystemSettingsCredentialsProvider`：综合系统设置获取凭证。
* `WebIdentityTokenFileCredentialsProvider`：通过Web身份令牌文件获取凭证。

更多可以查看EKS官网了解不同类型的授权策略；<https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authentication-strategies>

## 参考资料

[Amazon EKS cluster IAM role](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html)

[Enabling IAM principal access to your cluster](https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html?source=post_page-----f69b485c674f--------------------------------)

[Enabling IAM users/roles Access on Amazon EKS cluster](https://medium.com/@radha.sable25/enabling-iam-users-roles-access-on-amazon-eks-cluster-f69b485c674f)

<https://repost.aws/zh-Hans/knowledge-center/eks-pods-iam-role-service-accounts>

[EKS OpenID Connect Tokens](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens)
