本文介绍如何使用 RAM 角色安全令牌对移动设备进行临时授权,以实现使用临时安全令牌直接访问相关资源。

背景信息

企业 A 开发了一款移动 App,并购买了 OSS 服务。移动 App 需要直连 OSS 上传或下载数据,但是移动 App 运行在用户自己的终端设备上,这些设备并不受 A 的控制。

企业 A 有如下要求:

  • 直传数据:企业 A不希望所有 App 都通过企业自己的服务端应用服务器(AppServer)来进行数据中转,而希望让 App 能直连 OSS 上传或下载数据。
  • 安全考虑:企业 A 不能将访问密钥保存到移动 App 中,因为移动设备是归属于用户控制,属于不可信任的运行环境。
  • 风险管控:企业 A 希望将安全风险控制到最小,每个移动 App 直连 OSS 时都必须使用最小权限的访问令牌且访问时效也要很短。

临时访问授权解决方案

  • 云账号 A 在 RAM 中创建一个角色,给角色授予合适的权限,并允许 AppServer 以 RAM 用户身份使用该角色。

    操作流程见创建角色、用户及授权

  • 当 App 需要直连 OSS 上传或下载数据时,AppServer 可以扮演角色(调用 STS AssumeRole),获取角色的一个临时安全令牌并传送给 App,App 就可以使用临时安全令牌直接访问 OSS API。

    操作流程见获取、传递角色令牌及访问

  • AppServer 可以在使用角色时进一步限制临时安全令牌的资源操作权限,以更精细地控制每个 App 的权限。

    操作流程见 限制 STS token 权限

创建角色、用户及授权

假设云账号 A 的 AccountID 为:11223344。

  1. 云账号 A 创建 RAM 角色: oss-readonly,并选择当前云账号作为受信云账号,即只允许云账号 A 下的 RAM 用户来扮演该角色。

    具体操作请参考角色

    角色创建成功后,在角色详情中可以查看到该角色的基本信息:

    • 角色的 Arn 如下:
      acs:ram::11223344:role/oss-readonly
    • 角色的信任策略(只允许云账号 A 下的 RAM 角色来扮演角色)如下:
      {
      "Statement": [
      {
       "Action": "sts:AssumeRole",
       "Effect": "Allow",
       "Principal": {
         "RAM": [
           "acs:ram::11223344:root"// 当角色类型为用户角色时,此处固定是root
         ]
       }
      }
      ],
      "Version": "1"
      }
  2. 云账号 A 给角色授权,向 RAM 角色(oss-readonly)授予AliyunOSSReadOnlyAccess(只读访问 OSS)的权限。

    具体操作请参考授权

  3. 云账号 A 为 AppServer 创建 RAM 用户身份: Appserver,并为该 RAM 用户创建 AccessKey 并授予AliyunSTSAssumeRoleAccess(调用 STS AssumeRole 接口)的系统策略。

获取、传递角色令牌及访问 OSS

App 获取并使用角色令牌调用 OSS API 的操作示意图如下:
图 1. 操作流程


AppServer 使用已拥有的 RAM 用户的 AccessKey 调用 STS API AssumeRole
说明 必须配置 AppServer 的 AccessKey,而非主账号 A 的 AccessKey。

使用 aliyuncli 来调用 AssumeRole 的命令示例如下:

$ aliyuncli sts AssumeRole --RoleArn acs:ram::11223344:role/oss-readonly --RoleSessionName client-001
 {
     "AssumedRoleUser": {
         "AssumedRoleId": "39157875257397****:client-001", 
         "Arn": "acs:ram::11223344:role/oss-readonly/client-001"
     }, 
     "Credentials": {
         "AccessKeySecret": "93ci2umK1QKNEja6WGqi1Ba7Q2Fv9PwxZqtVF2Vy****", 
         "SecurityToken": "CAES6AIIARKAAUiwSHpkD3GXRMQk9stDr3YSVbyGqanqkS+fPlEEkjZ+dlgFnGdCI2PV93jksole8ijH8dHJrHRA5JA1YCGsfX5hrzcNM37Vr4eVdWFVQhoCw0DXBpHv//ZcITp+ELRr4MHsnyGiErnDsXLkI7q/sbuWg6PACZ/jzQfEWQb/f7Y1Gh1TVFMuRjEzR2pza1hUamszOGRCWTZZeEp0WEFaayISMzkxNTc4NzUyNTczOTcyODU0KgpjbGllbnQtMDAxMKT+lIHBKjoGUnNhTUQ1QkoKATEaRQoFQWxsb3cSGwoMQWN0aW9uRXF1YWxzEgZBY3Rpb24aAwoBKhIfCg5SZXNvdXJjZUVxdWFscxIIUmVzb3VyY2UaAwoBKkoFNDMyNzRSBTI2ODQyWg9Bc3N1bWVkUm9sZVVzZXJgAGoSMzkxNTc4NzUyNTczOTcyODU0cgllY3MtYWRtaW544Mbewo/2****", 
         "Expiration": "2016-01-13T15:02:37Z", 
         "AccessKeyId": "STS.F13GjskXTjk38dBY6YxJt****"
     }, 
     "RequestId": "E1779AAB-E7AF-47D6-A9A4-53128708B6CE"
 }

限制 STS token 权限

  1. 调用 AssumeRole 后授予更小的权限。
    上述 AssumeRole 调用时没有指定 Policy 参数,意味着该 STS token 拥有 oss-readonly 的所有权限。如果需要进一步限制 STS token 的权限(例如:只允许访问 sample-bucket/2015/01/01/*.jpg),那么可以通过设置如下Policy 参数:
    $ aliyuncli sts AssumeRole --RoleArn acs:ram::11223344:role/oss-readonly --RoleSessionName client-002 --Policy "{\"Version\":\"1\", \"Statement\": [{\"Effect\":\"Allow\", \"Action\":\"oss:GetObject\", \"Resource\":\"acs:oss:*:*:sample-bucket/2015/01/01/*.jpg\"}]}"
    {
       "AssumedRoleUser": {
           "AssumedRoleId": "39157875257397****:client-002", 
           "Arn": "acs:ram::11223344:role/oss-readonly/client-002"
       }, 
       "Credentials": {
           "AccessKeySecret": "28Co5Vyx2XhtTqj3RJgdud4ntyzrSNdUvNygAj7x****", 
           "SecurityToken": "CAESnQMIARKAASJgnzMzlXVyJn4KI+FsysaIpTGm8ns8Y74HVEj0pOevO8ZWXrnnkz4a4rBEPBAdFkh3197GUsprujsiU78FkszxhnQPKkQKcyvPihoXqKvuukrQ/Uoudk31KAJEz5o2EjlNUREcxWjRDRSISMzkxNTc4NzUyNTczOTcyODU0KgpjbGllbnQtMDAxMKmZxIHBKjoGUnNhTUQ1Qn8KATEaegoFQWxsb3cSJwoMQWN0aW9uRXF1YWxzEgZBY3Rpb24aDwoNb3NzOkdldE9iamVjdBJICg5SZXNvdXJjZUVxdWFscxIIUmVzb3VyY2UaLAoqYWNzOm9zczoqOio6c2FtcGxlLWJ1Y2tldC8yMDE1LzAxLzAxLyouanBnSgU0MzI3NFIFMjY4NDJaD0Fzc3VtZWRSb2xlVXNlcmAAahIzOTE1Nzg3NTI1NzM5NzI4NTRyCWVjcy1hZG1pbnjgxt7Cj/bo****", 
           "Expiration": "2016-01-13T15:03:39Z", 
           "AccessKeyId": "STS.FJ6EMcS1JLZgAcBJSTDG1****"
       }, 
       "RequestId": "98835D9B-86E5-4BB5-A6DF-9D3156ABA567"
    }
    说明 上述 STS token 的默认过期时间为 3600 秒,用户还可以通过 DurationSeconds 参数来限制 STS token 的过期时间(最长不超过 3600 秒)。
  2. AppServer 获取并解析临时凭证。
    • AppServer 从 AssumeRole 返回的临时凭证中获取 AccessKeyId、AccessKeySecret 和 STS token。
    • 考虑到 STS token 过期时间较短,如果应用业务需要一个较长的过期时间,需要 AppServer 重新颁发新的 STS token(比如每隔 1800 秒颁发一次 STS token)。
  3. AppServer 将临时凭证传递给 App。
  4. App 使用 STS token 直接访问云服务的 API(比如 OSS)。

    下面是 aliyuncli 使用 STS token 访问 OSS 对象的操作命令(颁发给 client-002 的 STS token):

    
    配置STS token语法:aliyuncli oss Config --host  --accessid  --accesskey  --sts_token 
    $ aliyuncli oss Config --host oss.aliyuncs.com --accessid STS.FJ6EMcS1JLZgAcBJSTDG1**** --accesskey 28Co5Vyx2XhtTqj3RJgdud4ntyzrSNdUvNygAj7xEMow --sts_token CAESnQMIARKAASJgnzMzlXVyJn4KI+FsysaIpTGm8ns8Y74HVEj0pOevO8ZWXrnnkz4a4rBEPBAdFkh3197GUsprujsiU78FkszxhnQPKkQKcyvPihoXqKvuukrQ/Uoudk31KAJEz5o2EjlNUREcxWjRDRSISMzkxNTc4NzUyNTczOTcyODU0KgpjbGllbnQtMDAxMKmZxIHBKjoGUnNhTUQ1Qn8KATEaegoFQWxsb3cSJwoMQWN0aW9uRXF1YWxzEgZBY3Rpb24aDwoNb3NzOkdldE9iamVjdBJICg5SZXNvdXJjZUVxdWFscxIIUmVzb3VyY2UaLAoqYWNzOm9zczoqOio6c2FtcGxlLWJ1Y2tldC8yMDE1LzAxLzAxLyouanBnSgU0MzI3NFIFMjY4NDJaD0Fzc3VtZWRSb2xlVXNlcmAAahIzOTE1Nzg3NTI1NzM5NzI4NTRyCWVjcy1hZG1pbnjgxt7Cj/bo****
    访问OSS对象
    $ aliyuncli oss Get oss://sample-bucket/2015/01/01/grass.jpg grass.jpg

更多参考

关于移动应用直传场景,可参考以下文档: