当前位置: 首页 > news >正文

AWS实战 - 利用IAM对S3做访问控制

介绍

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

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

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

当 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中输入该密钥;

clipboard.png

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

clipboard.png

  • 此时Harp-Admin已经开启了MFA验证,使用该用户登录控制台时,需要在验证密码之后,再验证MFA(即输入Authy中的实时CODE);
  • 在IAM控制台中点击账户设置,将密码策略修改如下,可根据需要调整;

clipboard.png

创建测试用户和存储桶

  • 根据AWS最佳实践,本步骤的操作都是使用Harp-Admin来处理的;
  • 依次创建以下4个用户,暂不赋予任何权限;

clipboard.png

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

clipboard.png

配置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-public1derek-public2derek-bucket3/public,其中derek-public2只有可读权限,如果用户尝试写入,例如创建一个文件夹,会显示“无法使用名称XXX创建文件夹”;

clipboard.png

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

clipboard.png

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-bucket2derek-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写入,则会被拒绝,如图:

clipboard.png

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

clipboard.png

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

clipboard.png

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

clipboard.png


一些坑

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

相关文章:

  • 糟糕的软件设计:幻想出来的问题
  • windows下启动和运行分布式消息中间件消息队列 kafka
  • 关系与外键约束
  • TP自动生成模块目录
  • maven私服搭建
  • canvas 使用图片跨域问题
  • MySQL的安装与配置
  • redhat7.5在H3C机器上黑屏无显
  • 超级详细使用Webpack4.X 搭建H5开发环境
  • 真数组与伪数组的区别
  • 搜狗地图下载|搜狗地图app下载
  • 腾讯朱华:数据中心下一个风向的探索
  • 汇编语言实验9
  • CentOS 7下mysqld服务启动失败终极解决方案
  • 【Python】【翻转字符串】
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • AngularJS指令开发(1)——参数详解
  • bootstrap创建登录注册页面
  • create-react-app项目添加less配置
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • IOS评论框不贴底(ios12新bug)
  • JavaScript DOM 10 - 滚动
  • Javascript弹出层-初探
  • Java超时控制的实现
  • tensorflow学习笔记3——MNIST应用篇
  • Vue2.x学习三:事件处理生命周期钩子
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • Vue--数据传输
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 回顾 Swift 多平台移植进度 #2
  • 免费小说阅读小程序
  • 如何设计一个比特币钱包服务
  • 使用parted解决大于2T的磁盘分区
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 一个完整Java Web项目背后的密码
  • 怎么将电脑中的声音录制成WAV格式
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • ​香农与信息论三大定律
  • ()、[]、{}、(())、[[]]命令替换
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (力扣)1314.矩阵区域和
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .net oracle 连接超时_Mysql连接数据库异常汇总【必收藏】
  • .NET 解决重复提交问题
  • .net 受管制代码
  • [ C++ ] STL---string类的模拟实现
  • [20150629]简单的加密连接.txt
  • [23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians
  • [Android学习笔记]ScrollView的使用
  • [C++]unordered系列关联式容器
  • [cb]UIGrid+UIStretch的自适应
  • [JS]变量