「OSS」阿里云OSS之STS临时访问授权

前言

小白后台仅仅只是一位小白Java

上一篇文章中,小白介绍了阿里云OSS有关自定义域名、证书托管的内容,这一片文章我们将着重介绍一下阿里云OSS身份认证相关的内容。

拓展开来说,我们这里介绍的 身份认证 机制其实也是贯穿于阿里云各个产品线的 访问控制 机制,换句话说就是阿里云为客户提供的 用户身份管理资源访问控制 服务,但是这里我们只介绍在阿里云OSS这个产品下如何配置和使用身份认证服务,不对阿里云的整套 访问控制 服务做深入探讨。

介绍

阿里云提供的 权限管理系统访问控制服务 主要包含两部分,RAM(Resource Access Management)和 STS(Security Token Service),RAM 主要的作用是控制账号系统的权限,你可以使用 RAM 在主账号的权限范围内创建子用户,给不同的子用户分配不同的权限从而达到授权管理的目的。STS 是一个安全凭证(Token)的管理系统,你可以使用 STS 来完成对于临时用户的访问授权。

RAM 和 STS 需要解决的一个核心问题是如何在不暴露主账号的 AccessKey 的情况下安全的授权别人访问,因为一旦主账号的 AccessKey 暴露出去的话会带来极大的安全风险,别人可以随意操作该账号下所有的资源,盗取重要信息等。

RAM 提供一种 长期有效 的权限控制机制,通过分出不同权限的 子账号,将不同的权限分给不同的用户,这样一旦子账号泄露也不会造成全局的信息泄露。但是,由于子账号在一般情况下是长期有效的,因此,子账号的 AccessKey 也是不能泄露的。

相对于 RAM 提供的长效控制机制,STS 提供的是一种 临时访问授权 。通过 STS 可以返回 临时的 AccessKey 和 Token,这些信息可以直接发给临时用户用来访问 OSS 。一般来说,从 STS 获取的权限会受到更加严格的限制,并且拥有时间限制,因此这些信息泄露之后对于系统的影响也很小。

场景描述

使用阿里云OSS的过程中,一般大家对于 RAM 会比较了解和熟悉,通常的做法也都是在阿里云的 RAM访问控制台 为 OSS 服务单独创建一个具备 OSS 相应访问权限的 RAM子账号,然后在之后的 API 调用过程中使用该 RAM子账号 的 AccessKey 进行签名等操作。

看起来这种通过 RAM子账号 实现对 OSS 进行访问控制的方式是挺安全的,那么这种方式有没有什么缺陷呢?或者有没有更加安全的方式?接下来我们先来给大家举一个模拟场景的例子。

Example
某个阿里云用户,名为 小白,其在 OSS 下有两个私有的 Bucketbucket-abucket-b 。小白对这两个 Bucket 都拥有完全的权限。

为了避免阿里云主账号的 AccessKey 泄露导致安全风险,小白使用 RAM 创建了两个子账号 小明小贤,小明对 bucket-a 拥有读写权限,小贤对 bucket-b 拥有读写权限。小明和小贤都拥有独立的 AccessKey,这样万一某个子账号泄露了也只会影响其中一个 Bucket,而且小白可以很方便的在控制台取消泄露用户的授权。

现在因为某些原因,需要授权给别人读取 bucket-a 中的 Object,这种情况下不应该直接把 小明AccessKey 透露出去;那么,这个时候可以新建一个 角色,比如 Bucket-A-Reader,给这个角色赋予读取 bucket-a权限。但是请注意,这个时候 Bucket-A-Reader 还是没法直接用的,因为并不存在对应 角色 Bucket-A-ReaderAccessKeyBucket-A-Reader 现在仅仅表示一个拥有访问 bucket-a 权限的一个虚拟实体。

为了能获取 临时授权,这个时候可以调用 STSAssumeRole 接口,告诉 STS ,子账号 小明 将要扮演 Bucket-A-Reader 这个角色,如果成功,STS 会返回一个 临时的 AccessKeyIdAccessKeySecret 还有 SecurityToken 作为访问凭证。将这个 临时授权凭证 发给需要访问的 临时用户 就可以获得访问 bucket-a 的临时权限了,凭证过期的时间可以在调用 AssumeRole 接口的时候指定,最大不超过2小时。

STS临时访问授权

STS临时访问授权 还是少不了 RAM 机制的支撑,一般要实现 STS 临时访问授权需要依次完成 创建RAM子账号 > 创建自定义角色 > 创建自定义授权策略 > 自定义角色添加自定义授权策略 > 子账号授权STS权限 > STS签发临时凭证

准备工作

1. 创建 RAM 子账号

创建一个 RAM 子账号 ram_test_app不需要赋予任何权限,因为在扮演角色的时候会自动获得被扮演角色的所有权限。

2. 创建角色

这里创建两个角色,一个用于用户读取等操作,一个用于用户上传文件。

  • 打开访问控制的管理控制台,选择 角色管理 > 新建角色 ;
  • 选择角色类型,这里选择用户角色;
  • 填写类型信息,因为角色是被阿里云账号使用过的,因此选择默认的即可;
  • 配置角色基本信息;
创建角色
配置角色

3. 自定义授权策略

创建完角色之后,角色是没有任何权限的,因此这里和上文所述一样需要新建一个自定义的授权策略。授权策略如下:

  // 该授权策略表示对ram-test-app拥有只读权限
  {
    "Version": "1",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "oss:ListObjects",
          "oss:GetObject"
        ],
        "Resource": [
          "acs:oss:*:*:ram-test-app",
          "acs:oss:*:*:ram-test-app/*"
        ]
      }
    ]
  }
创建授权策略

4. 自定义角色授权

建立完成自定义授权策略后,即可在 角色管理 里面给自定义角色 RamTestAppReadOnly 添加上 ram-test-app 的只读授权。

角色管理
添加授权策略

5. 再次添加角色&授权

按照上文同样的方法,建立一个 RamTestAppWrite 的角色,并且赋予写 ram-test-app 的自定义授权,授权如下:

  {
    "Version": "1",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "oss:DeleteObject",
          "oss:ListParts",
          "oss:AbortMultipartUpload",
          "oss:PutObject"
        ],
        "Resource": [
          "acs:oss:*:*:ram-test-app",
          "acs:oss:*:*:ram-test-app/*"
        ]
      }
    ]
  }

目前新建的两个角色为:RamTestAppReadOnlyRamTestAppWrite,分别表示了对于 Bucket ram-test-app 的读写权限。

自定义角色

临时授权访问凭据

创建了角色之后,接下来就可以使用临时授权来访问OSS了。

在正式使用之前,还有一些工作需要完成。扮演角色 也是需要授权的,否则任意子账号都可以扮演这些角色会带来不可预计的风险,因此有扮演对应角色需求的子账号需要显式的配置权限。

1. 在授权管理策略中新建两个自定义的授权策略,分别如下:

  {
    "Statement": [
      {
        "Action": "sts:AssumeRole",
        "Effect": "Allow",
        "Resource": "acs:ram::1894******722283:role/ramtestappreadonly"
      }
    ],
    "Version": "1"
  }

使用相同的方法创建另一个自定义授权策略:

  {
    "Statement": [
      {
        "Action": "sts:AssumeRole",
        "Effect": "Allow",
        "Resource": "acs:ram::1894******722283:role/ramtestappwrite"
      }
    ],
    "Version": "1"
  }

这里 Resource 后面填写的内容表示某个角色 ID,角色的 ID 可以在 角色管理 > 角色详情 中找到。

2. 将这两个授权赋给 ram_test_app 这个账号

现在一切准备就绪,可以正式使用STS来授权访问了。

RAM进行STS临时授权

这里小白给出基于 SpringBoot 的 Java SDK 源码实现

  <!-- OSS Maven Dependency -->
  <dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.4.2</version>
  </dependency>
  public AssumeRoleResponse buildAliyunSTSCredentials() throws ClientException {
    // STS
    DefaultProfile.addEndpoint("", "", "Sts", "sts.cn-hangzhou.aliyuncs.com");
    IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
    DefaultAcsClient client = new DefaultAcsClient(profile);

    final AssumeRoleRequest request = new AssumeRoleRequest();
    request.setMethod(MethodType.POST);
    request.setProtocol(ProtocolType.HTTPS);
    request.setDurationSeconds(60 * 60 * 1L);
    request.setRoleArn("acs:ram::12************41:role/RamTestAppReadOnly");  // 要扮演的角色ID
    request.setRoleSessionName("external-username");
    // request.setPolicy(policy);

    // 生成临时授权凭证
    final AssumeRoleResponse response = client.getAcsResponse(request);

    String appKey = response.getCredentials().getAccessKeyId();  // 临时凭据AccessKeyId
    String appSecret = response.getCredentials().getAccessKeySecret();  // 临时凭据AccessKeySecret
    String securityToken = response.getCredentials().getSecurityToken();  
    String expiration = response.getCredentials().getExpiration();
    return response;
  }

accessKeyId表示RAM子账号的AccessKeyId;
accessKeySecret表示RAM子账号的AccessKeySecret;
RoleArn表示的是需要扮演的角色ID,角色的ID可以在 角色管理 > 角色详情 中找到;
RoleSessionName是一个用来标示临时凭证的名称,一般来说建议使用不同的应用程序用户来区分;
DurationSeconds指的是临时凭证的有效期,单位是s,最小为900,最大为3600;
Policy表示的是在扮演角色的时候额外加上的一个权限限制;
appKey表示创建的临时凭据AccessKeyId;
appSecret表示创建的临时凭据AccessKeySecret;

总结

其实实现STS临时访问授权的过程就是 创建RAM子账号 > RAM子账号授予STS权限 > RAM子账号扮演指定角色,拿到临时授权凭证就可以进行服务端相关的签名/上传等权限内的操作了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容