跳至内容
aws
aws-IAM身份

aws-IAM身份

IAM

身份认证

核心要素

  • 资源: 需要操作的对象
  • 动作: 可以对这个对象 进行某些操作
  • 身份: 谁

其它要素

  • 策略: 也就是 权限, 即 资源+动作 的绑定;
  • 角色: 身份集合, 可以把策略绑定给角色
  • 用户

策略

  • user-policy: 直接附加到单个 IAM 用户上的权限策略, 尽量少用
  • group-policy: 附加到 IAM 用户组上的权限策略,组内所有用户继承该权限
  • role-policy: 附加到 IAM 角色上的权限策略

一般模式

人员: group + group-policy 程序: role + role-policy CICD: Role Policy + OIDC

管理 cli

https://docs.aws.amazon.com/zh_cn/cli/latest/userguide/cli_iam_code_examples.html

aws iam list-users
aws iam list-groups
aws iam list-roles
aws iam list-user-policies --user-name Bob
aws iam list-role-policies --role-name Test-Role
aws iam list-policies --max-items 3                 # 可用的托管策略

用户+组

aws iam create-user --user-name Bob
aws iam delete-user --user-name Bob

aws iam create-group --group-name MyTestGroup
aws iam delete-group --group-name MyTestGroup

aws iam add-user-to-group --user-name Bob --group-name Admins

角色

# 创建角色 + 附加策略
aws iam create-role --role-name Test-Role \
    --assume-role-policy-document file://Test-Role-Trust-Policy.json

aws iam delete-role --role-name Test-Role

策略

aws iam delete-user-policy --user-name Bob --policy-name ExamplePolicy
aws iam delete-group-policy --group-name Admins --policy-name ExamplePolicy
aws iam delete-role-policy --role-name Test-Role --policy-name ExamplePolicy
aws iam delete-policy --policy-arn arn:aws:iam::123456789012:policy/MySamplePolicy


# 将策略附加到组
aws iam attach-group-policy --group-name Finance \
    --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

# 将策略附加到角色
aws iam attach-role-policy --role-name ReadOnlyRole \
    --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

# 将策略附加到用户
aws iam attach-user-policy --user-name Alice \
    --policy-arn arn:aws:iam::aws:policy/AdministratorAccess \

# 新建权限策略, 并附加到 IAM 角色
aws iam put-role-policy --role-name Test-Role \
    --policy-name ExamplePolicy --policy-document file://AdminPolicy.json

用户密码


# 更新当前用户密码, 注意不能是 root iam 用户;

# 先生成一个标准格式文件, 然后在文件内填入旧密码和新密码
aws iam change-password --generate-cli-skeleton > change-password.json
# 变更密码
aws iam change-password --cli-input-json file://change-password.json

# 修改其他用户的密码 - 需要管理员权限
aws iam update-login-profile --user-name user_name --password new_pw

# 修改其他用户的密码 - 需要管理员权限 - 下次登录必须修改
aws iam update-login-profile --user-name Bob \
    --password "TemporaryP@ss123" --password-reset-required

sts


# 获取当前身份
aws sts get-caller-identity --region ap-southeast-1

# # 获取当前账号ID
ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)

# 验证当前使用的身份, 输出 ARN 地址
aws sts get-caller-identity
aws sts get-caller-identity --query Arn --output text

审计

# 查看谁在 AssumeRole
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRoleWithWebIdentity \
  --start-time "2024-01-01T00:00:00Z"

特殊权限说明

iam:PassRole

授权, 授权这个系统可以使用自己 角色的权限

一般可以通过 --role-arn xxxx 参数进行显式指定授于的角色

{
    "Version": "2012-10-17",
    "Statement": [

        // 传递角色权限, 如果要创建资源, 必须要能传递自身的权限
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",       // 允许传递 IAM 角色
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:PassedToService": "eks.amazonaws.com"  // 角色只能传递给 EKS 服务
                }
            }
        }
    ]
}

凭证使用

操作场景

  1. 人工 ui 操作: 账号 + 密码 + 二次验证
  2. 本地 cli: aws_access_key_id + aws_secret_access_key
  3. 生产环境程序: 不注入任何密码和 key 信息, 程序从环境中获取身份

本地环境

  • 方式 1: aws_access_key_id + aws_secret_access_key 有特权的长期凭证

  • 方式 2: aws_access_key_id + aws_secret_access_key 无特权的长期凭证 + 通过 sts api AssumeRole 获取短期临时凭证 aws_session_token;

~/.aws/credentials

[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws_session_token = xxxxxxxxxx

env 注入

AWS_ACCESS_KEY_ID=x
AWS_SECRET_ACCESS_KEY=x
AWS_SESSION_TOKEN=x
# 临时切换到一个角色(AssumeRole), 返回结果中包含 SessionToken
aws sts assume-role \
    --role-arn "arn:aws:iam::123456789012:role/MyRole" \
    --role-session-name "MySession"

从环境中获取身份

将一个 IAM 角色 附加到这些计算资源上 运行在该资源上的 AWS SDK 会自动通过实例元数据服务 (IMDS) 或容器凭证端点来获取临时的, 动态刷新的凭证

对于 aws 原生资源(ec2 等) 默认有一个 IAM 角色; 所以实际是将权限 附加策略 给默认 IAM 角色

# EC2 实例元数据服务, 也会获取到 AWS_SESSION_TOKEN
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/MyRole

sdk_auth

不要在代码或配置文件里存储任何 Access Key 程序里面只需要使用默认方法创建客户端即可;

import boto3
s3 = boto3.client('s3')         # 直接创建客户端
import software.amazon.awssdk.services.s3.S3Client;
S3Client s3 = S3Client.create();    // 直接创建客户端, 无需任何凭证相关配置
import "github.com/aws/aws-sdk-go-v2/service/s3"
client := s3.NewFromConfig(aws.Config{Region: "us-west-2"})     // 直接创建客户端

原理

SDK 会按照预定义的顺序检查一系列位置来寻找凭证, 一旦找到有效的凭证就停止搜索

EKS Pod Identity

在 Pod 内启动了一个本地代理(Agent)来负责凭证的获取和刷新

  1. 注入环境变量 当 Pod 启动时, EKS 集群会自动向 Pod 注入特定的环境变量和挂载卷 AWS_CONTAINER_CREDENTIALS_FULL_URI 指向节点上 Agent 的本地地址 (http://169.254.170.23/v1/credentials

AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE 指向一个服务账户令牌文件

  1. SDK 在默认凭证链中, 会发现 AWS_CONTAINER_CREDENTIALS_FULL_URI 这个环境变量, 从而知道应该向本地的 Agent 请求凭证

  2. Agent 代理请求: Agent 收到 SDK 的请求后, 会使用挂载的令牌文件, 通过调用 EKS Auth API 的 AssumeRoleForPodIdentity 接口, 来获取与 Pod 服务账户关联的 IAM 角色的临时凭证

  3. 返回临时凭证: Agent 将获取到的临时凭证返回给 SDK

IRSA (IAM Roles for Service Accounts)

让 SDK 直接与 AWS STS 服务交互来换取凭证, 没有本地代理, 需要集群拥有 OIDC 终端节点

  1. 注入环境变量: 集群的 Webhook 会自动为 Pod 注入以下环境变量; AWS_ROLE_ARN: 需要扮演的 IAM 角色 ARN; AWS_WEB_IDENTITY_TOKEN_FILE: 指向一个 OIDC 令牌文件的路径;

  2. SDK 交换令牌: 应用程序的 SDK 在默认凭证链中, 会发现 AWS_WEB_IDENTITY_TOKEN_FILE 和 AWS_ROLE_ARN 环境变量, 于是知道需要通过 OIDC 方式获取凭证;

  3. 调用 STS 服务: SDK 会读取令牌文件内容, 然后直接调用 AWS STS 服务的 AssumeRoleWithWebIdentity API, 将令牌发送给 STS 服务以交换临时凭证;

  4. 使用临时凭证: STS 服务验证令牌后, 返回临时凭证给 SDK, SDK 随后使用这些凭证调用 AWS 服务

EKS Pod Identity

较新的, 更简单的方案, 无需配置 OIDC

  1. 安装 EKS Pod Identity 代理: 确保集群已安装 eks-pod-identity-agent 插件
  2. 创建 IAM 角色, 附加业务策略, 角色的信任策略 (Trust Policy) 需要允许 Pod Identity 服务代为获取凭证
  3. 创建 Pod Identity 关联: 将 IAM 角色与特定的 Kubernetes 服务账户 (Service Account) 关联起来
  4. 在 Pod 中指定服务账户: 在 Pod 的 YAML 文件中, 通过 serviceAccountName 字段指定上述服务账户

定义 IAM 角色的信任策略 (Trust Policy) 是明确谁(AWS 服务)可以扮演(Assume)这个角色

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowEksAuthToAssumeRoleForPodIdentity",
      "Effect": "Allow",
      "Principal": {
        // 授权 EKS 的 Pod Identity 服务本身来扮演此角色
        "Service": "pods.eks.amazonaws.com"
      },
      "Action": [
        "sts:AssumeRole",       // 允许执行角色扮演操作

        // 允许在扮演角色时添加会话标签(Session Tags)
        // 这些标签可以用于在 IAM 策略中实施更细粒度的权限控制(ABAC)
        "sts:TagSession"
      ],

      // 可选条件限制
      "Condition": {
        "StringEquals": {
          "aws:RequestTag/kubernetes-namespace": ["your-namespace"],
          "aws:RequestTag/kubernetes-service-account": ["your-service-account"]
        }
      }

    }
  ]
}

创建 Pod Identity 关联:

将创建好的 IAM 角色, 与你 Kubernetes 集群中的服务账户(ServiceAccount)绑定起来

aws eks create-pod-identity-association \
    --cluster-name your-cluster-name \
    --namespace your-namespace \
    --service-account your-service-account \
    --role-arn arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>
最后更新于