首页 > 技术文章 > 国产最强权限管理,没有之一,不接受任何反驳!

cloudstorageangel 2022-03-29 14:19 原文

引言

在使用 COS 的过程中,你一定遇到过这些问题:如何限制用户访问 ip ?如何限制上传文件大小?如何只允许使用了 https 协议的请求通过?如何只允许列出指定目录下的对象?

以上这些问题,通通可以使用一把最强武器全面解决!

Policy Condition ——在设置权限策略时指定生效条件,限制用户请求只有在指定条件下才能通过。COS 目前已支持11个条件键,是国内目前支持条件键数量最多、最丰富的对象存储产品。未来,我们还会继续增加对更多条件键的支持,打造国产最强权限管理。

背景知识:什么是 Policy Condition(生效条件)?

COS 的各位资深用户,对于使用访问策略进行权限管理应当并不陌生。一个完整的访问策略包括几个基本元素:委托人(Principal)、资源(Resource)、效力(Effect)、操作(Action)、生效条件(Condition)。

其中,生效条件支持您在授予权限时指定条件,例如限制用户访问来源,携带指定的请求参数等。一个完整的生效条件包括以下几个元素:条件键、条件操作符和条件值。

以下面这个存储桶策略为例,用户必须在 10.217.182.3/24 或者 111.21.33.72/24 网段才能调用云 API 访问 cos:PutObject。

其中,条件键为 qcs:ip ,表示条件判断的内容是ip;

条件操作符为 ip_equal ,表示条件判断的方法是判断ip地址是否相等;

条件值为数组["10.217.182.3/24","111.21.33.72/24"],表示条件判断的规定值。若用户处于数组中任意一个 ip 所在的网段,条件判断都为 true。

{
"version":"2.0",
"statement":[
{
"Principal":{
"qcs":[
"qcs::cam::uin/1250000000:uin/1250000001"
]
},
"Effect":"allow",
"Action":[
"name/cos:PutObject"
],
"Resource":[
"qcs::cos:ap-guangzhou:
uid/1250000000:examplebucket-1250000000/*"
],
"Condition":{
"ip_equal":{
"qcs:ip":[
"10.217.182.3/24",
"111.21.33.72/24"
]
}
}
}
]
}

重头戏:COS 11个条件键包括哪些?
目前国内各家云厂商比较常见的是通过 Policy Condition 支持对 ip、vpc 的限制。COS 本次发布的条件键的亮点在于将条件键的支持范围进行了扩展,包括Content-Type、Content-Length 等用户多次提出希望进行限制的请求头部和请求参数。下表列出了COS目前支持的所有条件键。

cos条件键

含义

类型

qcs:ip

检查请求来源的ip网段

IP

qcs:vpc

检查请求来源的vpc id

String

cos:secure-transport

检查请求是否适用了https协议

Boolean

cos:prefix

检查请求参数 prefix。例如,只允许列出存储桶指定目录(prefix)下的对象。

String

cos:response-content-type

检查请求参数 response-content-type,该请求参数用于设置响应中Content-Type头部的值。

String

cos:x-cos-acl

检查请求头部 x-cos-acl,该请求头部用于设置、修改对象和存储桶ACL。

String

cos:x-cos-storage-class

检查请求头部 x-cos-storage-class,该头部用于在上传对象时指定存储类型或修改对象的存储类型。

String

cos:x-cos-forbid-overwrite

检查请求头部 x-cos-forbid-overwrite,使用请求头x-cos-forbid-overwrite可以在上传对象时禁止覆盖同名文件。

String

cos:versionid

检查请求参数 versionId,该请求参数表示对象的版本号,您可以在下载对象(GetObject)、删除对象(DeleteObject)时使用通过versionId指定需要操作的对象版本。

String

cos:content-length

检查请求头部:Content-Length,该请求头部为RFC 2616中定义的 HTTP 请求内容长度(字节)。

Numeric

cos:content-type

检查请求头部:Content-Type,该请求头部为RFC 2616中定义的 HTTP 请求内容类型(MIME)。

String

动手实践:Policy Condition最佳实践!
Policy Condition 的使用非常灵活,不同的条件操作符、条件键和条件值的组合往往有不同的使用效果。在这里我们选取了cos:secure-transport、cos:content-type、cos:content-length和cos:versionid 四个条件键作为示例,为您展示条件键的最佳实践。

更多最佳实践可参考COS官网文档:https://cloud.tencent.com/document/product/436/71307
备注:qcs:ip、vpc:requester_vpc、cos:content-type条件键支持在所有地域使用,其余条件键仅支持成都、广州、上海、雅加达、圣保罗、弗吉尼亚、东京、首尔地域,其他地域将陆续支持。

只允许使用了https协议的请求通过(cos:secure-transport)
条件键 cos:secure-transport

您可以使用条件键 cos:secure-transport 限制请求必须使用https协议。

示例1:下载请求需要使用https协议

假设主账号(uin:100000000001)拥有存储桶examplebucket-1250000000,以下存储桶策略的含义表示仅对由子用户(uin:100000000002)使用了 https 协议的 GetObject 请求进行授权。

{
"version":"2.0",
"Statement":[
{
"Principal":{
"qcs":[
"qcs::cam::uin/100000000001:uin/100000000002"
]
},
"Effect":"allow",
"Action":[
"name/cos:GetObject"
],
"Resource":[
"qcs::cos:ap-guangzhou:uid/1250000000:examplebucket-1250000000/*"
],
"Condition":{
"bool_equal":{
"cos:secure-transport":"true"
}
}
}
]
}
命令行curl测试

添加上面的存储桶策略后,通过 curl 测试下载对象 test:只有通过 https 协议的请求会返回200 OK;http 协议的请求会返回403 Forbidden

curl -X GET -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com" -H "Authorization: 这里是签名" "https://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com/test"

图片

curl -X GET -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com/test"
图片

限制上传文件的类型(cos:content-type)
背景知识:请求头部Content-Type

RFC 2616中定义的 HTTP 请求内容类型(MIME),例如application/xml或image/jpeg。

条件键 cos:content-type

使用条件键 cos:content-type 可以对请求的 Content-Type 头部进行限制。

示例2:限定上传对象(PutObject)的 Content-Type 必须为“image/jpeg”

假设主账号(uin:100000000001)拥有存储桶examplebucket-1250000000,可以通过cos:content-length条件键限制子用户(uin:100000000002)上传请求的 Content-Length 头的具体内容。

下面这个存储桶策略的含义是:限制使用 PutObject 上传对象必须携带Content-Type头部,且Content-Type的值为“image/jpeg”。

需要注意的是,string_equal要求请求必须携带Content-Type头部,且Content-Type 的值必须与规定值完全一致。在实际请求中,您需要明确指定请求的 Content-Type 头部。否则,当您的请求不携带 Content-Type 头部时,请求将会失败;此外,当您使用某些工具发起请求,并未明确指定 Content-Type 时,工具可能会为您自动添加不符合预期的Content-Type头部,也可能导致请求失败。

注:string_equal和strin_equal_if_exist 的区别:

条件操作符是否包含_if_exist的区别在于请求不带条件键对应的请求头/请求参数时如何处理。

条件操作符没有 _if_exist,如 string_equal,当请求不带对应的请求头/请求参数时,默认命中条件,即为 False。

条件操作符有 _if_exist,如 string_equal_if_exist,当请求不带对应的请求头/请求参数时,默认命中条件,即为 True 。

{
"Statement": [
{
"Principal": {
"qcs": [
“qcs::cam::uin/100000000001:uin/100000000002”
]
},
"Effect": "Allow",
"Action": [
"name/cos:PutObject"
],
"Resource": [
“qcs::cos:ap-guangzhou:uid/1250000000:examplebucket-1250000000/
],
"Condition": {
"string_equal": {
"cos:content-type": "image/jpeg"
}
}
},
{
"Principal": {
"qcs": [
“qcs::cam::uin/100000000001:uin/100000000002”
]
},
"Effect": "Deny",
"Action": [
"name/cos:PutObject"
],
"Resource": [
“qcs::cos:ap-guangzhou:uid/1250000000:examplebucket-1250000000/

],
"Condition": {
"string_not_equal_if_exist": {
"cos:content-type": "image/jpeg"
}
}
}
],
"version": "2.0"
}

命令行curl测试

添加上面的存储桶策略后,使用 PutObject 上传对象时,Content-Type 头部必须为"image/jpeg";正确的请求会返回200 OK,未携带 Content-Type 头部或头部值不是 image/jpeg 都会返回403 Forbidden

curl -X PUT -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com" -H "Content-Type: image/jpeg" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com/test2.jpeg" -T ./test2.jpeg
图片

curl -X PUT -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com/test2.jpeg" -T ./test2.jpeg
图片

限制上传文件的大小(cos:content-length)
请求头部Content-Length

RFC 2616中定义的 HTTP 请求内容长度(字节),在 PUT 和 POST 请求中经常使用。

条件键 cos:content-length

上传对象时,可以通过条件键cos:content-length限制请求头部Content-Length,进而限制上传对象的文件大小,以方便您更加灵活管理存储空间,避免上传过大、过小文件浪费存储空间与网络带宽。

在下面两个示例中,假设主账号(uin:100000000001)拥有存储桶examplebucket-1250000000,可以通过cos:content-length条件键限制子用户(uin:100000000002)上传请求的Content-Length头的大小。

示例3: 限制请求头部 Content-Length的最大值

限制 PutObject 和 PostObject 上传请求必须携带 Content-Length 头部,且这个头部的值不得大于100。

{
"Statement": [
{
"Action": [
"name/cos:PutObject",
"name/cos:PostObject"
],
"Condition": {
"numeric_less_than_equal": {
"cos:content-length": 100
}
},
"Effect": "Allow",
"Principal": {
"qcs": [
“qcs::cam::uin/100000000001:uin/100000000002”
]
},
"Resource": [
“qcs::cos:ap-guangzhou:uid/1250000000:examplebucket-1250000000/
]
},
{
"Action": [
"name/cos:PutObject",
"name/cos:PostObject"
],
"Condition": {
"numeric_greater_than_if_exist": {
"cos:content-length": 100
}
},
"Effect": "Deny",
"Principal": {
"qcs": [
“qcs::cam::uin/100000000001:uin/100000000002”
]
},
"Resource": [
“qcs::cos:ap-guangzhou:uid/1250000000:examplebucket-1250000000/

]
}
],
"version": "2.0"
}

命令行curl测试

添加上面的存储桶策略后,通过PutObject上传对象,Content-Length 的值不可超过100。在这里我们使用 curl 命令上传对象到COS,curl 会自动计算文件的大小(字节数),添加 Content-Length 头部上。

例如,test3 文件大小为77字节,通过 curl 命令上传,Content-Length为77,请求通过,返回200 OK。

curl -X PUT -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com/test" -T ./test3
图片

test4文件大小为145字节,通过curl命令上传,Content-Length为145,请求被拒绝,返回403 Forbidden。

curl -X PUT -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com/test" -T ./test4
图片

只允许用户获取指定版本号的对象
请求参数 versionId

请求参数 versionId 表示对象的版本号。您可以在下载对象(GetObject)、删除对象(DeleteObject)时使用请求参数 versionId 指定需要操作的对象版本。

不带 versionId 请求参数时,请求默认作用于对象的最新版本。

versionId 请求参数为一个空字符串时,等同于不带versionId请求参数时。

versionId 请求参数为字符串"null"的情况。对于一个存储桶在开启版本控制之前上传的对象,开启版本控制后,这批对象的版本号统一是字符串"null"

条件键 cos:versionid

条件键 cos:versionid 用于限制请求参数 versionId。

示例4:只允许用户获取指定版本号的对象

假设主账号(uin:100000000001)拥有存储桶examplebucket-1250000000,需要向其子用户(uin:100000000002)进行授权,仅允许子用户获取指定版本号的对象。

采用以下存储桶策略后,子用户(uin:100000000002)发起下载对象请求时,只有在携带了versionid参数,且versionid的值为版本号“MTg0NDUxMDQ0MzA5ODY1ODc2OTQ”时,请求才会成功。

{
"Statement": [
{
"Action": [
"name/cos:GetObject"
],
"Condition": {
"string_equal": {
"cos:versionid": "MTg0NDUxMDQ0MzA5ODY1ODc2OTQ"
}
},
"Effect": "Allow",
"Principal": {
"qcs": [
“qcs::cam::uin/100000000001:uin/100000000002”
]
},
"Resource": [
“qcs::cos:ap-guangzhou:uid/1250000000:examplebucket-1250000000/*”
]
}
],
"version": "2.0"
}

命令行curl测试

添加以上存储桶策略后,只有携带版本号MTg0NDUxMDQ0MzA5ODY1ODc2OTQ的下载请求才会通过,返回200 OK;不带版本号或者携带的版本号不是MTg0NDUxMDQ0MzA5ODY1ODc2OTQ,请求都会被拒绝,返回403 Forbidden。
curl -X GET -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com/test?versionId=MTg0NDUxMDQ0MzA5ODY1ODc2OTQ"
图片

curl -X GET -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com" -H "Authorization: 这里是签名 ""http://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com/test"
图片

— END —

推荐阅读