引言
在使用 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.myzijiebao.com" -H "Authorization: 这里是签名" "https://examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com/test"
curl -X GET -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.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.myzijiebao.com" -H "Content-Type: image/jpeg" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com/test2.jpeg" -T ./test2.jpeg
curl -X PUT -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.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.myzijiebao.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com/test" -T ./test3
test4文件大小为145字节,通过curl命令上传,Content-Length为145,请求被拒绝,返回403 Forbidden。
curl -X PUT -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.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.myzijiebao.com" -H "Authorization: 这里是签名" "http://examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com/test?versionId=MTg0NDUxMDQ0MzA5ODY1ODc2OTQ"
curl -X GET -v -H "Host: examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com" -H "Authorization: 这里是签名 ""http://examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com/test"
— END —