aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制

介绍

要对S3的访问权限做控制,既可以使用基于身份的策略(IAM用户策略),也可以使用基于资源的策略(ACL和存储桶策略)。

访问一个存储桶的权限控制流程如图所示:

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第1张图片

访问存储桶中的对象的权限控制流程如图所示:

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第2张图片

当 Amazon S3 收到对象操作请求时,它会将基于资源的所有相关权限(对象访问控制列表 (ACL)、存储桶策略、存储桶 ACL)和IAM用户策略转换为将在运行时进行评估的策略集。然后它会通过一系列步骤评估生成的策略集。在每个步骤中,它会在三个特定上下文 (用户上下文、存储桶上下文和对象上下文) 中评估一个策略子集。

简单来说就是先判断用户权限,然后判断存储桶权限,最后判断对象权限。

目前我们都是通过同一个AWS账户下的多个IAM用户去访问S3的,因此可以只使用IAM用户策略去做访问权限控制,这也基本能满足绝大部分常规的权限控制需求,如果无法满足的情况再考虑使用存储桶处理和ACL。

实战演练

准备工作

使用AWS根账号(我的账户名是Harp)登录AWS管理控制台,选择IAM服务进入,创建一个名为Administrators的组,并向其附加AdministratorAccess权限;

创建一个IAM用户(Harp-Admin),并将其添加到Administrators组;

下载Authy软件,手机版或PC版均可,并安装,用于为用户添加MFA验证;

在IAM控制台中点击用户,点击Harp-Admin,点击安全凭证;

已分配 MFA 设备目前显示未分配,点击管理,添加虚拟 MFA 设备,继续;

此时弹出如下的对话框,如果使用的Authy是手机版本的,那么点击显示QR码并扫描,如果是PC版则点击显示私有密钥,并在PC版的Authy中输入该密钥;

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第3张图片

之后将Authy中连续两个30s的MFA CODE输入以下文本框中,并点击分配MFA;

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第4张图片

此时Harp-Admin已经开启了MFA验证,使用该用户登录控制台时,需要在验证密码之后,再验证MFA(即输入Authy中的实时CODE);

在IAM控制台中点击账户设置,将密码策略修改如下,可根据需要调整;

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第5张图片

创建测试用户和存储桶

根据AWS最佳实践,本步骤的操作都是使用Harp-Admin来处理的;

依次创建以下4个用户,暂不赋予任何权限;

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第6张图片

如下图,创建Bucket一列对应的存储桶,Object不为*的需要创建对应的文件夹,权限一列是我们要实现的访问控制权限;

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第7张图片

配置IAM用户策略

s3_common_policy

在IAM控制台中点击策略,创建策略,JSON,输入如下json,命名为s3_common_policy;

{

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"Action": [

"s3:ListAllMyBuckets",

"s3:GetBucketLocation"

],

"Resource": "arn:aws:s3:::*"

},

{

"Effect": "Allow",

"Action": [

"s3:ListBucket"

],

"Resource": [

"arn:aws:s3:::derek-public*"

]

},

{

"Sid": "AllowRootLevelListingOfTheBucket",

"Action": [

"s3:ListBucket"

],

"Effect": "Allow",

"Resource": [

"arn:aws:s3:::derek-bucket3"

],

"Condition": {

"StringEquals": {

"s3:prefix": [

""

],

"s3:delimiter": [

"/"

]

}

}

},

{

"Sid": "AllowListBucketOfASpecificUserPrefix",

"Action": [

"s3:ListBucket"

],

"Effect": "Allow",

"Resource": [

"arn:aws:s3:::derek-bucket3"

],

"Condition": {

"StringLike": {

"s3:prefix": [

"public/*"

]

}

}

},

{

"Effect": "Allow",

"Action": [

"s3:PutObject",

"s3:PutObjectAcl",

"s3:GetObject",

"s3:GetObjectAcl",

"s3:DeleteObject"

],

"Resource": [

"arn:aws:s3:::derek-public1/*",

"arn:aws:s3:::derek-bucket3/public/*"

]

},

{

"Effect": "Allow",

"Action": [

"s3:GetObject"

],

"Resource": "arn:aws:s3:::derek-public2/*"

}

]

}

解释一下各条statements:

statement1: 对所有的S3资源赋予s3:ListAllMyBuckets和s3:GetBucketLocation,这两个权限是给控制台使用的,通过控制台访问S3时,需要这两个权限来正常列出所有存储桶,如果通过CLI访问则不需要;

statement2: 赋予所有derek-public开头的存储桶列出存储桶对象的权限(s3:ListBucket);

statement3: 允许列出derek-bucket3第一层路径下的对象,这个写法可以在S3的官方文档中找到;

statement4: 允许列出derek-bucket3/public下的所有对象;

statement5: 允许对derek-public1和derek-bucket3/public中的对象读写、复制操作;

statement6: 允许对derek-public2中的对象读取操作;

创建一个用户组s3_common_group,并将所有用户添加到其中,将s3_common_policy附加到这个组;

此时id为1/4/8的权限已经实现,4个用户可以正常读取derek-public1、derek-public2和derek-bucket3/public,其中derek-public2只有可读权限,如果用户尝试写入,例如创建一个文件夹,会显示“无法使用名称XXX创建文件夹”;

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第8张图片

如果用户尝试进入无权限的bucket或者文件夹,例如derek-bucket1或derek-bucket3/user1,会显示“Access Denied”;

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第9张图片

user1_policy

在IAM控制台中点击策略,创建策略,JSON,输入如下json,命名为user1_policy;

{

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"Action": [

"s3:ListBucket"

],

"Resource": [

"arn:aws:s3:::derek-bucket1",

"arn:aws:s3:::derek-bucket2"

]

},

{

"Effect": "Allow",

"Action": [

"s3:PutObject",

"s3:PutObjectAcl",

"s3:GetObject",

"s3:GetObjectAcl",

"s3:DeleteObject"

],

"Resource": [

"arn:aws:s3:::derek-bucket1/*",

"arn:aws:s3:::derek-bucket3/user1/*"

]

},

{

"Effect": "Allow",

"Action": [

"s3:GetObject"

],

"Resource": "arn:aws:s3:::derek-bucket2"

},

{

"Sid": "AllowListBucketOfASpecificUserPrefix",

"Action": [

"s3:ListBucket"

],

"Effect": "Allow",

"Resource": [

"arn:aws:s3:::derek-bucket3"

],

"Condition": {

"StringLike": {

"s3:prefix": [

"user1/*"

]

}

}

}

]

}

解释一下各条statements:

statement1: 允许列出derek-bucket1和derek-bucket2中的所有对象;

statement2: 允许对derek-bucket1和derek-bucket3/user1中的对象读写、复制操作;

statement3: 允许对derek-bucket2中的对象读取操作;

statement4: 允许列出derek-bucket3/user1下的所有对象;

因为该策略只有user1使用,我们可以不创建组,直接将其附加到user1上;

点击用户,user1,添加权限,直接附加现有策略,选择user1_policy,审核,添加权限;

此时id为3/4/6中涉及user1的权限已经配置完成;

user2_policy

在IAM控制台中点击策略,创建策略,JSON,输入如下json,命名为user2_policy;

{

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"Action": [

"s3:ListBucket"

],

"Resource": [

"arn:aws:s3:::derek-bucket2"

]

},

{

"Effect": "Allow",

"Action": [

"s3:PutObject",

"s3:PutObjectAcl",

"s3:GetObject",

"s3:GetObjectAcl",

"s3:DeleteObject"

],

"Resource": [

"arn:aws:s3:::derek-bucket2/*",

"arn:aws:s3:::derek-bucket3/user2/*"

]

},

{

"Sid": "AllowListBucketOfASpecificUserPrefix",

"Action": [

"s3:ListBucket"

],

"Effect": "Allow",

"Resource": [

"arn:aws:s3:::derek-bucket3"

],

"Condition": {

"StringLike": {

"s3:prefix": [

"user2/*"

]

}

}

}

]

}

解释一下各条statements:

statement1: 允许列出derek-bucket2中的所有对象;

statement2: 允许对derek-bucket2和derek-bucket3/user2中的对象读写、复制操作;

statement3: 允许列出derek-bucket3/user2下的所有对象;

将该策略附加给user2,此时id为4/7中涉及user2的权限已经配置完成;

user3_policy

在IAM控制台中点击策略,创建策略,JSON,输入如下json,命名为user3_policy;

{

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"Action": [

"s3:ListBucket"

],

"Resource": [

"arn:aws:s3:::derek-bucket3"

]

},

{

"Effect": "Allow",

"Action": [

"s3:GetObject"

],

"Resource": "arn:aws:s3:::derek-bucket3"

}

]

}

将该策略附加给user3,此时id为5的权限已经配置完成;

user4_policy

根据之前的步骤,使用Harp-Admin为user4创建虚拟MFA;

在IAM控制台中点击策略,创建策略,JSON,输入如下json,命名为user4_policy;

{

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"Action": [

"s3:ListBucket"

],

"Resource": [

"arn:aws:s3:::derek-bucket4"

]

},

{

"Effect": "Allow",

"Action": [

"s3:PutObject",

"s3:PutObjectAcl",

"s3:GetObject",

"s3:GetObjectAcl",

"s3:DeleteObject"

],

"Resource": [

"arn:aws:s3:::derek-bucket4/*"

]

},

{

"Effect": "Deny",

"Action": [

"s3:PutObject",

"s3:PutObjectAcl",

"s3:GetObjectAcl",

"s3:DeleteObject"

],

"Resource": [

"arn:aws:s3:::derek-bucket4/mfa/*"

],

"Condition": {

"BoolIfExists": {

"aws:MultiFactorAuthPresent": false

}

}

},

{

"Effect": "Allow",

"Action": [

"s3:GetObject"

],

"Resource": [

"arn:aws:s3:::derek-bucket4/mfa/*"

]

}

]

}

解释一下各条statements:

statement1: 允许列出derek-bucket4中的所有对象;

statement2: 允许对derek-bucket4中的对象读写、复制操作;

statement3: 未通过MFA验证时禁止写derek-bucket4/mfa下的所有对象;

statement4: 允许读取derek-bucket4/mfa下的所有对象;

其中涉及MFA验证的权限控制可以参考带MFA条件的示例策略;

将该策略附加给user4,此时id为9的权限已经配置完成;

如果user4通过控制台登录,必须要使用MFA验证,登录之后符合statement3的条件,因此可以在mfa文件夹下写入内容;

如果user4通过CLI直接向mfa写入,则会被拒绝,如图:

bVbkA17?w=1042&h=61

此时需要加上MFA验证,输入下图中的命令,两个红框依次替换成user4的MFA ARN和MFA当前的6位token,会返回一个json格式的临时凭证,该凭证默认有效期12h,更多关于CLI和MFA的内容可参考 如何使用 MFA 令牌对通过 AWS CLI 进行的 AWS 资源访问执行身份验证?:

bVbkA2E?w=1106&h=169

修改AWS CLI的配置文件credentials,如下图红框,添加一个mfa-user,将上一步的结果复制到这里;

aws php s3 限制访问,AWS实战 - 利用IAM对S3做访问控制_第10张图片

利用mfa-user复制文件到mfa文件夹,提示复制成功;

bVbkA4m?w=479&h=60

一些坑

在使用user1时,在derek-bucket1中建立文件夹没有问题,但是上传文件却失败,提示OptionsRequestDenied,经谷歌查询猜测可能和浏览器的AdBlock相关插件有关,于是换火狐浏览器、或者使用CLI上传,都没有问题。

你可能感兴趣的:(aws,php,s3,限制访问)