亚马逊AWS官方博客

IAM 可让您更轻松地管理访问资源的 Amazon Web Services 服务的权限

Amazon Web Services 客户在 Amazon Web Services 上存储前所未有的大量数据,将这些数据用于一系列使用案例,包括数据湖和分析、机器学习以及企业应用程序。客户通过实施数据安全控制(包括身份和访问管理、网络安全和加密)来保护其数据。对于非公开的敏感数据,客户需要确保仅限来自已知位置的授权用户访问这些数据。客户实施基于身份和网络的数据丢失防护控制措施,以确保仅限可信身份(例如您的授权企业用户)和预期的网络位置(例如您的公司网络或 Amazon VPC)访问敏感数据。某些 Amazon Web Services 服务需要使用自己的身份从您的网络位置之外访问您的资源。在这篇文章中,我们将展示如何使用全局 Amazon Web Services Identity and Access Management(IAM)条件键 aws:PrincipalIsAWSService 来编写策略,限制不可信身份和意外网络位置访问您的数据,同时安全地授予 Amazon Web Services 服务的访问权限。我们将讨论如何使用新的条件键,提供显示其使用情况的示例策略,同时展示如何将其纳入组织的数据安全策略中。

新的全局 IAM 条件键

aws:PrincipalIsAWSService 是一个全局 IAM 条件键,可在授予 Amazon Web Services 服务的访问权限时简化基于资源的策略(例如 Amazon S3 存储桶策略)。该条件键提供允许 Amazon Web Services 服务访问您资源的简写形式,并且可以与其他所需的限制(例如限制对网络的访问)搭配使用。由于此条件键的目的是简化 Amazon Web Services 服务与您资源交互的方式,因此本文中的示例主要涵盖基于资源的策略。我们使用 Amazon CloudTrail 说明如何使用此条件键。借助 CloudTrail,您可以记录日志、持续监控并保留与整个亚马逊云科技基础设施中的操作相关的账户活动。CloudTrail 允许您创建跟踪,从而可将事件作为日志文件持续传输到您指定的 Amazon Simple Storage Service(Amazon S3)存储桶。考虑如下的场景:您希望允许 CloudTrail 直接从其服务账户向 S3 存储桶写入数据,但也希望确保来自您身份的所有其他访问仅限于自己的网络(例如 Amazon VPC),如图 1 所示。

图 1:来自可信网络和 CloudTrail 的访问

新的 aws:PrincipalIsAWSService 条件键可用于实施存储桶策略,该策略限制从您的 VPC 访问您的数据,同时安全地授予 Amazon Web Services 服务(例如 CloudTrail)的访问权限。在以下示例中,将 <my-logs-bucket><AccountNumber> 和 <vpc-111bbb22> 替换为您的信息。

 <CloudTrail standard cross account bucket policy configuration>
       …
      {
         "Sid":"expected-network+service-principal",
         "Effect":"Deny",
         "Principal":"*",
         "Action":[
            "s3:PutObject*",
            "s3:GetObject*",
			"s3:ListBucket"
         ],
         "Resource":"arn:aws:s3:::<my-logs-bucket>/AWSLogs/<AccountNumber>/*",
         "Condition":{
            "StringNotEquals":{
               "aws:SourceVpc":"<vpc-111bbb22>"
            },
            "Bool":{
               "aws:PrincipalIsAWSService":"false"
            }
         }
      }

上述策略语句将 s3:PutObject 和 s3:GetObject 操作限制在 VPC 中,同时 Amazon Web Services 服务不受此条件的约束。aws:PrincipalIsAWSService 条件键与布尔条件运算符搭配使用,根据键与 true 或 false 的比较结果来限制访问。在前面的语句中,除非请求来自指定的 VPC(<vpc-111bbb22>)或 Amazon Web Services 服务(在本例中为 CloudTrail),否则对包含 CloudTrail 数据的存储桶的访问受到限制。

注意:本文章稍后将介绍完整的策略,包括必要的跨账户访问 Allow 语句。

作为数据边界一部分的 aws:PrincipalIsAWSService

您刚刚了解了新的 aws:PrincipalIsAWSService 全局条件键及其基本用法。继续阅读以了解如何使用新的条件键来建立数据边界。简而言之,数据边界是一组预防性防护机制,可确保仅限客户的身份从预期的网络位置访问云中自己的数据。关键的数据边界控制措施之一是将您的资源配置为仅可由可信身份从预期网络位置访问。 假设您在 S3 存储桶中存储敏感数据。作为建立数据边界的环节之一,您希望将对这些数据的访问限制在网络位置,例如您的 VPC 或本地网络。接下来了解如何根据四种常见的数据访问模式限制访问权限,同时安全地豁免还需要从网络外部访问资源的 Amazon Web Services 服务。了解不同的数据访问模式将有助于您理解何时以及如何使用此新条件键和其他 IAM 条件键来安全地豁免 Amazon Web Services 服务。

1. 您的身份直接访问数据

最基本的数据访问模式是,您的 Amazon Web Services 账户中的 IAM 主体(角色或用户)直接访问 S3 存储桶中的数据。例如,用户登录 Amazon Web Services 管理控制台以将对象上传到 S3 存储桶,如图 2 所示。

图 2:您的身份直接访问数据(数据访问模式 1)

使用这种访问模式,您的存储桶策略可以限制您已经授予的权限,如下所示。将 <my-data-bucket> 和 <203.0.113.0/24> 替换为您的信息。

{
   "Version":"2012-10-17",
   "Id":"S3BucketPolicyId1",
   "Statement":[
      {
         "Sid":"expected-network",
         "Effect":"Deny",
         "Principal":"*",
         "Action":[
            "s3:ListBucket",
            "s3:PutObject*",
            "s3:GetObject*"
         ],
         "Resource":[
            "arn:aws:s3:::<my-data-bucket>",
            "arn:aws:s3:::<my-data-bucket>/*"
         ],
         "Condition":{
            "NotIpAddress":{
               "aws:SourceIp":"<203.0.113.0/24>"
            }
         }
      }
   ]
}

通过在前面的策略中包含 aws:SourceIp 条件,将会拒绝用户列出、放入或获取 S3 存储桶的对象,除非 API 调用来自其公司网络。

注意:本示例和后续示例使用 Deny 语句来限制您已授予的权限,以帮助说明有效的数据边界策略。主体还需要基于身份的策略,该策略具有相应的 Allow 权限,这样主体才能写入此存储桶,本示例中未对此进行描述。同样,对于跨账户访问,必须在存储桶策略中为授权主体添加相应的 Allow 语句。

这些策略包括 s3 数据访问操作的子集,而不是包括 s3:*,以防止您的存储桶意外锁定,如果您在指定网络位置之外编辑存储桶策略,则可能会发生这种情况。可以考虑扩展操作列表以包括其他操作,例如 DeleteObject、RestoreObject 或 PutBucketPolicy,具体取决于您的要求。您甚至可以包括 s3:*,前提是可以在定义的网络边界内执行所有操作。

2.通过 Amazon Web Service 服务直接访问数据

通过 Amazon Web Services 服务访问数据,并且该服务代表 IAM 主体执行后续操作时,第二种访问模式适用。这种访问模式的一个常见示例是 Amazon Athena。Athena 是一项交互式查询服务,可让您使用标准 SQL 在 Amazon S3 中查询数据。继续前面的示例,假设您希望限制用户访问 S3 存储桶,除非 API 调用来自其公司网络。但是,您也允许他们通过 Athena 查询数据,如图 3 所示。

图 3:通过 Amazon Web Service 服务直接访问数据(数据访问模式 2)

上述示例中的存储桶策略阻止用户使用 Athena 查询数据,因为对 Amazon S3 的调用是从 Athena 服务发出的,而不是从您的公司网络发出。为说明这种访问模式,您可以通过向 StringNotEquals 添加条件键 aws:CalledViaFirst 来更新存储桶策略,如以下示例所示:

{
    "Version": "2012-10-17",
    "Id": "S3BucketPolicyId1",
    "Statement": [
        {
            "Sid": "expected-network+athena",
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:ListBucket",
                "s3:PutObject*",
                "s3:GetObject*"
            ],
            "Resource": [
                "arn:aws:s3:::<my-data-bucket>",
                "arn:aws:s3:::<my-data-bucket>/*"
            ],
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "<203.0.113.0/24>"
                },
                "StringNotEquals": {
                    "aws:CalledViaFirst": "athena.amazonaws.com"
                }
            }
        }
    ]
}

我们现在有了带有两个否定条件键的 Deny 语句。这意味着两个条件都必须解析为 true 才能触发 Deny 效果。上述策略中的条件语句现在内容如下:拒绝这三个 S3 操作,除非它们源自您的公司网络(带有 aws:SourceIp 的 NotIpAddress)或通过 Athena 服务执行(带有 aws:CalledViaFirst 的 StringNotEquals)。我们使用 aws:CalledViaFirst(单值键)而非 aws:CalledVia(多值键),因为与 StringNotEquals 条件搭配使用时,单值键更容易推理。有关评估逻辑的更多详细信息,请参阅创建具有多个键或值的条件

3.用于数据访问的中间 IAM 角色

第三种常见模式是使用 Amazon Web Services 角色。在此情况下,给定的 Amazon Web Services 服务将扮演您创建的服务角色,以代表您执行操作。由于 Amazon Web Services 服务使用服务角色,而不是代表主体提出请求,因此您不能使用上述示例中的 aws:CalledViaFirst 条件键。这种访问模式有两种变体,它们将决定我们如何授予 Amazon Web Services 访问资源的权限。

3a.API 调用源自您的 VPC

第一种情况是 API 调用从您的预期网络内发出,例如在您的 VPC 内。Amazon Glue 就是不错的示例。Amazon Glue 是一项无服务器数据集成服务,可以让用户更轻松地发现、准备和合并数据,以便进行分析、机器学习和应用程序开发。进一步继续前面的示例,假设您希望限制用户访问您 S3 存储桶中的数据,除非 API 调用源自您的公司网络,但也允许他们使用 Amazon Glue 爬取数据以更新 Amazon Glue Data Catalog 中的架构。对于 Amazon Glue,您可以通过指定所需的 VPC ID、子网 ID 和安全组,将爬网程序配置为搭配使用您的网络和指向 Amazon S3 的网络连接,如图 4 所示。

图 4:用于从客户的 VPC 访问数据的中间 IAM 角色(数据访问模式 3a)

使用这种模式,您只需在 StringNotEquals 中添加 aws:SourceVpc 条件即可扩展数据边界,将您的 VPC 网络包括在内,如以下示例所示。将每个 <placeholder> 替换为您的值。

{
   "Version":"2012-10-17",
   "Id":"S3BucketPolicyId1",
   "Statement":[
      {
         "Sid":"expected-network+athena",
         "Effect":"Deny",
         "Principal":"*",
         "Action":[
            "s3:ListBucket",
            "s3:PutObject*",
            "s3:GetObject*"
         ],
         "Resource":[
            "arn:aws:s3:::<my-data-bucket>",
            "arn:aws:s3:::<my-data-bucket>/*"
         ],
         "Condition":{
            "NotIpAddress":{
               "aws:SourceIp":"<203.0.113.0/24>"
            },
            "StringNotEquals":{
               "aws:CalledViaFirst":"athena.amazonaws.com",
               "aws:SourceVpc":"<vpc-111bbb22>"
            }
         }
      }
   ]
}

上述策略将 aws:SourceVPC 条件添加到与之前添加的 aws:CalledViaFirst 条件相同的代码块中。我们现在有了带三个否定条件键的 Deny 语句。这意味着所有三个条件都必须解析为 true 才能触发 Deny 效果。因此,只有当调用不是来自您的本地网络、并非通过 Athena 服务进行,以及不是来自您的 VPC 网络时,此策略才会拒绝对 Amazon S3 的调用。

3b.API 调用源自您的 VPC 外部

虽然某些使用服务角色的 AWS 服务直接从您的 VPC 访问您的资源,例如 AWS Glue,但当服务角色需要从 VPC 外部访问 S3 存储桶中的数据时,这种访问模式还有第二种变体。这种模式的一个良好示例是使用 Amazon S3 复制功能复制对象。如果您应用上述存储桶策略,则复制将失败。之所以发生这种情况,是因为对 Amazon S3 的调用是由与复制配置关联的服务角色从 VPC 外部发出的。具体情况如图 5 所示。

图 5:用于从客户 VPC 外部访问数据的中间 IAM 角色(数据访问模式 3b)

为说明这种访问模式,您可以更新存储桶策略,在 StringNotEquals 语句中包括 aws:PrincipalArn 条件键,如以下示例所示。将每个 <placeholder> 替换为您的值。

{
   "Version":"2012-10-17",
   "Id":"S3BucketPolicyId1",
   "Statement":[
      {
         "Sid":"expected-network+athena+service-role",
         "Effect":"Deny",
         "Principal":"*",
         "Action":[
            "s3:ListBucket",
            "s3:PutObject*",
            "s3:GetObject*"
         ],
         "Resource":[
            "arn:aws:s3:::<my-data-bucket>",
            "arn:aws:s3:::<my-data-bucket>/*"
         ],
         "Condition":{
            "NotIpAddress":{
               "aws:SourceIp":"<203.0.113.0/24>"
            },
            "StringNotEquals":{
               "aws:CalledViaFirst":"athena.amazonaws.com",
               "aws:SourceVpc":"<vpc-111bbb22>",
"aws:PrincipalArn":"arn:aws:iam::<AccountNumber>:role/<AmazonS3ReplicationRole>"
            }
         }
      }
   ]
}

使用上述策略,您可以有效地将与复制配置关联的 Amazon S3 复制角色 <AmazonS3ReplicationRole> 排除在 SourceIp 和 SourceVpc  限制之外。您可以建立此例外的原因是 Amazon S3 存储桶复制角色已配置有信任策略,该策略仅允许 Amazon S3 服务担任该角色,即只有 s3.amazonaws.com 可担任该角色。最佳实践是应用最低权限原则,以确保仅允许授权用户修改角色的信任策略,并将该角色作为转换作业配置的一部分进行传递。

4.可直接访问您资源的 Amazon Web Services 服务

在前面三个示例中,存储桶中的数据可由您的可信身份直接访问,也可通过 Amazon Web Services 服务(Athena)或可信中间服务角色(Amazon Glue 和 Amazon S3)直接访问。但是,还有最后一种访问模式,即 Amazon Web Services 服务使用自己的身份(服务主体)代表客户执行操作。这种访问模式的一个良好示例是我们在本博客文章开头介绍的 CloudTrail 使用案例,如图 6 所示。

图 6:可直接访问您资源的 Amazon Web Services 服务(数据访问模式 4)

假设您的数据边界目标是限制从 VPC 或 CloudTrail 服务访问 S3 存储桶中的日志。如果您单独使用 aws:SourceVpc 条件制定仅限访问您的 VPC 的存储桶策略,则实际上可以阻止 CloudTrail 向您的存储桶写入数据。不能使用 aws:CalledViaFirst 排除 CloudTrail,如上面的数据访问模式 #2 所示,因为 CloudTrail 正在使用自己的服务主体向您的存储桶写入数据(注意:尽管作为 CalledVia 条件的一部分,您也指定了服务主体,例如 athena.amazonaws.com,但 CalledVia 仅在服务代表调用主体提出请求时才适用,而与之相对的是,CloudTrail 服务直接向您的存储桶写入数据)。同样,不能使用数据访问模式 #3b 中所示的 aws:PrincipalArn,因为 CloudTrail 使用的是服务主体而非 ARN。通过将新的 aws:PrincipalIsAWSService 条件添加到您的存储桶策略中,您可以实现数据边界目标,如下所示。将每个 <placeholder> 替换为您的值。

{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Sid":"grant-read-access-to-cloudtrail",
         "Effect":"Allow",
         "Principal":{
            "Service":"cloudtrail.amazonaws.com"
         },
         "Action":"s3:GetBucketAcl",
         "Resource":"arn:aws:s3:::<my-logs-bucket>"
      },
      {
         "Sid":"grant-write-access-to-cloudtrail",
         "Effect":"Allow",
         "Principal":{
            "Service":"cloudtrail.amazonaws.com"
         },
         "Action":"s3:PutObject",
         "Resource":"arn:aws:s3:::<my-logs-bucket>/AWSLogs/<AccountNumber>/*",
         "Condition":{
            "StringEquals":{
               "s3:x-amz-acl":"bucket-owner-full-control"
            }
         }
      },
      {
         "Sid":"expected-network+service-principal",
         "Effect":"Deny",
         "Principal":"*",
         "Action":[
            "s3:PutObject*",
            "s3:GetObject*",
            "s3:ListBucket"
         ],
"Resource":"arn:aws:s3:::<my-logs-bucket>/AWSLogs/<AccountNumber>/*",
         "Condition":{
            "StringNotEquals":{
               "aws:SourceVpc":"<vpc-111bbb22>"
            },
            "BoolIfExists":{
               "aws:PrincipalIsAWSService":"false"
            }
         }
      }
   ]
}

上述存储桶策略中的前两条 Allow 语句是 CloudTrail 标准跨账户存储桶策略配置的一部分。最后一条语句 expected-network+service-principal 结合使用 aws:SourceVpc 和新推出的 aws:PrincipalIsAWSService 条件来拒绝访问,除非调用源自您的 VPC 网络或由 Amazon Web Services 服务主体(例如 CloudTrail)发出。

常见数据访问模式的数据边界策略

现在您已经查看常见的数据访问模式和各种 IAM 条件键,包括新的 aws:PrincipalIsAWSService,接下来了解数据边界策略。以下示例策略可以附加到您的所有存储桶或其他基于资源的策略中。将每个 <placeholder> 替换为您的值。

注意:将策略附加到现有资源可能会导致应用程序意外中断。将这些策略应用于生产资源之前,请考虑在较低条件的环境中对其进行测试。

{
   "Version":"2012-10-17",
   "Id":"S3BucketPolicyId1",
   "Statement":[
      {
         "Sid":"network-data-perimeter",
         "Effect":"Deny",
         "Principal":"*",
         "Action":[
            "s3:ListBucket",
            "s3:PutObject*",
            "s3:GetObject*"
         ],
         "Resource":[
            "arn:aws:s3:::<my-data-bucket>",
            "arn:aws:s3:::<my-data-bucket>/*"
         ],
         "Condition":{
            "NotIpAddress":{
               "aws:SourceIp":[
                  "<203.0.113.0/24>"
               ]
            },
            "StringNotEquals":{
               "aws:SourceVpc":[
                  "<vpc-111bbb22>"
               ],
               "aws:PrincipalArn":"arn:aws:iam::<AccountNumber>:role/<AmazonS3ReplicationRole>"
            },
            "Bool":{
               "aws:PrincipalIsAWSService":"false",
               "aws:ViaAWSService":"false"
            }
         }
      },
      {
         "Sid":"identity-data-perimeter",
         "Effect":"Deny",
         "Principal":"*",
         "Action":[
            "s3:ListBucket",
            "s3:PutObject*",
            "s3:GetObject*"
         ],
         "Resource":[
            "arn:aws:s3:::<my-data-bucket>",
            "arn:aws:s3:::<my-data-bucket>/*"
         ],
         "Condition":{
            "StringNotEquals":{
               "aws:PrincipalOrgID":"<o-yyyyyyyyyy>"
            },
            "Bool":{
               "aws:PrincipalIsAWSService":"false"
            }
         }
      }
   ]
}

上述策略由两条语句组成。第一条语句 network-data-perimeter 设置预期的网络数据边界。接下来了解此语句中的所有条件元素:

条件键 使用情况 数据访问模式示例
aws:SourceIp 如果请求不是通过 VPC 端点发出,用于限制对预期网络的公有 IP 范围的访问。 从本地公司网络进行控制台访问,如数据访问模式 #1 中所述。
aws:SourceVpc 如果请求通过 VPC 端点发出,则用于限制对预期网络的特定 VPC ID 的访问。 Amazon Elastic Compute Cloud(Amazon EC2)实例上运行的应用程序(使用实例配置文件),部署在 VPC 中的 Lambda 函数,或者配置有 VPC 网络连接的 Amazon Glue 爬网程序,如前面数据访问模式 #3a 中所述。
aws:PrincipalArn 如果请求不是源自您的网络,则允许排除主体,例如 Amazon Web Services 服务的服务角色。 数据访问模式 #3b 中的 Amazon S3 复制。
aws:PrincipalIsAWSService 在 Amazon Web Services 服务使用自己的服务主体从自己的网络访问您的存储桶时,提供一种允许访问该服务的简单方法。如果 Amazon Web Services 服务代表 IAM 主体提出请求,则不能使用此条件键(例如在数据访问模式 #2 中,此时必须改用 aws:CalledVia)。 数据访问模式 #4 中的 CloudTrail。
aws:ViaAWSService

此条件键类似于 aws:CalledVia 和 aws:CalledViaFirst,但它不限于特定的 Amazon Web Services 服务(即 Athena),而是可用于允许或拒绝访问代表 IAM 主体请求访问您资源的任何 Amazon Web Services 服务(因此设置为 true 或 false),如数据访问模式 #2 中所述。

通常不会在同一个存储桶策略中同时使用 aws:CalledVia 和 aws:ViaAWSService。相反,对范围限定为特定 Amazon Web Services 服务的策略使用 aws:CalledVia;而如果您想允许或拒绝代表 IAM 主体提出请求的任何 Amazon Web Services 服务,则使用 aws:ViaAWSService。

数据访问模式 2 中的 Amazon Athena。

上述策略中的第二条语句 identity-data-perimeter 设置了可信身份的数据边界。接下来了解此语句中的两个条件:

条件键 使用情况 数据访问模式
aws:PrincipalOrgID 限制属于您的 Amazon Organizations 的可信主体的访问权限。请参阅博客文章:如何更简单地使用 IAM 主体的 Amazon 组织控制对 Amazon Web Services 资源的访问,了解此功能强大的条件键的其他使用案例。 用于基于资源的策略,例如存储桶策略和 VPC 端点策略。
aws:PrincipalIsAWSService 与上述策略中的第一条语句类似,您可以使用此条件键允许 Amazon Web Services 服务使用自己的服务主体从其网络访问您的存储桶。 数据访问模式 #4 中的 CloudTrail。

后续步骤

aws:PrincipalIsAWSService 条件键简化了基于资源的策略,方法是提供一种直观的方法来限制可信身份和预期网络的访问权限,同时授予从您网络位置之外使用自身服务主体的 Amazon Web Services 服务的访问权限。您也可以使用此条件键作为广泛数据边界策略的一部分,涵盖我们在本博客文章中讨论的常见数据访问模式。

Original URL: https://aws.amazon.com/blogs/security/iam-makes-it-easier-to-manage-permissions-for-aws-services-accessing-resources/