This tutorial demonstrates how to use RAM policies to control access to OSS buckets and folders.

Background information

  • Operations related to RAM policies are complex. We recommend that you configure Bucket Policy to control access by using the graphical interface of the console.
  • If you choose to use RAM policies, we recommend that you use the official tool RAM Policy Editor to generate the required RAM policies.

Buckets and folders

Alibaba Cloud OSS uses a flat data model structure instead of a hierarchical one. All objects (files) are directly related to their corresponding buckets. Because of this, OSS does not have directories and subfolders like a hierarchical file system would. However, you can simulate a folder hierarchy in the OSS console to group, classify, and manage objects by folders, as shown in the following figure.

OSS is a distributed object storage service in which objects are identified as key-value pairs. You can retrieve the content of an object based on its object name. For example, a bucket named example-company has three folders: Development, Marketing, and Private. This bucket also has an object named oss-dg.pdf.

  • When you create the Development folder, the console creates an object with key Development/. Note that the key of a folder includes a forward slash (/) as the delimiter.
  • When you upload an object named ProjectA.docx to the Development folder, the console uploads the object and sets its key to Development/ProjectA.docx.

    In the key, Development is the prefix and the forward slash (/) is the delimiter. You can retrieve a list of all objects within a bucket that share a common prefix and delimiter. In the console, click the Development folder. The console lists the objects in the folder, as shown in the following figure.

    Note To list objects in the Development folder of the example-company bucket, the console sends a request to OSS to list objects that share the specified prefix Development and a forward slash (/) as the delimiter. The console responds with a folder list the same way as that in the file system. The preceding example shows that the example-company bucket has three objects with following keys: Development/Alibaba Cloud.pdf, Development/ProjectA.docx, and Development/ProjectB.docx.

The console uses object keys to determine a logical hierarchy. After a logical hierarchy is determined for an object, you can manage access to individual folders, as described in the following section.

Before going into this tutorial, you must understand the concept of root-level bucket content. Assume that the example-company bucket contains the following objects:

  • 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

These object keys determine a logical hierarchy withDevelopment, Marketing, and Private as root-level folders and oss-dg.pdf as a root-level object. When you click the bucket name in the OSS console, folders that share a common prefix and delimiter (Development/, Marketing/, and Private/) are displayed as root-level folders. The oss-dg.pdf object does not have a prefix, so it appears as a root-level item.

Requests and responses

Before granting permissions, you need to understand what request the console sends to OSS when you click a bucket name, what response OSS returns, and how the console parses the response.

When you click a bucket name, the console sends the GetBucket request to OSS. This request includes the following parameters:

  • prefix, with an empty string as its value.
  • delimiter, with a forward slash (/) as its value.

An example request is as follows:

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 returns a response that includes the ListBucketResult element:

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>

Because the key oss-dg.pdf does not contain a forward slash (/) delimiter, OSS returns the key in the <Contents/> element. All other keys in the example-company bucket contain forward slashes (/) as delimiters. OSS groups these keys and returns a <CommonPrefixes/> element for each of the prefix values Development/, Marketing/, and Private/. CommonPrefixes specifies a set of substrings containing object name prefixes. The substrings here must contain the entire prefix without the forward slash (/) delimiter.

The console parses this result and displays the root-level items as follows:

If you click the Development folder, the console sends the GetBucket request to OSS. This request includes the following parameters:

  • prefix, with Development/ as its value.
  • delimiter, with a forward slash (/) as its value.

An example request is as follows:

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=

In the response, OSS returns object keys with the specified prefix:

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>

The console parses this result and displays the object keys as follows:

Tutorial example

The tutorial example is as follows:

  • Create a bucket named example-company and add the following three folders: Development, Marketing, and Private.
  • Your account has two users, Anne and Leo. You want Anne to only have access to the Development folder and Leo to only have access to the Marketing folder. You want to keep the Private folder private. For this example, you can manage access by creating RAM user accounts for Anne and Leo, and granting each of them the necessary permissions.
  • RAM also allows you to create user groups and grant group-level permissions so that you can better manage and control permissions. For this tutorial, both Anne and Leo need some of the same permissions. To resolve this problem, you can create a group named Staff and add both Anne and Leo to the group. After granting permissions to the Staff group by assigning a group policy, you can add user-specific permissions by assigning policies to specific users.
Note The tutorial uses example-company as the bucket name, Anne and Leo as RAM users, and Staff as the group name. Because Alibaba Cloud OSS requires that bucket names be globally unique, you must replace the bucket name in the tutorial with your own unique bucket name.

Prepare for the tutorial

For this example, you use your Alibaba Cloud account to create RAM users. These users do not have any permissions when they are created. You grant them specific OSS operation permissions by performing the required steps. To test these permissions, you must log on to the console with the RAM user account of each user. You must log on to the console with your Alibaba Cloud account to grant permissions to a RAM user account and log on to the console with the RAM user account to test the permissions. You can perform the testing with one browser. You can also use two browsers to log on to the Alibaba Cloud console with your Alibaba Cloud account and with a RAM user account. This way, the testing is more efficient.

To log on to the Alibaba Cloud console with your Alibaba Cloud account, go to https://account.alibabacloud.com/login/login.htm. RAM users cannot log on using the same link. They must use the RAM user logon link. You can provide this logon link to RAM users under your Alibaba Cloud account.

Note For more information about RAM, see Log on with a RAM user account.

Step 1: Create a bucket

In this step, you can log on to the OSS console with your Alibaba Cloud account. You can create a bucket, add folders (Development, Marketing, and Private) to the bucket, and upload one or two sample documents to each folder in the console.

  1. Log on to the OSS console with an Alibaba Cloud account.
  2. Create a bucket named example-company. For more information, see Create a bucket.
  3. Upload an object to the bucket. For more information about how to upload an object, see Upload objects.
    For this example, assume that you upload the object oss-dg.pdf to the root directory of the bucket.
  4. Create three folders named Development, Marketing, and Private. For more information, see Create a folder.
  5. Upload one or two objects to each folder.
    For this example, assume that you upload objects with the following object keys to a bucket:
    • 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

Step 2: Create RAM users and a group

In this step, you must use the RAM console to add two RAM users, Anne and Leo, to your Alibaba Cloud account. You also must create a group named Staff, and add both users to the group.
Note Do not add any policies that grant permissions to these users in this step. You will grant permissions to the RAM users in subsequent steps.

For more information about how to create a RAM user, see Create a RAM user in the RAM Quick Start. Remember to create a logon password for each RAM user.

For more information about how to create a RAM user group, see RAM user groups in the RAM User Guide.

Step 3: Verify that RAM users do not have any permissions

If you have two browsers, you can use the other browser to log on to the console with one of the RAM user accounts.

  1. Open the RAM user logon page and log on to the RAM console with Anne's or Leo's account. For more information, see Log on to the RAM console as a RAM user.
  2. Go to the OSS console.
    There are no buckets in the console, which indicates that Anne does not have any permissions on the example-company bucket.

Step 4: Grant group-level permissions

You need to authorize Anne and Leo to perform the following tasks:

  • List all buckets owned by the Alibaba Cloud account

    To this end, Anne and Leo must have permissions for the oss:ListBuckets operation.

  • List root-level items, folders, and objects in the example-company bucket

    To this end, Anne and Leo must have permissions for the oss:ListObjects operation on the example-company bucket.

Grant a RAM user account the permission to list all buckets owned by the Alibaba Cloud account:

  1. Create a policy to grant users permissions to list all buckets. For more information about how to create a policy, see Create a custom policy.
    The content of the AllowGroupToSeeBucketListInConsole policy created in this example is as follows:
    {
    "Version": "1",
    "Statement": [
     {
       "Effect": "Allow",
           "Action": [
             "oss:ListBuckets",
             "oss:GetBucketStat",
              "oss:GetBucketInfo",
             "oss:GetBucketAcl"
           ],
       "Resource": [
         "acs:oss:*:*:*"
       ]
     }
    ]
    }
    Note
    • RAM policies are written in JSON format. The fields in the policy are described as follows:
      • Statement: This field is an array of objects where each object describes a permission by using a collection of key-value pairs.
      • Effect: This field value determines whether a specific operation is allowed or denied.
      • Action: This field specifies the type of operation. In the policy, oss:ListBuckets is a predefined OSS operation, which returns a list of all buckets owned by the authenticated sender.
    • We recommend that you use RAM Policy Editor to generate a RAM policy. For more information about RAM policies, see RAM policy.
  2. Assign the AllowGroupToSeeBucketListInConsole policy to the Staff group. For more information, see Authorize RAM users.
  3. Test the permissions.
    1. Open the RAM user logon page and log on to the RAM console with Anne's or Leo's account.
    2. Go to the OSS console.
      The console lists all buckets, indicating that the permission to list buckets is normal.
    3. Click the example-company bucket, and then click the Files tab.
      A message is displayed as shown in the following figure, indicating that you do not have the corresponding access permission.

Grant a RAM user account the permission to list the root-level content of a bucket:

  1. Log on to the RAM console.
  2. Choose Permissions > Policies.
  3. Find the created AllowGroupToSeeBucketListInConsole policy and click the policy name.
  4. On the page that appears, click the Policy Document tab.
    To list bucket content, you must have the permission to perform the oss:ListObjects operation.
    {
       "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": [
                 "/"
               ]
             }
           }
         }
       ]
     }
    Note You can modify a RAM policy up to five times. If this is reached, you must delete the policy and create a new one to assign to the Staff group.
  5. Test the updated policy.
    After logging on to the OSS console with a RAM user account, you can access the example-company bucket and see all the objects in the root directory. Clicking any file will result in a prompt indicating that you do not have the corresponding permission.
The result of the added group policy is to grant the RAM users Anne and Leo the following permissions:
  • List all buckets owned by the Alibaba Cloud account.
  • View the root-level items in the example-company bucket.
However, RAM users Anne and Leo still have limited permissions. In the following section, further user-specific permissions are granted to them:
  • Allow Anne to obtain and download objects in the Development folder.
  • Allow Leo to obtain and download objects in the Finance folder.

For user-specific permissions, you must assign a policy to the specific user, not to the entire group. In the following section, you grant Anne the permission to operate the Development folder. You can repeat these steps to grant similar permission to Leo to operate the Finance folder.

Step 5: Grant RAM user Anne specific permissions

In this step, you grant additional permissions to Anne so that Anne can view the content of the Development folder to obtain and download objects in the folder.

  1. Follow the preceding steps to create a RAM policy named AllowGroupToSeeBucketListInConsole.
    Policy content:
    {
       "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. Grant the AllowGroupToSeeBucketListInConsole policy to RAM user Anne.
  3. Log on to the OSS console with Anne's account and test whether Anne can upload to and download from the Development folder.

Step 6: Grant RAM user Leo specific permissions

Now you want to grant Leo the permission to access the Marketing folder. Follow the steps you used to grant permissions to Anne, but replace the Development folder with the Marketing folder. For detailed procedures, see Step 5: Grant RAM user Anne specific permissions.

Step 7: Secure the Private folder

In this example, you have only two RAM users. You have granted them all the minimum required permissions at the group level. Only grant user-specific permissions to RAM users when they need permissions at the individual user level. This approach helps minimize the effort for managing permissions. As the number of users increases, you need to make sure that you do not accidentally grant a user the permission to access the Private folder. Therefore, you must add a policy that explicitly denies access to the Private folder. An explicit denial overrides any other permissions. To make sure that the Private folder remains private, you can add the following deny statements to the group policy:

  • Add the following statement to explicitly deny any access to the Private folder (example-company/Private/*):
    {
        "Effect": "Deny",
        "Action": [
          "oss:*"
        ],
        "Resource": [
          "acs:oss:*:*:example-company/Private/*"
        ],
        "Condition": {}
      }
  • Add the following statement to deny users to perform the ListObjects operation when accessing the Private/prefix folder. If Anne or Leo clicks the Private folder in the console, OSS returns an error message.
    {
        "Effect": "Deny",
        "Action": [
          "oss:ListObjects"
        ],
        "Resource": [
          "acs:oss:*:*:*"
        ],
        "Condition": {
          "StringLike": {
            "oss:Prefix": [
              "Private/"
            ]
          }
        }
      }
  • Replace the policy AllowGroupToSeeBucketListInConsole for the Staff group with an updated policy that contains the preceding deny statements. After the updated policy is applied, none of the users in the group can access the Private folder in your bucket.
    {
    "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/"
           ]
         }
       }
     }
    ]
    }