本教程示例详细演示了如何使用 RAM Policy 控制用户对 OSS 存储空间(Bucket)和文件夹的访问。

背景信息

  • RAM Policy操作比较复杂,强烈推荐您使用简单易用的图形化配置方式Bucket Policy
  • 如果您选择使用RAM Policy,建议您通过官方工具RAM策略编辑器快速生成所需的RAM Policy。

存储空间和文件夹的基本概念

阿里云 OSS 的数据模型为扁平型结构,所有文件都直接隶属于其对应的存储空间。因此,OSS 缺少文件系统中类似于目录与子文件夹的层次结构。但是,您可以在 OSS 控制台上模拟文件夹层次结构。在该控制台中,您可以按文件夹对相关文件进行分组、分类和管理,如下图所示。
教程示例:使用RAM Policy控制OSS的访问权限_权限控制_数据安全_开发指南_对象存储 OSS 阿里云技术文档 第1张

OSS 提供使用键值(key)对格式的分布式对象存储服务。用户根据其唯一的key(对象名)检索对象的内容。例如,名为 example-company 的存储空间有三个文件夹:Development、 MarketingPrivate,以及一个对象 oss-dg.pdf

  • 在创建 Development 文件夹时,控制台会创建一个 key 为Development/的对象。注意,文件夹的 key 包括分隔符 /
  • 当您将名为 ProjectA.docx 的对象上传到 Development 文件夹中时,控制台会上传该对象并将其 key 设置为Development/ProjectA.docx

    在该 key 中,Development 为前缀,而/为分隔符。您可以从存储空间中获取具有特定前缀和分隔符的所有对象的列表。在控制台中,单击 Development 文件夹时,控制台会列出文件夹中的对象,如下图所示。


    教程示例:使用RAM Policy控制OSS的访问权限_权限控制_数据安全_开发指南_对象存储 OSS 阿里云技术文档 第2张
    说明 当控制台列出 example-company 存储空间中的 Development 文件夹时,它会向 OSS 发送一个用于指定前缀 Development 和分隔符/的请求。控制台的响应与文件系统类似,会显示文件夹列表。上例说明,存储空间 example-company 有三个对象,其 key 分别为 Development/Alibaba Cloud.pdfDevelopment/ProjectA.docxDevelopment/ProjectB.docx

控制台通过对象的 key 推断逻辑层次结构。当您创建对象的逻辑层次结构时,您可以管理对个别文件夹的访问,如本教程后面描述的那样。

在本教程开始之前,您还需要知道“根级”存储空间内容的概念。假设 example-company 存储空间包含以下对象:

  • Development/Alibaba Cloud.pdf
  • Development/ProjectA.docx
  • Development/ProjectB.docx
  • Marketing/data2016.xlsx
  • Marketing/data2016.xlsx
  • Private/2017/images.zip
  • Private/2017/promote.pptx
  • oss-dg.pdf

这些对象的 key 构建了一个以 Development、MarketingPrivate 作为根级文件夹并以 oss-dg.pdf 作为根级对象的逻辑层次结构。当您单击 OSS 控制台中的存储空间名时,控制台会将一级前缀和一个分隔符(Development/、Marketing/Private/)显示为根级文件夹。对象 oss-dg.pdf 没有前缀,因此显示为根级别项。


教程示例:使用RAM Policy控制OSS的访问权限_权限控制_数据安全_开发指南_对象存储 OSS 阿里云技术文档 第3张

OSS 的请求和响应逻辑

在授予权限之前,我们需要清楚,当用户单击某个存储空间的名字时控制台向 OSS 发送的是什么请求、OSS 返回的是什么响应,以及控制台如何解析该响应。

当用户单击某个存储空间名时,控制台会将 GetBucket 请求发送至 OSS。此请求包括以下参数:

  • prefix,其值为空字符串。
  • delimiter,其值为/

请求示例如下所示:

GET /?prefix=&delimiter=/ HTTP/1.1
Host: example-company.oss-cn-hangzhou.aliyuncs.com
Date: Fri, 24 Feb 2012 08:43:27 GMT
Authorization: OSS qn6qrrqxo2oawuk53otfjbyc:DNrnx7xHk3sgysx7I8U9I9IY1vY=

OSS 返回的响应包括ListBucketResult元素:

HTTP/1.1 200 OK
x-oss-request-id: 534B371674E88A4D8906008B
Date: Fri, 24 Feb 2012 08:43:27 GMT
Content-Type: application/xml
Content-Length: 712
Connection: keep-alive
Server: AliyunOSS
<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns=¡±http://doc.oss-cn-hangzhou.aliyuncs.com¡±>
<Name>example-company</Name>
<Prefix></Prefix>
<Marker></Marker>
<MaxKeys>100</MaxKeys>
<Delimiter>/</Delimiter>
    <IsTruncated>false</IsTruncated>
    <Contents>
        <Key>oss-dg.pdf</Key>
        ...
    </Contents>
   <CommonPrefixes>
        <Prefix>Development</Prefix>
   </CommonPrefixes>
      <CommonPrefixes>
        <Prefix>Marketing</Prefix>
   </CommonPrefixes>
      <CommonPrefixes>
        <Prefix>Private</Prefix>
   </CommonPrefixes>
</ListBucketResult>

由于 oss-dg.pdf 不包含/分隔符,因此 OSS 在<Contents/>元素中返回该 key。存储空间 example-company 中的所有其他 key 都包含/分隔符,因此 OSS 会将这些 key 分组,并为每个前缀值 Development/、Marketing/ Private/ 返回一个 <CommonPrefixes/> 元素。该元素是一个字符串,包含从这些 key 的第一个字符开始到第一次出现指定的/分隔符之间的字符。

控制台会解析此结果并显示如下的根级别项:


教程示例:使用RAM Policy控制OSS的访问权限_权限控制_数据安全_开发指南_对象存储 OSS 阿里云技术文档 第4张

现在,如果用户单击 Development 文件夹,控制台会将 GetBucket 请求发送至 OSS。此请求包括以下参数:

  • prefix,其值为 Development/
  • delimiter,其值为/

请求示例如下所示:

GET /?prefix=Development/&delimiter=/ HTTP/1.1
Host: oss-example.oss-cn-hangzhou.aliyuncs.com
Date: Fri, 24 Feb 2012 08:43:27 GMT
Authorization: OSS qn6qrrqxo2oawuk53otfjbyc:DNrnx7xHk3sgysx7I8U9I9IY1vY=

作为响应,OSS 返回以指定前缀开头的 key:

HTTP/1.1 200 OK
x-oss-request-id: 534B371674E88A4D8906008B
Date: Fri, 24 Feb 2012 08:43:27 GMT
Content-Type: application/xml
Content-Length: 712
Connection: keep-alive
Server: AliyunOSS
<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns=¡±http://doc.oss-cn-hangzhou.aliyuncs.com¡±>
<Name>example-company</Name>
<Prefix>Development/</Prefix>
<Marker></Marker>
<MaxKeys>100</MaxKeys>
<Delimiter>/</Delimiter>
    <IsTruncated>false</IsTruncated>
    <Contents>
        <Key>ProjectA.docx</Key>
        ...
    </Contents>
    <Contents>
        <Key>ProjectB.docx</Key>
        ...
    </Contents>
</ListBucketResult>

控制台会解析此结果并显示如下的 key:


教程示例:使用RAM Policy控制OSS的访问权限_权限控制_数据安全_开发指南_对象存储 OSS 阿里云技术文档 第5张

教程示例

本教程示例如下所示:

  • 创建一个存储空间 example-company,然后向其中添加三个文件夹(DevelopmentMarketingPrivate)。
  • 您有 Anne 和 Leo 两个用户。您希望 Anne 只能访问 Development 文件夹而 Leo 则只能访问 Marketing 文件夹,并且希望将 Private 文件夹保持私有。在教程示例中,通过创建访问控制(RAM)用户(Anne 和 Leo)来管理访问权限,并授予必要的权限。
  • RAM 还支持创建用户组并授予适用于组中所有用户的组级别权限。这有助于更好地管理权限。在本示例中,Anne 和 Leo 都需要一些公共权限。因此,您还要创建一个名为 Staff 的组,然后将 Anne 和 Leo 添加到该组中。首先,您需要给该组分配策略授予权限。然后,将策略分配给特定用户,添加特定用户的权限。
说明 本教程示例使用 example-company 作为存储空间名、使用 Anne 和 Leo 作为 RAM 用户名并使用 Staff 作为组名。由于阿里云 OSS 要求存储空间名全局唯一,所以您需要用自己的存储空间名称替换本教程中的存储空间名。

示例准备

本示例使用阿里云主账号创建 RAM 用户。最初,这些用户没有任何权限。您将逐步授予这些用户执行特定 OSS 操作的权限。为了测试这些权限,您需要使用每个用户的 RAM 账号登录到控制台。当您作为主账号所有者逐步授予权限并作为 RAM 用户测试权限时,您需要每次使用不同账号进行登录和注销。您可以使用一个浏览器来执行此测试。如果您可以使用两个不同的浏览器,则该测试过程用时将会缩短:一个浏览器用于使用主账号连接到阿里云控制台,另一个浏览器用于使用 RAM 账号进行连接。

要使用您的主账号登录到阿里云控制台。 RAM 用户不能使用相同的链接登录,必须使用 RAM 用户登录链接。作为主账号所有者,您可以向 RAM 用户提供此链接。

说明 有关 RAM 的详细信息,请参见使用 RAM 用户账号登录

步骤 1:创建存储空间

在此步骤中,您可以使用主账号登录到 OSS 控制台、创建存储空间、将文件夹(Development、Marketing、Private)添加到存储空间中,并在每个文件夹中上传一个或两个示例文档。

  1. 使用主账号登录 OSS 控制台
  2. 创建名为 example-company 的存储空间,详情请参见创建存储空间
  3. 将一个文件上传到存储空间中,上传文件的方法请参见上传文件
    本示例假设您将文件 oss-dg.pdf 上传到存储空间的根目录。
  4. 添加名为 Development、Marketing Private 的三个文件夹,配置方法请参见创建文件夹
  5. 在每个文件夹中上传一到两个文件。
    本示例假设您将具有以下对象键的对象上传到存储空间中:
    • Development/Alibaba Cloud.pdf
    • Development/ProjectA.docx
    • Development/ProjectB.docx
    • Marketing/data2016.xlsx
    • Marketing/data2016.xlsx
    • Private/2017/images.zip
    • Private/2017/promote.pptx
    • oss-dg.pdf

步骤 2:创建 RAM 用户和组

在此步骤中,您使用 RAM 控制台将两个 RAM 用户 Anne 和 Leo 添加到主账号中。您还将创建一个名为 Staff 的组,然后将这两个用户添加到该组中。
说明 在此步骤中,不要分配任何授予这些用户权限的策略。在以下步骤中,您将逐步为其授予权限。

有关创建 RAM 用户的详细过程,请参见 RAM 快速入门中的创建 RAM 用户。请为每个 RAM 用户创建登录密码。

有关创建组的详细过程,请参见 RAM 用户指南中的创建组

步骤 3:确认 RAM 用户没有任何权限

如果您使用两个浏览器,现在可以在另一个浏览器中使用其中一个 RAM 用户账号登录到控制台。

  1. 打开 RAM 用户登录链接,并用 Anne 或 Leo 的账号登录到 RAM 控制台。详情请参见使用 RAM 用户账号登录
  2. 进入 OSS 控制台
    您会发现控制台中没有任何存储空间,这意味着 Anne 没有存储空间 example-company 的任何权限。

步骤 4:授予组级别权限

我们希望 Anne 和 Leo 都能执行以下操作:

  • 列出主账号所拥有的所有存储空间

    为此,Anne 和 Leo 必须具有执行 oss:ListBuckets 操作的权限。

  • 列出 example-company 存储空间中的根级别项、文件夹和对象

    为此,Anne 和 Leo 必须具有对 example-company 存储空间执行 oss:ListObjects 操作的权限。

授予子账号列出主账号所拥有的所有存储空间的权限:

  1. 创建一个列出所有存储空间的权限的策略。创建策略步骤请参见创建自定义策略
    本示例中创建名为 AllowGroupToSeeBucketListInConsole 的策略,内容如下:
    {
    "Version": "1",
    "Statement": [
     {
       "Effect": "Allow",
           "Action": [
             "oss:ListBuckets",
             "oss:GetBucketStat",
              "oss:GetBucketInfo",
             "oss:GetBucketAcl"
           ],
       "Resource": [
         "acs:oss:*:*:*"
       ]
     }
    ]
    }
    说明
    • RAM 策略为 JSON 格式。各字段定义如下:
      • Statement:对象数组,每个对象使用名/值对的集合来描述权限。
      • Effect:决定是允许还是拒绝特定的权限。
      • Action:指定访问权限的类型。在本策略中,oss:ListBuckets 是预定义的 OSS 操作,可返回经过身份验证的发送者所拥有的所有储存空间的列表。
    • 推荐您使用 RAM 策略编辑器快速生成 RAM 策略。更详细的 RAM 策略介绍请参见如何构建 RAM Policy
  2. AllowGroupToSeeBucketListInConsole 策略分配给 Staff 组。 详情请参见为 RAM 用户授权
  3. 测试权限。
    1. 打开 RAM 用户登录链接,并用 Anne 或 Leo 的账号登录到 RAM 控制台。
    2. 进入 OSS 控制台
      能看到存储空间列表,表明列举存储空间的权限是正常的。
    3. 单击 example-company 存储空间,然后单击文件管理选项卡。
      此时会弹出如下对话框,表明您没有相应的访问权限。
      教程示例:使用RAM Policy控制OSS的访问权限_权限控制_数据安全_开发指南_对象存储 OSS 阿里云技术文档 第6张

授予子账号列出存储空间根级内容的权限:

  1. 进入 RAM 控制台。
  2. 单击权限管理 > 权限策略管理
  3. 找到刚创建的AllowGroupToSeeBucketListInConsole策略,单击策略名称。
  4. 单击修改策略内容
    要列出存储空间内容,用户需要有 oss:ListObjects 权限。
    {
       "Version": "1",
       "Statement": [
         {
           "Effect": "Allow",
           "Action": [
             "oss:ListBuckets",
             "oss:GetBucketStat",
             "oss:GetBucketInfo",
             "oss:GetBucketAcl"
           ],
           "Resource": [
             "acs:oss:*:*:*"
           ],
           "Condition": {}
         },
         {
           "Effect": "Allow",
           "Action": [
             "oss:ListObjects"
           ],
           "Resource": [
             "acs:oss:*:*:example-company"
           ],
           "Condition": {
             "StringLike": {
               "oss:Prefix": [
                 ""
               ],
               "oss:Delimiter": [
                 "/"
               ]
             }
           }
         }
       ]
     }
    说明 您最多可对 RAM 策略进行五次修改。如果超过了五次,则需要删除该策略并创建一个新的策略,然后再次将新策略分配给 Staff 组。
  5. 测试更新的权限。
    使用子账号登录 OSS 控制台后,已经可以访问 example-company 存储空间,可以看到所有根目录内的 Object,此时单击任何文件均提示没有相应的权限。
    教程示例:使用RAM Policy控制OSS的访问权限_权限控制_数据安全_开发指南_对象存储 OSS 阿里云技术文档 第7张
上述步骤中,授予了 Staff 组指定权限,最终结果是授予 RAM 用户 Anne 和 Leo 以下权限:
  • 列出主账号所拥有的所有存储空间。
  • 查看 example-company 存储空间中的根级别项。
然而,他们可以进行的操作仍然有限。在以下部分中,我们将授予用户以下特定权限:
  • 允许 Anne 在 Development 文件夹中获取和放入对象。
  • 允许 Leo 在 Finance 文件夹中获取和放入对象。

对于用户特定的权限,您需要将策略分配给特定用户,而非分配给组。以下部分授予 Anne 在 Development 文件夹中操作的权限。您可以重复这些步骤,授予 Leo 在 Finance 文件夹中进行类似操作的权限。

步骤 5:授予 RAM 用户 Anne 特定权限

在此步骤中,我们向 Anne 授予额外的权限,使她可以看到 Development 文件夹的内容,并将对象放入文件夹中。

  1. 按照上面创建RAM策略的步骤创建一个名为AllowGroupToSeeBucketListInConsole的策略。
    策略内容:
    {
       "Version": "1",
       "Statement": [
         {
           "Effect": "Allow",
           "Action": [
             "oss:ListObjects"
           ],
           "Resource": [
             "acs:oss:*:*:example-company"
           ],
           "Condition": {
             "StringLike": {
               "oss:Prefix": [
                 "Development/*"
               ]
             }
           }
         },
         {
           "Effect": "Allow",
           "Action": [
             "oss:GetObject",
             "oss:PutObject",
             "oss:GetObjectAcl"
           ],
           "Resource": [
             "acs:oss:*:*:example-company/Development/*"
           ],
           "Condition": {}
         }
       ]
     }
  2. AllowGroupToSeeBucketListInConsole策略授予 RAM 用户 Anne。
  3. 使用 Anne 账号登录 OSS 控制台,测试 Anne 已经可以在 Development 文件夹中添加对象并下载对象。

步骤 6:授予 RAM 用户 Leo 特定权限

现在,您希望授予 Leo 访问 Marketing 文件夹的权限。请遵循之前用于向 Anne 授予权限的步骤,但应将 Development 文件夹替换为 Marketing 文件夹。有关详细过程,请参见步骤 5:授予 RAM 用户 Anne 特定权限。

步骤 7:确保 Private 文件夹安全

在本例中,您仅拥有两个用户。您在组级别授予两个用户所有所需的最小权限,只有当您真正需要单个用户级别上的权限时,才授予用户级别权限。此方法有助于最大限度地减少管理权限的工作量。随着用户数量的增加,我们希望确保不意外地授予用户对 Private 文件夹的权限。因此,我们需要添加一个显式拒绝访问 Private 文件夹的策略。显式拒绝策略会取代任何其他权限。若要确保 Private 文件夹保持私有,可以向组策略添加以下拒绝语句:

  • 添加以下语句以显式拒绝对 Private 文件夹(example-company/Private/*)的访问:
    {
        "Effect": "Deny",
        "Action": [
          "oss:*"
        ],
        "Resource": [
          "acs:oss:*:*:example-company/Private/*"
        ],
        "Condition": {}
      }
  • 当您请求指定访问 Private/prefix 时拒绝执行 ListObjects 操作的权限。在控制台中,如果 Anne 或 Leo 单击 Private 文件夹,则此策略将导致 OSS 返回错误响应。
    {
        "Effect": "Deny",
        "Action": [
          "oss:ListObjects"
        ],
        "Resource": [
          "acs:oss:*:*:*"
        ],
        "Condition": {
          "StringLike": {
            "oss:Prefix": [
              "Private/"
            ]
          }
        }
      }
  • 用包含前述拒绝语句的更新策略取代 Staff 组策略 AllowGroupToSeeBucketListInConsole。在应用更新策略后,组中的任何用户都不能访问您的存储空间中的 Private 文件夹。
    {
    "Version": "1",
    "Statement": [
     {
       "Effect": "Allow",
           "Action": [
             "oss:ListBuckets",
             "oss:GetBucketStat",
             "oss:GetBucketInfo",
             "oss:GetBucketAcl"
           ],
       "Resource": [
         "acs:oss:*:*:*"
       ],
       "Condition": {}
     },
     {
       "Effect": "Allow",
       "Action": [
         "oss:ListObjects"
       ],
       "Resource": [
         "acs:oss:*:*:example-company"
       ],
       "Condition": {
         "StringLike": {
           "oss:Prefix": [
              ""
            ],
           "oss:Delimiter": [
             "/"
           ]
         }
       }
     },
     {
       "Effect": "Deny",
       "Action": [
         "oss:*"
       ],
       "Resource": [
         "acs:oss:*:*:example-company/Private/*"
       ],
       "Condition": {}
     },
     {
       "Effect": "Deny",
       "Action": [
         "oss:ListObjects"
       ],
       "Resource": [
         "acs:oss:*:*:*"
       ],
       "Condition": {
         "StringLike": {
           "oss:Prefix": [
             "Private/"
           ]
         }
       }
     }
    ]
    }