什么是S3的权限管理

S3的权限管理是任何使用S3的人都无法绕开的功能,决定了S3中的Object是否能够被访问。

权限管理本质上解决了这么一个问题: 谁(Principal)能够在何种条件(condition)下被允许或拒绝(Effect)对哪些资源(Resource)做何种操作(Action)

S3权限管理概述

S3权限管理,需要了解什么是S3的策略(Policy),有哪些策略,有多个策略时S3是如何进行评估的,以及如何选取合适的策略。

策略(Policies)

  • 默认所有S3的资源都是私有的
    • 只有资源的拥有者(创建资源的账号)能访问资源
    • 拥有者可以通过policy来赋予其他人来访问资源
  • 策略(policy)分为两类
    • 直接应用于某个资源(一个Object或者一个Bucket)的策略称为资源策略(Resources Policies)
    • 直接应用于某个IAM用户的被称为用户策略(User Resources)
  • Resources Based Polices
    • 总共有两类的资源策略
      • 访问控制列表(Access Control Lists)
        • 可以赋予简单的对object和bucket的读写权限给AWS账号和预定义组
        • 使用XML schema
        • 由一个权限条目的列表组成
      • 桶策略(Bucket Policies)
        • 用来赋予AWS账号或者IAM用户访问Bucket和object的权限
        • 使用JSON
        • 可以进行精细化控制
        • 大多数情况下,可以用来替换ACL
  • 用户策略(User Policies)
    • 使用AWS IAM添加到用户(users), 组(groups)或者角色(roles)
    • 可以进行精细化控制
    • 使用JSON
    • 因为是直接赋给IAM users/groups/role的,因此不支持给予匿名访问的权限
    • 不能被赋予root account
  • 跨账户访问(Cross Account Access)
    • 跨账户访问是一个账户授权另一个账户访问它的资源
      • 比如Account A可以通过Bucket Policy授权Account B访问权限
        1. Account A通过Bucket Policy授权了Account B可以访问某个Bucket
        2. Account B通过User Policy授权Account B的某个IAM User访问权限
        3. Account B中的IAM user就可以访问Account A中Bucket的资源了

S3怎么评估polices

  • 整体规则:
    • 当有显式拒绝时,会被判定为拒绝访问
    • 没有显式拒绝,有显示允许时,会被判定为允许访问。
    • 没有显式拒绝也没有显示允许时,就适用默认拒绝规则,会被判定为拒绝访问。
  • 原理和例子可以参照这两篇文章 深挖AWS S3的权限管理深挖AWS S3的权限管理(实验篇)

怎么选取使用哪个策略

  • 一般情况下,优先使用User Policy和Bucket Policy,而不是ACL,因为它们能提供细粒度的控制。
  • 如下情况下,需要使用ACL
    • 需要控制不是Bucket拥有者的object的权限
    • 需要控制大量零碎的,不同prefix的object的权限
    • 赋予“S3 Log Delivery Group”权限到Bucket时
  • 如下情况时,需要使用Bucket Policy
    • 无法使用ACL授权跨账户访问时

S3的访问控制列表(ACL)

  • 什么是ACL
    • ACL是基于XML的,可用于bucket和object
    • 每一个bucket和object都有一条ACL作为它的sub-resource来定义访问权限
    • 默认的ACL是给object的拥有者完全的访问权限
  • ACL 特性
    • 只能被用来给AWS account和预定义的groups来赋予权限,不能管理IAM user的权限
    • 只能赋予基本的读写权限
      • 不能基于条件来控制读写权限
      • 不能赋予显式拒绝的权限
    • ACL 可以拥有最多 100 个授权
  • ACL 例子解析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?xml version="1.0" encoding="UTF-8"?>
    <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <Owner>
    <ID>*** Owner-Canonical-User-ID ***</ID>
    <DisplayName>owner-display-name</DisplayName>
    </Owner>
    <AccessControlList>
    <Grant>
    <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:type="Canonical User">
    <ID>*** Owner-Canonical-User-ID ***</ID>
    <DisplayName>display-name</DisplayName>
    </Grantee>
    <Permission>FULL_CONTROL</Permission>
    </Grant>
    </AccessControlList>
    </AccessControlPolicy>
    • 注意Owner.ID一栏中,是拥有这个object的aws account的规范用户ID(canonical ID),而不是12位的account ID, 关于如何查找规范用户ID,可以参阅查找账户的规范用户ID

    • Grant的实体,分为好几类,可以是AWS account,也可以是S3预定义的组。

      • 当为AWS account时,则Grantee中xsi:type为CanonicalUser,Grant中以ID, DisplayName字段展示

        1
        2
        3
        4
        5
        6
        7
        <Grant>
        <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
        <ID>user2-canonical-user-ID</ID>
        <DisplayName>display-name</DisplayName>
        </Grantee>
        <Permission>READ</Permission>
        </Grant>
      • 当为预定义组时,则Grantee中xsi:type为Group,Grant中以group的URI字段来展示。

        1
        2
        3
        4
        5
        6
        <Grant>
        <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
        <URI>http://acs.amazonaws.com/groups/s3/LogDelivery</URI>
        </Grantee>
        <Permission>WRITE</Permission>
        </Grant>
  • ACL 权限

    • ACL只能几个设定好的权限集,针对Object和Bucket的ACL权限集相同。
      s3-acl-permissions
  • ACL 预定义组(ACL Predefined Groups)

  • 标准ACL(Canned ACL)

    • AWS定义了一系列预定义的ACL授权,称为标准ACL(Canned ACL)
      s3-acl-canned-acl
    • 设置时只能使用其中的一个canned ACL
    • 最常用于AWS CLI, 如下命令拷贝xxx.jpg到S3中,并且设置为public可读
      • aws s3 cp xxx.jpg s3://bucket_name/public/ --acl public-read

Bucket & User Policies

  • 什么是Bucket和User Policies
    • Bucket和User Polices都是策略,以JSON格式定义,用来规定bucket和object的访问权限
      • Bucket policies是attached在Bucket上的, 在S3中设置
      • User Policies是基于用户的,在IAM中设置
    • Bucket或者IAM默认都是没有任何策略的
  • Bucket & User Policy特性
    • 都可以规定IAM User的访问权限。Bucket Policy还可以规定AWS root account的访问权限,而IAM Policy因为没法attach到root account,因此无法规定root account的权限
    • 可以定义非常精细的访问权限
    • 可以使用显式拒绝
    • 可以设置带条件的访问权限
    • JSON格式
    • 大小限制在20KB
  • Policy的必备要素
    • 一个Policy包含如下几个元素
      • Principal服务委托人 - 被允许对某个资源进行某种操作的主体,只在Bucket Policy中使用。分为以下几种:
        • 特定AWS账户: "Principal": { "AWS": "arn:aws:iam::AWS-account-ID:root" }
        • IAM用户: "Principal": { "AWS": "arn:aws:iam::AWS-account-ID:user/user-name" }
        • 联合身份用户(federated identity) - web identity federation
          • "Principal": { "Federated": "cognito-identity.amazonaws.com" }
          • "Principal": { "Federated": "www.amazon.com" }
          • "Principal": { "Federated": "graph.facebook.com" }
          • "Principal": { "Federated": "accounts.google.com" }
        • 联合身份用户(federated identity) - SAML identity provider
          • "Principal": { "Federated": "arn:aws:iam::AWS-account-ID:saml-provider/provider-name" }
        • IAM角色(IAM Role)
          • "Principal": { "AWS": "arn:aws:iam::AWS-account-ID:role/role-name" }
        • AWS 服务
          • "Principal": { "Service": "elasticmapreduce.amazonaws.com" }
        • Everyone(匿名用户)
          • "Principal": "*""Principal" : { "AWS" : "*" }
        • 规范用户ID
          • "Principal": { "CanonicalUser": "79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be" }
      • Effect - 规则的结果
        • 有效值为Allow和Deny
      • Action - 指定的策略权限,能进行何种操作
        • AWS S3相关的所有策略权限,参考官网AWS S3 在策略中指定权限
        • 例子
          • Amazon SQS操作 - "Action": "sqs:SendMessage"
          • Amazon EC2操作 - "Action": "ec2:StartInstances"
      • Resource - 资源名
        • Resource就是ARN(aws resource name)的集合
        • ARN有三种格式
          • 格式一: arn:partition:service:region:account-id:resource
            • 例子 arn:aws:iam:us-west-2:123456789012:user/David
          • 格式二: arn:partition:service:region:account-id:resourcetype/resource
            • 例子 arn:aws:s3:::my_corporate_bucket/exampleobject.png
          • 格式三: arn:partition:service:region:account-id:resourcetype:resource
            • 例子 arn:aws:rds:eu-west-1:123456789012:db:mysql-db
          • 其中全球区的partition为aws,而中国区的partition为aws-cn
        • Resource可以使用通配符*和?
          • 某个bucket中所有的object arn:aws:s3:::mypublicbucket/*
      • SID - 每份策略的标识符
        • 策略的名字,在整个Policy文件中需要唯一
    • 注意: 在User Policy中没有Principal,执行User Policy的主体就是Principal
  • Policy中的可选元素 – Condition

    • Condition是一个可选元素
    • Condition元素可用来在Policy中授予条件时指定某些条件, 一条Policy可以有一条或者多条Condition
    • 类似于在policy中添加了一个”if”语句
    • 详细用法参见官网文档
    • 一个Condition包含如下要素

      • 一个条件运算符(Condition Operators),例如StringEquals,NumericEquals以及IpAddress等,所有的条件运算符参见官网文档IAM JSON 策略元素:条件运算符
      • Key/Value的键值对,包含条件键(Condition Key)和允许的值(Value)
      • 例子, 如下Condition的片段中,StringEquals就是条件运算符,s3:x-amz-acl就是条件键, public-read就是值。这个Condition会被解读为: s3:x-amz-acl的字符串等于(StringEquals) public-read的时候,Condition检查通过
        1
        2
        3
        4
        5
        "Condition": {
        "StringEquals": {
        "s3:x-amz-acl":["public-read"]
        }
        }
    • 用途举例

      • 允许用户只有在设置”public-read” ACL的时候才能”put” object

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        {
        "Version":"2012-10-17",
        "Statement":[
        {
        "Sid":"AddCannedAcl",
        "Effect":"Allow",
        "Principal": {"AWS": ["arn:aws:iam::111122223333:root","arn:aws:iam::444455556666:root"]},
        "Action":["s3:PutObject","s3:PutObjectAcl"],
        "Resource":["arn:aws:s3:::examplebucket/*"],
        "Condition":{"StringEquals":{"s3:x-amz-acl":["public-read"]}}
        }
        ]
        }
      • 仅允许用户在开启加密的时候才允许”put” object, 例子参考官网博文How to Prevent Uploads of Unencrypted Objects to Amazon S3

      • 仅允许用户在使用multi-factor验证的时候才能删除某个object
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        {
        "Version": "2012-10-17",
        "Id": "123",
        "Statement": [
        {
        "Sid": "",
        "Effect": "Deny",
        "Principal": "*",
        "Action": "s3:*",
        "Resource": "arn:aws:s3:::examplebucket/taxdocuments/*",
        "Condition": { "Null": { "aws:MultiFactorAuthAge": true }}
        }
        ]
        }
    • 带有Condition的完整Policy例子

      • 允许来自源IP在192.168.143.0/24的任何人获取Bucket examplebucket中的任意object,但IP地址192.168.143.188除外。
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        {
        "Version": "2012-10-17",
        "Id": "S3PolicyId1",
        "Statement": [
        {
        "Sid": "statement1",
        "Effect": "Allow",
        "Principal": "*",
        "Action":["s3:GetObject"] ,
        "Resource": "arn:aws:s3:::examplebucket/*",
        "Condition" : {
        "IpAddress" : {
        "aws:SourceIp": "192.168.143.0/24"
        },
        "NotIpAddress" : {
        "aws:SourceIp": "192.168.143.188/32"
        }
        }
        }
        ]
        }
  • 记忆Policy元素的小技巧,AcloudGuru课程中有一个容易记忆的方法

    • 总共6个要素(Condition可选)
      • Conditions
      • Principal
      • Effect
      • Action
      • Resource
      • SID
    • 对于Bucket policy来说
      • I “C PEARS” – 字母C读成成see,意为”我在Bucket Policy中看见了梨子”
    • 对于IAM Policy来说
      • I “C EARS” – 字母C读成see,意为”我在IAM Policy中看见了耳朵”

跨账户策略注意点

  1. 跨账户访问时,假设账户A设置了允许账户B上传object到A的Bucket中, 当账户B上传object到A的Bucket中时,object的owner是B,A默认是没有权限访问该Object的。
    可以通过设置Bucket Policy的方式,让账户B必须要授权A能够完全控制B上传的object。
    官网文章 How can I make sure the bucket owner has access to resources that are copied or moved between Amazon S3 buckets owned by different AWS accounts?

  2. 跨账户授权时,如果通过Bucket Policy授权其他账户的IAM用户访问自己的Bucket,IAM用户还需要他自己的Root账户也同时授权权限访问该Bucket,否则IAM用户没有权限访问该Bucket。 被授权的其他账户的IAM账户,仍然需要自己的root账户添加授权permission才能访问源Bucket。
    如果账户A使用Bucket Policy授权账户B的User C能够访问账户A的Bucket_A, 此时User C还会没法访问Bucket_A, 必须账户B在给User C的Policy中添加允许访问Bucket_A的策略后,User C才能访问Bucket_A。
    总结为: 如果一个Bucket要授权给其他账号的IAM User使用时,必须要两个Account都显式授权IAM User访问权限才行。

使用签名(signed)的方式访问私有Object

什么是签名

AWS提供了一个签署签名的功能,在HTTP请求中附加签名信息后,AWS能够识别发送请求的用户,并验证请求是否是该用户授权签名的。

AWS S3中可以使用该功能来短暂的让用户访问或操作某个私有Object。
Bucket的Owner通过指定如下信息来生成一个pre-signed的URL

  • 加密凭证(Security credentials)
  • Bucket名字
  • Object名字
  • HTTP方法(GET, PUT, DELETE等)
  • 过期时间

得到pre-signed URL的任何人,都能够在指定的过期时间之前,访问指定的object。

签名版本

AWS提供了两种签名版本Signature Version 4 和Signature Version 2。
对于S3来说,所有的Region都支持Signature Version 4,而Signature Version 2的签名方式,只有在2014年1月30日之前的Region才支持,在此日期之后建立的Region,一律都只支持Signature Version 4的签名方式。此处是官方说明文档Authenticating Requests (AWS Signature Version 4)

AWS CLI生成pre-signed的一个例子, 拿韩国首尔Region为例。

1
2
3
4
# 不指定Region的话,aws s3 cli会使用Signature Version 2方式签名
$ aws s3 presign s3://carl-test-at-seoul/fox.jpg --expires-in 3600
https://carl-test-at-seoul.s3.amazonaws.com/fox.jpg?AWSAccessKeyId=AKIAIJQFRFPQCLKRF5MA&Signature=M1teYMCFbGKlfOBt0d%2BAgl8NvFs%3D&Expires=1523590452
$

但是首尔Region是不支持该签名方式的,因此使用生成的上述URL访问S3时,会报告如下错误

1
2
3
4
5
6
7
8
9
<Error>
<Code>InvalidRequest</Code>
<Message>The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.</Message>
<RequestId>F7B09345800A56B8</RequestId>
<HostId>Fjr3JFqFxLI7Ar2HYyOJk/ZFuMfreIFa5CnFRBq8A1J8/g9/3XbaK3bkiY2gXtNFuZ6AcN/+8Is=</HostId>
<head>
<link/>
</head>
</Error>

在AWS CLI中指定首尔Region后,CLI会判断Region,从而使用Signature Version 4的加密方式

1
2
3
$ aws s3 presign s3://carl-test-at-seoul/fox.jpg --expires-in 3600 --region ap-northeast-2
https://carl-test-at-seoul.s3.amazonaws.com/fox.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIJQFRFPQCLKRF5MA%2F20180413%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20180413T023641Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=a97309f2de68d16afcc3f380dec5ec06d0de09f3b748081598107a0b3842c255
$

使用上述生成的URL,就能够顺利访问到原本私有的Object了。

延伸阅读

Reference

留言