发布于: Oct 30, 2022

云存储安全性大概是每个使用云存储功能的客户都关心的问题,尤其是如何限制其他用户的访问权限,更是大家关注的重点,本文将会介绍如何将 Amazon S3 存储桶的访问权限到一个特定 IAM 角色。

您可以使用 IAM S3 存储桶策略的 NotPrincipal 元素,仅限特定用户组访问资源。此元素允许您阻止未在其值数组中定义的所有用户,即使他们自己的 IAM 用户策略中具有 Allow 也是如此。因此,如果您有一个用户应该可以访问除 S3 中的某个存储桶以外的所有存储桶,则可以在该存储桶本身上进行此定义,而无需编辑用户的 IAM 策略堆栈。

但对于 IAM 角色来说,这要更为复杂,因为角色是由 Principal 中的两个 ARN 定义的:role ARN  assumed-role ARNrole ARN (arn:aws:iam::ACCOUNTNUMBER:role/ROLE-NAME) 是静态的,独立于角色会话发起者。(在本文中,切记将 placeholder information 替换为您自己的账户信息。)assumed-role ARN (arn:aws:sts::ACCOUNTNUMBER:assumed-role/ROLE-NAME/ROLE-SESSION-NAME) 将因为角色会话名称定义的内容而异。对于具有一个角色的用户发出的 API 调用,您可以通过查看 Amazon CloudTrail 条目中的以下 Identity 元素来了解此信息。

{
  "type": "AssumedRole",
  "principalId": "AROAJI4AVVEXAMPLE:ROLE-SESSION-NAME",
  "arn": "arn:aws:sts::ACCOUNTNUMBER:assumed-role/ROLE-NAME/ROLE-SESSION-NAME",
  "accountId": "ACCOUNTNUMBER",
  "accessKeyId": "ASIAEXAMPLEKEY",
  "sessionContext": {
    "attributes": {
      "mfaAuthenticated": "false",
      "creationDate": "XXXX-XX-XXTXX:XX:XXZ"
    },
    "sessionIssuer": {
      "type": "Role",
      "principalId": "AROAJI4AVV3EXAMPLEID",
      "arn": "arn:aws:iam::ACCOUNTNUMBER:role/ROLE-NAME",
      "accountId": "ACCOUNTNUBMER",
      "userName": "ROLE-SESSION-NAME"
    }
  }
}

在此 Identity 元素中,您可以看到 role ARN assumed-role ARN。根据承担角色的用户不同,ROLE-SESSION-NAME 也可能会有所变化。

principalId 值也包含此信息,但采用可以在存储桶策略的 Principal 元素以外使用的方式设置格式。在编写存储桶策略时,我会使用这些信息向特定角色授予同账户存储桶访问权限。

在从同一账户访问存储桶时,在大多数情况下不必使用存储桶策略。这是因为存储桶策略定义了已由用户的直接 IAM 策略授予的访问权限。S3 存储桶策略通常用于跨账户访问,但您也可以使用它们,通过显式 Deny 来限制访问,这将应用于所有主体,无论是与存储桶位于相同账户中还是不同账户中的主体。

每个 IAM 实体(用户、组或角色)都有一个已定义的 aws:userid 量。您需要在存储桶策略中使用此变量,才能在条件元素内以例外的形式指定角色或用户。assumed-role  aws:userId 值定义为 UNIQUE-ROLE-ID:ROLE-SESSION-NAME(例如 AROAEXAMPLEID:userdefinedsessionname)。

要获得 IAM 角色的 AROAEXAMPLEID,请执行以下操作:

  1. 务必安装 Amazon CLI,并打开一个命令提示符或 shell
  2. 运行以下命令:aws iam get-role -–role-name ROLE-NAME
  3. 在输出中,查找以 AROA 开头的 RoleId 字符串。您将在存储桶策略中使用它来将存储桶访问权限的范围仅限于此角色。

在前述 CloudTrail 代码示例中,此 ID  principalId 元素。此元素的值十分重要,因为 Amazon Web Services 策略变量也可以在 IAM 策略中作为字符串进行检查。您不必在 NotPrincipal 元素中指定 role  assumed-role ARN,而是可以将 StringNotLike 条件中的 aws:userId 值与通配符字符串一起使用。在 aws:userId 值内,您还需要添加账户的 Root 用户,以便在删除定义的角色时,不会致使存储桶完全无法访问。Root 账户的 userId 是账户编号。

使用您刚刚通过 Amazon CLI 检索的 AROAEXAMPLEID,即可创建条件逻辑,让存储桶策略将存储桶访问权限的范围仅限于访问存储桶时使用此角色的用户。使用条件逻辑而非 NotPrincipal 元素可支持使用通配符字符串,从而允许接受任何角色会话名称。

现在您已获得要允许其访问的角色 ID,接下来需要阻止与存储桶处于相同账户内的其他用户的访问。阻止未使用 IAM 角色或 Root 账户凭证的用户访问存储桶及其对象的策略如下所示。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::MyExampleBucket",
        "arn:aws:s3:::MyExampleBucket/*"
      ],
      "Condition": {
        "StringNotLike": {
          "aws:userId": [
            "AROAEXAMPLEID:*",
            "111111111111"
          ]
        }
      }
    }
  ]
}

您也可以对 IAM 用户使用相同的策略。IAM 用户拥有一个以 AIDA 开头的唯一 ID,您可以将此 ID 用于此用途。要查找此唯一 ID,请执行以下操作:

  1. 安装 Amazon CLI 后,打开命令提示符或 shell
  2. 运行命令:aws iam get-user -–user-name USER-NAME
  3. 在输出中,查找以 AIDAEXAMPLEID 开头的 userId 字符串。

找到 userId 字符串之后,您可以将其置于“aws:userId”条件数组中,如以下示例所示。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::MyExampleBucket",
        "arn:aws:s3:::MyExampleBucket/*"
      ],
      "Condition": {
        "StringNotLike": {
          "aws:userId": [
            "AROAEXAMPLEID:*",
            "AIDAEXAMPLEID",
            "111111111111"
          ]
        }
      }
    }
  ]
}

在上一节中,我向您展示了如何将 S3 存储桶访问权限限于同一个账户内的特定 IAM 角色或用户。现在,我将向您展示如何将访问权限限制到另一账户中的特定用户和角色。向 IAM 用户或角色授予跨账户存储桶访问权限时,您必须定义允许 IAM 用户或角色通过该访问权限执行哪些操作。在先前的 Amazon Web Services 安全性博客中,Jim Scharf 撰文介绍了允许 IAM 实体通过 CLI/API 和控制台访问存储桶所需的权限。利用之前这篇博文中提供的信息,CLI/API 级访问存储桶策略应如下所示。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:role/ROLENAME"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::MyExampleBucket"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:role/ROLENAME"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::MyExampleBucket/*"
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::MyExampleBucket",
                "arn:aws:s3:::MyExampleBucket/*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:userId": [
                        "AROAEXAMPLEID:*",
                        "111111111111"
                    ]
                }
            }
        }
    ]
}

以下策略显示了控制台级访问所需的服务操作,例如与控制台的 IAM 切换角色功能配合使用的操作。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:role/ROLENAME"
            },
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:role/ROLENAME"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::MyExampleBucket"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:role/ROLENAME"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::MyExampleBucket/*"
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::MyExampleBucket",
                "arn:aws:s3:::MyExampleBucket/*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:userId": [
                        "AROAEXAMPLEID:*",
                        "111111111111"
                    ]
                }
            }
        }
    ]
}

要向其他账户中的 IAM 用户授予 API/CLI 访问权限,您需要将 IAM 用户的 AIDAEXAMPLEID 添加到“aws:userId”条件,就像我们上一节所做的那样。除了“aws:userId”条件之外,您还需要将 IAM 用户的完整 ARN 添加到这些策略的 Principal 元素。请注意,您不能向 IAM 用户授予跨账户控制台访问权限,因为该用户需要具备目标账户中的角色,但您可以通过 API/CLI 授予对存储桶的访问权限。具体如下所示。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": [
                {
                    "AWS": [
                        "arn:aws:iam::222222222222:role/ROLENAME",
                        "arn:aws:iam::222222222222:user/USERNAME"
                    ]
                }
            ],
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::MyExampleBucket"
        },
        {
            "Effect": "Allow",
            "Principal": [
                {
                    "AWS": [
                        "arn:aws:iam::222222222222:role/ROLENAME",
                        "arn:aws:iam::222222222222:user/USERNAME"
                    ]
                }
            ],
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::MyExampleBucket/*"
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::MyExampleBucket",
                "arn:aws:s3:::MyExampleBucket/*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:userId": [
                        "AROAEXAMPLEID:*",
                        "AIDAEXAMPLEID",
                        "111111111111"
                    ]
                }
            }
        }
    ]
}

除了在存储桶策略中包含角色权限之外,您还需要在 IAM 用户或角色的用户策略中定义这些权限。这些权限可以添加到客户托管的策略并附加到 IAM 控制台中的角色或用户,详见以下策略文档。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListAllMyBuckets",
        "s3:GetBucketLocation"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::MyExampleBucket"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::MyExampleBucket/*"
    }
  ]
}

按照本文中的指导,即使用户拥有 Admin 策略或带有 s3:* 的策略,也可以将 S3 存储桶访问权限限于本地账户内和不同账户中的特定 IAM 角色或用户。这种逻辑有多种应用,各种使用案例的要求可能会有所不同。例如,您可以使用此方法设置存储桶,以供 Auto Scaling 组内的实例访问。如同在包含个人记录和账户信息的存储桶中一样,您还可以使用此方法限制对具有高级别安全需求的存储桶的访问。务必牢记,最好始终仅将权限授予执行必要任务所需的资源。

相关文章