Controlling access to individual objects in a bucket
This tutorial provides examples for how to use IAM access policies with IBM Cloud® Object Storage buckets to grant users access to individual objects within a bucket.
Before you begin
IBM Cloud Object Storage stores data in a flat structure where one bucket can contain billions of distinctly named objects. A folder hierarchy can be simulated by using identical prefixes in related object names. Also, an object name can be referred to as an object key. Here is an example:
Bucket Name: MyBucket
Objects in MyBucket:
User1/userDoc1.txt
User1/userDoc2.zip
Engineering/project1.git
Engineering/project2.git
Product/2023/roadmap1.ppt
Product/2024/roadmap2.ppt
Orgchart.pdf
In this example, the prefix User1
, Engineering
, and Product
can resemble root level folders. In addition, 2023
and 2024
can represent subdirectories. Use the delimiter “/” to represent
the file hierarchy. A delimiter can be any supported character. Orgchart.pdf
is considered a root-level object.
When running a list request on your bucket, you can specify a prefix for listing objects or list the content of the entire bucket. In addition, you can optionally pass a delimiter value in the listing request to simulate a folder structure in the response. For more information, see the examples of using prefix and delimiter condition statements.
Read or write operations typically target a specific object name which is also referred to as the object path.
Scenarios
The following examples show how to use IAM policies and conditions to grant access to individual objects in a bucket. We will continue to use the example bucket shown above. These examples show excerpts of the full access policy with respect to configuring the condition statements. For more information, see Assigning access to objects within a bucket using IAM access conditions.
Scenario 1: Grant Adam read access to all objects in the User1
folder only.
This will give Adam the ability to read all objects that start with the key name of User1/
. This will not give Adam the ability to list objects and he therefore cannot navigate the UI to access these objects. Adam can only retrieve
objects in the User1
folder through non-UI methods. Use a wildcard in the policy to give access to all possible objects that begin with User1/
. Failure to include a wildcard would give Adam only access to the object
named User1/
.
"control": {
"grant": {
"roles": [
{ "role_id":
"crn:v1:bluemix:public:cloud-object-storage::::serviceRole:ObjectReader"
}
]
}
},
"rule": {
"conditions": [
{
"key": "{{resource.attributes.path}}",
"operator": "stringMatch",
"value": "User1/*"
}
]
},
"pattern": "attribute-based-condition:resource:literal-and-wildcard"
Scenario 2: Grant Adam list and read access to all objects in the User1
folder.
This will give Adam the ability to read and list all objects that start with the key name of User1/
. Also, use a wildcard in the prefix
condition attribute. Failure to include the wildcard results in Adam only having
List access to the first level of objects or folders in the User1
folder. This policy will not permit Adam to list the bucket at the root level. If Adam uses the UI, he must search the bucket with the specific prefix of User1/
to see the objects for which he has access.
"control": {
"grant": {
"roles": [
{
"role_id":
"crn:v1:bluemix:public:cloud-object-storage::::serviceRole:ContentReader"
}
]
}
},
"rule": {
"operator": "or",
"conditions": [
{
"operator": "and",
"conditions": [
{
"key": "{{resource.attributes.prefix}}",
"operator": "stringMatch",
"value": "User1/*"
},
{
"key": "{{resource.attributes.delimiter}}",
"operator": "stringEquals",
"value": "/"
}
]
},
{
"key": "{{resource.attributes.path}}",
"operator": "stringMatch",
"value": "User1/*"
}
]
},
"pattern": "attribute-based-condition:resource:literal-and-wildcard
Scenario 3: Grant Samantha access to list, read, and replicate files in only the 2023
and 2024
subdirectories under the Product
folder.
These sets of actions will require Samantha to have at least the Writer
role. The Writer
role also contains some actions that do not specify a Path
or a Prefix
or Delimiter
such
as cloud-object-storage.bucket.put_replication
. To allow these actions, use the StringExists operator with the resource attributes based conditions.
Samantha will not have access to navigate the UI from the root folder. This situation is shown in Scenario 4.
"control": {
"grant": {
"roles": [
{
"role_id": "crn:v1:bluemix:public:iam::::serviceRole:Writer"
}
]
}
},
"rule": {
"operator": "or",
"conditions": [
{
"operator": "and",
"conditions": [
{
"key": "{{resource.attributes.prefix}}",
"operator": "stringMatchAnyOf",
"value": [
"Product/2023/*",
"Product/2024/*"
]
},
{
"key": "{{resource.attributes.delimiter}}",
"operator": "stringEquals",
"value": "/"
}
]
},
{
"key": "{{resource.attributes.path}}",
"operator": "stringMatchAnyOf",
"value": [
"Product/2023/*",
"Product/2024/*"
]
},
{
"operator": "and",
"conditions": [
{
"key": "{{resource.attributes.delimiter}}",
"operator": "stringExists",
"value": false
},
{
"key": "{{resource.attributes.prefix}}",
"operator": "stringExists",
"value": false
},
{
"key": "{{resource.attributes.path}}",
"operator": "stringExists",
"value": false
}
]
}
]
},
"pattern": "attribute-based-condition:resource:literal-and-wildcard"
Scenario 4: Grant Samantha access to navigate the UI to the files in the 2023
and 2024
folders in addition to list, read and replicate files in 2023
and 2024
.
To navigate the UI to MyBucket
, Samantha needs the platform role Viewer
. In addition, Samantha is given access to any directories above the target folder. In this case, Samantha needs access to list the root level
(defined by the prefix of the empty string) and the Product/
folder. This allows Samantha to see all root-level folders and objects.
"control": {
"grant": {
"roles": [
{
"role_id": "crn:v1:bluemix:public:iam::::serviceRole:Writer"
},
{
"role_id": "crn:v1:bluemix:public:iam::::role:Viewer"
}
]
}
},
"rule": {
"operator": "or",
"conditions": [
{
"operator": "and",
"conditions": [
{
"key": "{{resource.attributes.prefix}}",
"operator": "stringMatchAnyOf",
"value": [
"Product/2023/*",
"Product/2024/*"
]
},
{
"key": "{{resource.attributes.delimiter}}",
"operator": "stringEquals",
"value": "/"
}
]
},
{
"operator": "and",
"conditions": [
{
"key": "{{resource.attributes.prefix}}",
"operator": "stringEqualsAnyOf",
"value": [
"",
"Product/"
]
},
{
"key": "{{resource.attributes.delimiter}}",
"operator": "stringEquals",
"value": "/"
}
]
},
{
"key": "{{resource.attributes.path}}",
"operator": "stringMatchAnyOf",
"value": [
"Product/2023/*",
"Product/2024/*"
]
},
{
"operator": "and",
"conditions": [
{
"key": "{{resource.attributes.delimiter}}",
"operator": "stringExists",
"value": false
},
{
"key": "{{resource.attributes.prefix}}",
"operator": "stringExists",
"value": false
},
{
"key": "{{resource.attributes.path}}",
"operator": "stringExists",
"value": false
}
]
}
]
},
"pattern": "attribute-based-condition:resource:literal-and-wildcard"