混合云场景下使用STS进行OSS的一次性授权

更新时间:
复制为 MD 格式

本实践以对象存储OSS为例,通过对STS临时Token授权的实践,完成了产品的临时授权,对比较敏感的业务场景,提供一种临时授权的思路,可以更好的保障企业上云的安全。

前提条件

适用于对象存储OSS,云平台基于企业V3.12及以上版本。

STS介绍

阿里云STS(SecurityToken Service)是阿里云提供的一种临时访问权限管理服务。通过STS服务,您所授权的身份主体(RAM用户、RAM用户组或RAM角色)可以获取一个自定义时效和访问权限的临时访问令牌。

使用场景

对于您本地身份系统所管理的用户,比如您的App的用户、您的企业本地账号、第三方App的用户 ,将这部分用户称为联盟用户。此外,联盟用户还可以是您创建的能访问您的阿里云资源应用程序的用户。这些联盟用户可能需要直接访问OSS资源。

对于这部分联盟用户,通过阿里云STS服务为阿里云账号(或RAM用户)提供短期访问权限管理。您不需要透露云账号(或RAM用户)的长期密钥(如登录密码、AccessKey),只需要生成一个短期访问凭证给联盟用户使用即可。这个凭证的访问权限及有效期限都可以由您自定义。您不需要关心权限撤销问题,访问凭证过期后会自动失效。

方案概述

方案实现流程。1

  1. 创建RAM用户。

  2. 创建RAM CreateAccessKey。(创建RAM密钥,在获取STS有效访问凭证时使用)

  3. 创建STS访问AssumeRole接口的权限策略。

  4. RAM用户授予AssumeRole接口权限策略 。

  5. 创建RAM角色。

  6. 创建RAM角色的权限策略。

  7. 添加权限策略给RAM角色。

  8. 获取STS有效访问凭证。

  9. 使用STS获取的临时访问凭证访问OSS。

方案详细配置

  1. 创建RAM用户。

    1. 登录Apsara Uni-manager运营控制台,在页面顶部的菜单栏中,单击产品>其他>API与工具,进入API与工具页面,产品选择RAM,然后选择Createuser api进行调试。23

    2. 分别填写regionid、ak、sk、email、mobilephone、username信息,单击调用接口,返回参数为true则表明创建用户成功。4

      注意

      这里的ak、sk为所在组织的ak、sk,可以通过企业>组织管理>对应组织>获取accesskey,来获取。

    1
  2. 创建RAM CreateAccessKey(创建RAM密钥,在获取STS有效访问凭证时使用)。

    选择CreateAccessKey api进行调试,分别填写regionid、ak、sk、username进行调试,返回参数为true则表明创建成功,记录下创建的aksk。5

  3. 创建STS访问AssumeRole接口的权限策略。

    选择CreatePolicy api进行调试,regionid、ak、sk、policyname、policydocument的信息按照如下格式进行填写:

    1. {"Statement":[{"Action": "sts:AssumeRole","Effect":"Allow","Resource": "*" } ],"Version":"1"},然后进行调试,返回true则表明创建成功,记录下policynametype。6

  4. RAM用户授予AssumeRole接口权限策略。

    选择AttachPolicyToUser api进行调试,分别填写regionid、ak、sk、username、policyname、policytype的信息进行调试,返回true则表明创建成功。7

  5. 创建RAM角色。

    选择CreateRole api进行调试,regionid、ak、sk、rolename、AssumeRolePolicyDocument的信息按照如下格式填写(ID值为云账号id):

    {"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"RAM":"acs:ram::1357623202xxxxxx:root"}}],"Version":"1"},然后进行调试,返回true则表明创建RAM。9

  6. 创建RAM角色的权限策略。

    选择CreatePolicy api进行调试,regionid、ak、sk、policyname、policydocument的信息按照如下格式填写(其中ossstsBucket名称):

    {"Statement":[{"Effect":"Allow","Action":["oss:ListObjects","oss:GetObject"],"Resource":["acs:oss:*:*:osssts","acs:oss:*:*:osssts/*"]}],"Version":"1"},然后进行调试,返回true则表明创建成功,记录下policynametype。8

  7. 添加权限策略给RAM角色。

    选择AttachPolicyToRole api进行调试,分别填写regionid、ak、sk、rolename、policyname、policytype的信息,然后进行调试,返回true则表明创建成功。10

  8. 获取STS有效访问凭证。

    调用脚本生成STS有效凭证,会生成STS有效访问凭证的ak,sk,ststoken,以及有效凭证的过期时间。1脚本示例:

    # -*- coding: utf-8 -*-
    import oss2
    import json
    # -*- coding: utf-8 -*-
     
    from aliyunsdkcore import client
    from aliyunsdksts.request.v20150401 importAssumeRoleRequest
    import json
    import oss2
    import datetime
     
    # oss-serverendpoint,在天基-报表-所有报表-服务注册变量中搜索oss-server,拿到"api-endpoint"值
    endpoint ='oss-cn-hangzhou-ste4-d01-a.ops.ste4.com'
     
    # RAM用户的aksk
    access_key_id = 'ciA9iBJYoCxxxx'
    access_key_secret = '6ZBoI6Fhxxxxxx'
     
    # 填写Bucket名称。
    bucket_name = 'osssts'
     
    # 填写Object完整路径和字符串。Object完整路径中不能包含Bucket名称。
    object_name = 'sts.txt'
     
    # 填写角色的ARN信息,创建role时会生成该信息。格式为acs:ram::$accountID:role/$roleName,其中$accountID为阿里云主账号ID,$roleNameRAM角色名称。
    role_arn ='acs:ram::1357xxxxxxx:role/role-3'
     
    # 创建权限策略。
    # 只允许对名称为examplebucketBucket下的所有资源执行GetObject,ListObjects操作。
    policy_text = '{"Version":"1", "Statement": [{"Action":["oss:ListObjects","oss:GetObject"], "Effect":"Allow", "Resource":["acs:oss:*:*:osssts","acs:oss:*:*:osssts/*"]}]}'
    clt = client.AcsClient(access_key_id,access_key_secret, 'cn-hangzhou-ste4-d01', verify=False)
    req = AssumeRoleRequest.AssumeRoleRequest()
    req.set_endpoint('sts.cloud.ste4.com')
     
    # 设置返回值格式为JSON。
    req.set_accept_format('json')
    req.set_RoleArn(role_arn)
     
    # 用户自定义参数。此参数用来区分不同的令牌,可用于用户级别的访问审计。
    req.set_RoleSessionName('test1')
    req.set_Policy(policy_text)
     
    # 设置超时时间
    req.set_DurationSeconds(900)
    body = clt.do_action_with_exception(req)
     
    # 打印RAM用户的AccessKeyIdAccessKeySecretSTS申请临时访问凭证,以及过期时间
    token = json.loads(oss2.to_unicode(body))
    utc = token['Credentials']['Expiration']
    UTC_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
    utcTime = datetime.datetime.strptime(utc,UTC_FORMAT)
    localtime = utcTime +datetime.timedelta(hours=8)
    print('Expiration_time:',localtime)
    print('AccessKeyId:',token['Credentials']['AccessKeyId'])
    print('AccessKeySecret:',token['Credentials']['AccessKeySecret'])
    print('SecurityToken:',token['Credentials']['SecurityToken'])
  9. 使用STS获取的临时访问凭证访问OSS。

    1. 将上面步骤中生成的ak、sk、安全token填写到下面的demo文件中,然后进行脚本调用,可以查看存储空间下的所有文件。

      脚本示例:

      # 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
       
      auth =oss2.StsAuth('STS.3zz3kjbpx8RSgkKJAfoJzh4quY','4jaWmFDTfYCWpLQD1p28zkxcdMn7Ex5p2xSm4XQsAj7q','CAISsQJ1q6Ft5B6yfSjI0rnPeNHej69Zj5C4ZU36rkEzY8VWh/Hal0fGAXtEeHJhBOkYvv00mWlX5/wejIMeV5JeWRWczDTvNFMQo22beIPkl5GfCtVm4cTX+AHxZjf/2MjNGbWbKPrWZvaqbX3diyZ32sGUXD6+XlujQ9Xr7pl8dYYzXxKkSjBECdxKPWkHr9QBZ1TcKdGnMBPhnhD+bixStxF7lHl05Imm38SY8WC+tlDhzfIPrImDYPreZsJ3bpBkSIX3jq4kcbHayzJLiWRD/7wki7dfq3WV/IOaGEJK/w7Bccisq4Yyc1EjPfJiQf4U8KiizMcV4LKDy97FrD9WJvxQXijlQ4St/dDJAuvBNKxiJeqgaimUjIDWbcSs7FJ+PSoBWhlNf9dkcW/luIiBpoEGQBqAASFkUNzlvMviBPZzfM7X5s38PA8M9zEK1ehaftxO8UoTlpQ43S7xx6vwlFBYC7rQlRNR7A7MPPXQCCY6Hh+le9nqgefU8KXKDUVePTey7EYS6bTIRRxr8Nctby0ezLg9dUZcxQI+KwJF1q93cuvYeZeXGP0XiMR8NPLDFLsIfLja')
       
      # yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
      # 填写Bucket名称。
      bucket = oss2.Bucket(auth,'oss-cn-hangzhou-ste4-d01-a.ops.ste4.com', 'osssts')
       
       
      # 列举存储空间下所有文件。
      for obj in oss2.ObjectIterator(bucket):
      print(obj.key)
    2. 当超时之后,访问时报错。14脚本示例:

      # -*- coding: utf-8 -*-
      import oss2
       
      # 获取STS有效访问凭证,ak,sk,ststoken信息填入下方
      auth = oss2.StsAuth('yourAccessKeyId','yourAccessKeySecret','STStoken')
      # Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com,和bucket名称
      # 填写Bucket名称。
      bucket = oss2.Bucket(auth,'oss-cn-hangzhou-ste4-d01-a.ops.ste4.com', 'osssts')
       
      # 列举存储空间下所有文件。
      for obj in oss2.ObjectIterator(bucket):
      print(obj.key)