为什么我们需要 assume-role?告别“一把钥匙开所有门”

187 阅读5分钟

为什么我们需要 assume-role?告别“一把钥匙开所有门”

在早期的运维工作中,我们可能会为了方便,创建一个拥有高权限的 IAM User,并将其长期有效的访问密钥(Access Key)配置在各种服务器和开发人员的电脑上。这种方式虽然简单直接,但却隐藏着巨大的安全风险:

  • 密钥泄露风险:长期有效的密钥一旦泄露,攻击者就能长驱直入,后果不堪设 सेम。
  • 权限管理混乱:难以区分操作者身份,所有操作都源自同一个 IAM User,审计追溯变得异常困难。
  • 跨账户协作笨拙:在多账户环境下,管理和分发不同账户的密钥简直是一场噩梦。

为了解决这些问题,AWS 引入了 IAM Role 和临时安全凭证机制。而 aws sts assume-role 正是获取这种临时凭证的核心命令。

核心理念:IAM Role 是一种没有长期密钥的身份,它定义了一套权限。其他受信任的实体(如 IAM User、EC2 实例或其他 AWS 服务)可以通过“扮演”(Assume)这个角色,来临时获取该角色所拥有的权限。 这些临时凭证包含一个访问密钥 ID、一个私有访问密钥和一个会话令牌,并且它们都有一个明确的过期时间。

image.png

assume-role 的工作原理解析:信任的双向奔赴

要成功扮演一个角色,需要建立一个“双向信任”的关系,这由两个关键的策略(Policy)来定义:

  1. 信任策略(Trust Policy):这是附加在**被扮演角色(Role)**上的策略。它明确规定了“谁可以扮演我这个角色”。策略中必须允许受信实体执行 sts:AssumeRole 操作。

    打个比方:这就像一个VIP休息室的门禁规则,规定了只有持有特定邀请函(比如来自特定公司或特定个人)的人才能进入。

    示例 Trust Policy

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": { "AWS": "arn:aws:iam::111122223333:user/DevUser" },
          "Action": "sts:AssumeRole"
        }
      ]
    }
    

    这个策略表示,只有账户 111122223333 中的用户 DevUser 才有权扮演这个角色。

  2. 权限策略(Permissions Policy):这是附加在**发起者(IAM User)**身上的策略。它规定了“谁可以去扮演哪些角色”。

    打个比方:这就像是我们本人持有的那张“邀请函”,上面写着我们可以进入哪个VIP休息室。

    示例 Permissions Policy

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "sts:AssumeRole",
          "Resource": "arn:aws:iam::444455556666:role/TargetRole"
        }
      ]
    }
    

    这个策略允许该用户去扮演账户 444455556666 中名为 TargetRole 的角色。

只有当这两个策略同时满足条件时,assume-role 操作才能成功。

实战演练:如何使用 aws sts assume-role

1. 基本命令与参数

最基础的命令格式如下:

aws sts assume-role \
    --role-arn "arn:aws:iam::444455556666:role/TargetRole" \
    --role-session-name "MyWebAppSession"
  • --role-arn: 我们想要扮演的角色的 ARN (Amazon Resource Name)。这是角色的唯一标识。
  • --role-session-name: 一个自定义的会话名称。这个名称会出现在 CloudTrail 日志中,对于审计和问题追溯至关重要。强烈建议设置为能够识别操作来源的有意义的名称,比如 user-john-debug-s3-issue

成功执行后,我们会得到一串 JSON 输出,其中包含了最重要的 Credentials 对象:

{
    "Credentials": {
        "AccessKeyId": "ASIA...",
        "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY",
        "SessionToken": "AQoDYXdzEJr...",
        "Expiration": "2025-06-26T03:52:00Z"
    },
    ...
}

2. 使用临时凭证

获取到临时凭证后,我们需要将它们配置为环境变量,以便后续的 AWS CLI 命令或其他工具能够使用它们。

export AWS_ACCESS_KEY_ID="ASIA..."
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY"
export AWS_SESSION_TOKEN="AQoDYXdzEJr..."

配置完成后,我们在当前终端会话中执行的所有 aws 命令都将使用这个临时角色的身份和权限。一旦关闭这个终端,或者凭证过期,这些环境变量就会失效。

实用技巧:手动复制粘贴太麻烦?试试这个结合了 jqexport 的一行命令:

export $(aws sts assume-role --role-arn "arn:aws:iam::ACCOUNT_B_ID:role/ROLE_NAME" --role-session-name "my-session" --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" --output text | awk '{printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s", $1, $2, $3}')

3. 运维最佳实践:使用 AWS CLI Profile

手动导出环境变量的方式虽然可行,但既不优雅也容易出错。在日常运维中,我们强烈推荐使用 AWS CLI 的 Profile 功能来自动完成 assume-role 的过程。

这种方法只需要配置一次,之后就可以通过一个简单的参数无缝切换角色。

配置步骤

  1. ~/.aws/credentials 文件:存放我们的长期 IAM User 密钥。

    [default]
    aws_access_key_id = YOUR_IAM_USER_KEY
    aws_secret_access_key = YOUR_IAM_USER_SECRET
    
  2. ~/.aws/config 文件:定义角色扮演的规则。

    [profile cross-account-admin]
    role_arn = arn:aws:iam::444455556666:role/TargetRole
    source_profile = default
    region = us-east-1
    
    • [profile cross-account-admin]: 定义了一个名为 cross-account-admin 的新配置。
    • role_arn: 指定了要扮演的目标角色。
    • source_profile: 指定使用哪个 profile(这里是 default)的凭证来发起 sts:AssumeRole 调用。

如何使用

现在,当我们想用 TargetRole 的身份操作时,只需在命令后加上 --profile 参数即可:

# 使用扮演的角色身份列出S3存储桶
aws s3 ls --profile cross-account-admin

AWS CLI 会在后台自动调用 sts:AssumeRole,获取临时凭证并用它们来执行命令。整个过程对用户透明,既安全又高效。

总结

aws sts assume-role 是 AWS 安全体系的基石之一。掌握它,意味着我们能够:

  • 实现最小权限原则:仅在需要时授予必要的临时权限。
  • 提升安全性:避免长期密钥的使用和泄露风险。
  • 简化跨账户管理:轻松、安全地在多个 AWS 账户之间进行操作。
  • 增强可审计性:通过 role-session-name 精确追踪每一个操作的来源。

对于 AWS 运维工程师而言,请务必将“使用 CLI Profile 扮演角色”作为我们的标准操作流程。这不仅是衡量专业性的一个标准,更是保护云上资产安全的最佳实践。