Published on

AWS IAM Intro

Authors
  • avatar
    Name
    Guming
    Twitter

AWS IAM 角色安全最佳实践白皮书

1.0 引言:IAM 角色在现代云安全中的核心地位

在复杂的云环境中,精确控制"谁可以做什么"至关重要,而 IAM 角色为此提供了强大而灵活的机制。其核心价值在于通过提供临时安全凭证,而非给予永久性的密码或访问密钥,从根本上降低了凭证泄露带来的风险,极大地增强了整体安全态势。

2.0 IAM 核心概念回顾

在深入探讨 IAM 角色的复杂性之前,有必要回顾构成 AWS Identity and Access Management (IAM) 基础的几个核心概念。对这些构建块的清晰理解,是正确实施和保护 IAM 角色的前提,也是构建稳固云安全架构的基石。

委托人 (Principals)

委托人是在 AWS 中可以执行操作的身份实体。IAM 中主要有三种类型的委托人:

  • 用户 (Users): 代表与 AWS 交互的个人或应用程序。每个用户都拥有一组长期凭证,例如用于控制台登录的密码或用于 API 调用的访问密钥。
  • 角色 (Roles): 是一种不与特定个人关联的身份,它可以被需要它的任何可信实体(如 IAM 用户、应用程序或 AWS 服务)代入。角色不具备长期凭证,而是提供临时安全凭证。
  • 组 (Groups): 是 IAM 用户的集合,用于简化权限管理。通过将用户添加到组中,可以为一组用户统一应用权限策略,而不是为每个用户单独管理。

资源与 ARN (Resources and ARNs)

在 AWS 中,每一个实体,无论是计算实例、存储桶还是数据库表,都是一个资源。为了在策略中唯一地标识这些资源,AWS 使用了 Amazon 资源名称 (Amazon Resource Identifiers, ARN)。ARN 是一种标准化的字符串格式,包含了服务、区域、账户ID和具体的资源标识符。

以下是一些 ARN 的示例:

  • Amazon S3 存储桶: arn:aws:s3:::my-bucket
  • Amazon EC2 实例: arn:aws:ec2:eu-west-1:123456789012:instance/i-01234567890abcdef
  • Amazon RDS 数据库: arn:aws:rds:eu-west-1:123456789012:db:mydatabase
  • Amazon DynamoDB 表: arn:aws:dynamodb:eu-west-1:123456789012:table/mytable

通过使用 ARN,我们可以在权限策略中精确地指定操作所作用的对象,这是实现精细化访问控制的基础。

策略 (Policies)

策略是定义权限的 JSON 文档,它明确规定了委托人可以对哪些资源执行哪些操作。一个策略由一个或多个声明(Statement)组成,每个声明都包含以下关键元素:

元素 描述 Version 策略语言的版本。推荐使用最新的 2012-10-17。 Statement 包含一个或多个具体权限声明的容器。 Effect 声明的效果,可以是 Allow(允许)或 Deny(拒绝)。一个明确的 Deny 总是优先于 Allow。 Action 一个或多个被允许或拒绝的具体 API 操作,例如 s3:GetObject。 Resource 该声明所作用的一个或多个资源的 ARN。 Condition (可选)应用该声明必须满足的特定条件,例如请求来源的 IP 地址或是否使用了多因素认证 (MFA)。

策略示例 A:允许特定 S3 操作

以下策略允许其关联的委托人从名为 mydata 的 S3 存储桶中读取任何对象。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowGetObject",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::mydata/*"
    }
  ]
}

分析:

  • Effect: "Allow": 授予权限。
  • Action: "s3:GetObject": 明确指定了允许的操作是“获取对象”。
  • Resource: "arn:aws:s3:::mydata/": 将权限范围限定在 mydata 存储桶内的所有对象(由 / 通配符表示)。

策略示例 B:基于 IP 地址进行拒绝

以下策略拒绝来自指定 IP 范围之外的所有请求对任何资源执行任何操作。这是一种强大的安全控制,常用于限制对敏感环境的访问。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyIPRange",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": [
            "192.0.2.0/24",
            "203.0.113.0/24"
          ]
        }
      }
    }
  ]
}

分析:

  • Effect: "Deny": 这是一个拒绝策略,其优先级高于任何允许策略。
  • Action: "" 和 Resource: "": 作用于所有操作和所有资源。
  • Condition: 策略生效的关键。NotIpAddress 条件表示,如果请求的源 IP (aws:SourceIp) 不在 192.0.2.0/24 或 203.0.113.0/24 范围内,则此 Deny 声明生效。这在保护内部管理端点或仅限特定办公室访问的敏感数据源时尤为关键。

在掌握了这些基础知识后,我们将重点转向 IAM 角色本身的复杂性和其独特的安全含义。


3.0 深入解析 IAM 角色:信任与权限

IAM 角色与 IAM 用户的根本区别在于其独特的双重策略结构:它既需要定义谁可以代入它,也需要定义它可以做什么。IAM 角色本身不与任何特定个人绑定,而是设计为可被需要它的实体临时“代入”。理解角色的信任策略和权限策略这两个关键组成部分,是设计安全访问模式、防范安全风险的第一步。

3.1 信任策略:定义“谁可以代入”

信任策略 (Trust Policy) 是 IAM 角色的安全边界,它精确定义了哪些委托人(Principals)被授权调用 sts:AssumeRole API 来代入该角色。如果一个委托人没有在信任策略中被明确列出,它就绝无可能获得该角色的临时凭证。

这是一个典型的允许 AWS Lambda 服务代入角色的信任策略示例:

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Principal": {
      "Service": "lambda.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
  }
}

分析:

  • Effect: "Allow": 声明此策略是授予权限。
  • Principal: { "Service": "lambda.amazonaws.com" }: 这是信任策略的核心。它指定了可信的委托人是 AWS Lambda 服务。这意味着只有 Lambda 服务本身有权代入此角色。其他委托人,如某个 IAM 用户或其他 AWS 服务,都将被拒绝。
  • Action: "sts:AssumeRole": 明确授权了“代入角色”这一操作。

任何对信任策略的错误配置,例如错误地信任了整个 AWS 账户 ("AWS": "arn:aws:iam::123456789012:root") 而非特定角色,都可能导致严重的安全风险,必须严格审查。

3.2 权限策略:定义“可以做什么”

一旦角色被成功代入,其权限策略 (Permission Policy) 就决定了代入者可以执行哪些操作、可以访问哪些资源。这些策略与附加给 IAM 用户的策略在结构和语法上完全相同。

附加权限策略主要有两种方式:

  1. 内联策略 (Inline Policies): 直接嵌入在角色定义中的策略。它们与角色是一对一的关系,当角色被删除时,内联策略也随之消失。
  2. 托管策略 (Managed Policies): 独立于角色的策略资源,可以附加到多个角色、用户或组。它们分为两种:
  • AWS 托管策略 (AWS Managed Policies): 由 AWS 创建和管理,用于常见的用例,例如 AWSLambdaBasicExecutionRole。
  • 客户自定义托管策略 (Customer Managed Policies): 由您在自己的 AWS 账户中创建和管理,提供了更高的可重用性和版本控制能力。

特别注意: 使用 AWS 托管策略虽然方便,但也存在潜在风险。因为 AWS 有能力在任何时候更新它们,这种更新可能会在您不知情的情况下,无意中为角色授予超出预期的过多权限,或导致与其他策略的权限冲突。因此,对于需要严格控制权限的生产环境,最佳实践是创建并使用客户自定义的托管策略。

3.3 服务角色与服务相关角色

当 AWS 服务需要代表您访问其他服务中的资源时,通常会使用特定类型的 IAM 角色。这主要分为服务角色和服务相关角色。

特性 服务角色 (Service Roles) 服务相关角色 (Service-Linked Roles) 创建方式 由用户手动创建,或通过服务的初始配置向导创建。 由 AWS 服务在特定操作时自动创建,预先定义好。 权限可修改性 用户可以完全自定义和修改附加到该角色的权限策略。 权限策略由 AWS 定义和管理,用户无法修改。 管理责任 用户负责角色的生命周期管理和权限维护。 AWS 负责角色的策略更新和维护,简化了用户的管理负担。 核心目的 为服务提供由用户定义的灵活权限,适用于自定义集成场景。 通过 AWS 预定义的安全权限集来简化管理并降低配置错误的风险。

服务相关角色通过将权限管理责任转移给 AWS,降低了因用户配置不当而引入安全风险的可能性,是 AWS 推荐的安全实践。

理解了角色的内部构造后,下一步是分析与角色相关的、可能导致安全漏洞的关键操作和必须掌握的高级控制机制。


4.0 关键安全机制与高级策略

正确配置 IAM 角色不仅是授予权限,更重要的是实施强大的预防性安全控制。为了防止权限被滥用或意外升级,安全专业人员必须掌握几个高级机制。本节将聚焦于这些机制,它们是构建纵深防御体系的关键组成部分。

4.1 iam:PassRole 与权限提升风险

iam:PassRole 是一项特殊权限,它允许一个委托人(如 IAM 用户)将一个 IAM 角色传递给一个需要代入该角色的 AWS 服务(如启动一个 EC2 实例或创建一个 Lambda 函数)。这本质上是授权一个用户决定某个服务将以何种权限运行。

如果 iam:PassRole 权限的配置过于宽泛,它将构成一个严重的权限提升 (Privilege Escalation) 风险。

风险场景分析: 假设一个权限有限的开发者用户拥有无限制的 iam:PassRole 权限 ("Resource": "*")。虽然该用户自身无法直接访问生产数据库,但他可以创建一个 EC2 实例,并将一个拥有完全数据库访问权限的管理员角色传递给这个实例。然后,他只需登录到该 EC2 实例,就可以通过实例的元数据服务获取管理员角色的临时凭证,从而间接获得了远超其自身权限的访问能力。

为了缓解此风险,必须严格限制 iam:PassRole 权限的范围。最佳实践是仅允许用户传递预先批准的、权限受限的角色。

安全策略示例: 以下策略仅允许用户将 lambda-role 这一个特定的角色传递给服务:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/lambda-role"
    }
  ]
}

通过在 Resource 字段中明确指定角色的 ARN,可以有效阻止用户传递高权限角色,从而切断这条常见的权限提升路径。因此,安全策略的最佳实践是,iam:PassRole 的 Resource 字段绝不应使用通配符 (*)。

4.2 权限边界 (Permission Boundaries)

权限边界是一种高级安全功能,用于为一个 IAM 实体(用户或角色)设置其所能拥有的最大权限上限。它本身不授予任何权限,而是像一道“护栏”,规定了该实体最终能够行使的权限范围。

其核心价值在于安全地委派管理任务。例如,您可以允许高级开发人员创建新的 IAM 角色以满足应用需求,但同时为他们附加一个权限边界,确保他们创建的任何新角色,其权限都不能超过预设的范围(例如,不能创建管理员角色或修改网络安全配置)。

最终的有效权限是身份策略 (Identity-based Policies) 和权限边界 (Permission Boundary) 所允许权限的交集。即使身份策略中授予了某项权限,但如果该权限未在权限边界中被允许,该实体也无法执行相应操作。例如,您可以授予一名团队负责人创建 IAM 角色的权限,但通过附加一个权限边界,来确保他创建的任何角色都无法拥有修改网络配置 (ec2:CreateVpc) 或删除日志 (logs:DeleteLogGroup) 的权限,即使他在角色的身份策略中尝试授予这些权限也不行。

4.3 跨账户访问策略

IAM 角色是实现安全的跨 AWS 账户资源访问的核心机制。当一个账户(例如,111122223333)中的用户需要访问另一个账户(例如,123456789012)中的资源时,可以在目标账户中创建一个角色,并在其信任策略中明确信任源账户。

以下是一个安全的跨账户信任策略示例,它不仅信任了特定的 AWS 账户,还强制要求代入角色的实体必须使用多因素认证 (MFA):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Principal": {
        "AWS": "123456789012"
      },
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

分析:

  • Principal: { "AWS": "123456789012" }: 明确指定只有来自账户 ID 为 123456789012 的委托人才能代入此角色。
  • Condition: 这是一个关键的额外安全层。"aws:MultiFactorAuthPresent": "true" 条件块强制要求代入请求必须是在通过 MFA 验证的会话中发起的。这种策略常用于为中央审计或日志记录账户提供对其他成员账户的安全只读访问权限,同时通过MFA强制确保操作者身份的强验证。

掌握了这些高级安全机制后,同样重要的是在日常操作中采用标准化的部署和管理流程,以确保安全策略能够被一致、可靠地执行。


5.0 IAM 角色的部署与管理最佳实践

理论上的安全策略必须通过可靠和可重复的实践来落地。手动配置,尤其是在复杂的生产环境中,容易出错且难以审计。本节将评估不同的 IAM 角色创建和管理方法,并为生产环境提供明确的、基于自动化和代码化的最佳实践。

5.1 基础设施即代码 (IaC) 的必要性

创建 IAM 角色主要有三种方式:AWS 管理控制台、AWS 命令行界面 (CLI) 和基础设施即代码 (IaC) 工具。

  • AWS 管理控制台: 直观易用,适合学习、实验和快速原型设计。但其手动点击操作的方式难以追踪、复现和审计,不适用于严肃的生产环境。
  • AWS CLI: 适合脚本化和简单的自动化任务。然而,依赖于命令式脚本来管理复杂的 IAM 配置仍然可能变得脆弱和难以维护。
  • 基础设施即代码 (IaC): 使用 Terraform、AWS CloudFormation 或 CDK 等工具,以声明式代码的形式定义 IAM 角色及其策略。这是管理生产级 IAM 资源的唯一推荐方法。

采用 IaC 的核心优势在于:

  1. 可复现性 (Reproducibility): 同一份代码可以在不同环境(如开发、测试、生产)中部署完全一致的 IAM 配置,消除了“环境漂移”问题。
  2. 轻松监管 (Oversight): IAM 配置作为代码存储在版本控制系统(如 Git)中,所有变更都经过代码审查 (Code Review),有明确的变更历史和责任人,极大地提升了安全性和可审计性。
  3. 自动化与一致性: IaC 能够确保安全策略的自动化和一致性部署,避免了人为错误。

以下是使用 Terraform 创建一个 Lambda 服务角色的具体 IaC 示例 (main.tf):

provider "aws" {
  region = "eu-west-1"
}

定义 IAM 角色及其信任策略

resource "aws_iam_role" "example_role" {
  name = "lambda-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action    = "sts:AssumeRole"
        Effect    = "Allow"
        Principal = {
          Service = "lambda.amazonaws.com"
        }
      }
    ]
  })
}

将一个 AWS 托管的权限策略附加到该角色

resource "aws_iam_role_policy_attachment" "policy" {
  policy_arn = "arn:aws:iam::aws:policy/AWSLambdaBasicExecutionRole"
  role       = aws_iam_role.example_role.name
}

5.2 角色担任流程与临时凭证管理

从技术角度看,代入一个角色的流程如下:

  1. 一个经过授权的委托人调用 AWS Security Token Service (STS) 的 AssumeRole API,并提供要代入的角色的 ARN。
  2. STS 验证该委托人是否在该角色的信任策略中被允许。
  3. 验证通过后,STS 生成并返回一组临时安全凭证。这组凭证包含三个部分:
  • AccessKeyId
  • SecretAccessKey
  • SessionToken

这些凭证与永久性的 IAM 用户访问密钥的关键区别在于它们具有有限的生命周期(例如,默认为1小时,最长可配置)。一旦过期,这些凭证将自动失效。这一特性本身就是一项重要的安全机制,因为它极大地缩短了凭证意外泄露后可能被滥用的时间窗口,显著降低了安全风险。

将这些技术实践与组织层面的宏观安全治理相结合,才能构建一个真正稳固的云安全态势。


6.0 组织级 IAM 安全治理

在大型或多账户环境中,仅依赖于单个 IAM 角色的精细配置是远远不够的。必须建立一个全面的治理框架,将安全策略从顶层向下强制执行,以实现规模化的、一致的安全控制。

6.1 禁用根用户并强制执行多因素认证 (MFA)

这是 AWS 安全的最基本也是最重要的两条原则:

  1. 停用根用户凭证: AWS 账户的根用户拥有不受限制的最高权限。应立即将其长期凭证(密码和访问密钥)锁定,并仅在极少数必须使用根用户的账户管理任务时才启用。绝不应使用根用户进行任何日常操作。
  2. 强制执行 MFA: 凭证泄露是账户被盗的最常见原因。为所有人类用户(包括根用户和所有 IAM 用户)强制启用多因素认证 (MFA) 是抵御此类攻击最有效的单一措施。

您可以通过附加一个 IAM 策略来强制用户组必须使用 MFA 才能执行操作。以下策略拒绝了除管理自身 MFA 设备和凭证之外的所有操作,除非请求是通过 MFA 认证的。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyAllExceptListedIfNoMFA",
      "Effect": "Deny",
      "NotAction": [
        "iam:CreateVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:GetUser",
        "iam:ListMFADevices",
        "iam:ListVirtualMFADevices",
        "iam:ResyncMFADevice",
        "sts:GetSessionToken"
      ],
      "Resource": "*",
      "Condition": {
        "BoolIfExists": {
          "aws:MultiFactorAuthPresent": "false"
        }
      }
    }
  ]
}

6.2 利用 AWS Organizations 和服务控制策略 (SCPs)

AWS Organizations 允许您将多个 AWS 账户集中到一个组织中进行统一管理。在此基础上,服务控制策略 (Service Control Policies, SCPs) 提供了一种强大的顶层治理工具。

SCPs 的作用机制是为组织单元 (OU) 或单个账户设置权限的最大边界或护栏。它们本身不授予任何权限,而是定义了该 OU 内所有 IAM 实体(用户和角色)永远不能超过的权限上限。即使一个 IAM 角色拥有管理员权限,如果 SCP 禁止了某项操作,该角色也无法执行该操作。

例如,以下 SCP 可以在整个组织范围内禁止任何实体附加 AWS 托管的 AdministratorAccess 策略,以强制执行使用自定义、权限更小的管理员角色的安全规定:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "iam:AttachRolePolicy",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "iam:PolicyARN": "arn:aws:iam::aws:policy/AdministratorAccess"
        }
      }
    }
  ]
}

请注意,这只是一个示例性控制,它仅阻止了通过附加此特定托管策略来获取管理员权限的路径,攻击者仍可能通过其他方式提升权限。

6.3 身份联合与 AWS Identity Center

在大型组织中,为每位员工在 AWS 中创建和维护一个本地 IAM 用户是不可扩展且不安全的。最佳实践是采用身份联合 (Identity Federation),将 AWS 与您现有的身份提供商 (IdP),如 Okta、Azure AD 或其他支持 SAML 的系统,进行集成。在大型组织中,通常建议使用身份联合而非创建大量本地 IAM 用户。

AWS Identity Center (前身为 AWS SSO) 是实现这一目标的核心服务。它可以作为连接外部 IdP 的中心枢纽,也可以作为内置的 IdP 使用。通过 Identity Center,您可以集中管理对整个 AWS 组织中所有账户和应用程序的单点登录 (SSO) 访问。用户使用其熟悉的企业凭证登录一次,即可根据预设的权限集(Permission Sets)代入不同账户中的角色,无需管理任何长期的 AWS 访问密钥。这种方式极大地简化了用户访问管理,并提升了安全性和审计能力。