For an alternative way to control access
to individual objects in your buckets, see Access Control Lists.
For more information about controlling access to Cloud Storage
resources, read Overview of Access Control.
Required roles
To get the permissions that you need to set and manage IAM
policies for a bucket, ask your administrator to grant you the Storage Admin
(roles/storage.admin) IAM role for the bucket.
This role contains the following permissions, which are required to set
and manage IAM policies for buckets:
storage.buckets.get
storage.buckets.getIamPolicy
storage.buckets.setIamPolicy
storage.buckets.update
storage.buckets.list
This permission is only required if you plan on using the
Google Cloud console to perform the tasks on this page.
You can also get these permissions with custom roles.
Add a principal to a bucket-level policy
For a list of roles associated with Cloud Storage, see
IAM Roles. For information on entities to which you grant
IAM roles, see Principal identifiers.
Console
In the Google Cloud console, go to the Cloud Storage Buckets page.
In the list of buckets, click the name of the bucket for which you want
to grant a principal a role.
Select the Permissions tab near the top of the page.
Click the add_boxGrant access button.
The Add principals dialog appears.
In the New principals field, enter one or more identities
that need access to your bucket.
Select a role (or roles) from the Select a role drop-down menu.
The roles you select appear in the pane with a short description of
the permissions they grant.
Click Save.
To learn how to get detailed error information about failed Cloud Storage
operations in the Google Cloud console, see
Troubleshooting.
BUCKET_NAME is the name of the bucket you are
granting the principal access to. For example, my-bucket.
PRINCIPAL_IDENTIFIER identifies who you are
granting bucket access to. For example, user:jeffersonloveshiking@gmail.com. For
a list of principal identifier formats, see Principal identifiers.
IAM_ROLE is the IAM role
you are granting to the principal. For example, roles/storage.objectViewer.
namespacegcs=::google::cloud::storage;using::google::cloud::StatusOr;[](gcs::Clientclient,std::stringconst&bucket_name,std::stringconst&role,std::stringconst&member){autopolicy=client.GetNativeBucketIamPolicy(bucket_name,gcs::RequestedPolicyVersion(3));if(!policy)throwstd::move(policy).status();policy->set_version(3);for(auto&binding:policy->bindings()){if(binding.role()!=role||binding.has_condition()){continue;}auto&members=binding.members();if(std::find(members.begin(),members.end(),member)==members.end()){members.emplace_back(member);}}autoupdated=client.SetNativeBucketIamPolicy(bucket_name,*policy);if(!updated)throwstd::move(updated).status();std::cout << "Updated IAM policy bucket " << bucket_name << ". The new policy is " << *updated << "\n";}
usingGoogle.Apis.Storage.v1.Data;usingGoogle.Cloud.Storage.V1;usingSystem;usingSystem.Collections.Generic;publicclassAddBucketIamMemberSample{publicPolicyAddBucketIamMember(stringbucketName="your-unique-bucket-name",stringrole="roles/storage.objectViewer",stringmember="serviceAccount:dev@iam.gserviceaccount.com"){varstorage=StorageClient.Create();varpolicy=storage.GetBucketIamPolicy(bucketName,newGetBucketIamPolicyOptions{RequestedPolicyVersion=3});// Set the policy schema version. For more information, please refer to https://cloud.google.com/iam/docs/policies#versions.policy.Version=3;Policy.BindingsDatabindingToAdd=newPolicy.BindingsData{Role=role,Members=newList<string>{member}};policy.Bindings.Add(bindingToAdd);varbucketIamPolicy=storage.SetBucketIamPolicy(bucketName,policy);Console.WriteLine($"Added {member} with role {role} "+$"to {bucketName}");returnbucketIamPolicy;}}
import("context""fmt""io""time""cloud.google.com/go/iam""cloud.google.com/go/storage")// addBucketIAMMember adds the bucket IAM member to permission role.funcaddBucketIAMMember(wio.Writer,bucketNamestring)error{// bucketName := "bucket-name"ctx:=context.Background()client,err:=storage.NewClient(ctx)iferr!=nil{returnfmt.Errorf("storage.NewClient: %w",err)}deferclient.Close()ctx,cancel:=context.WithTimeout(ctx,time.Second*10)defercancel()bucket:=client.Bucket(bucketName)policy,err:=bucket.IAM().Policy(ctx)iferr!=nil{returnfmt.Errorf("Bucket(%q).IAM().Policy: %w",bucketName,err)}// Other valid prefixes are "serviceAccount:", "user:"// See the documentation for more values.// https://cloud.google.com/storage/docs/access-control/iamidentity:="group:cloud-logs@google.com"varroleiam.RoleName="roles/storage.objectViewer"policy.Add(identity,role)iferr:=bucket.IAM().SetPolicy(ctx,policy);err!=nil{returnfmt.Errorf("Bucket(%q).IAM().SetPolicy: %w",bucketName,err)}// NOTE: It may be necessary to retry this operation if IAM policies are// being modified concurrently. SetPolicy will return an error if the policy// was modified since it was retrieved.fmt.Fprintf(w,"Added %v with role %v to %v\n",identity,role,bucketName)returnnil}
importcom.google.cloud.Binding;importcom.google.cloud.Policy;importcom.google.cloud.storage.Storage;importcom.google.cloud.storage.StorageOptions;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.List;publicclassAddBucketIamMember{/** Example of adding a member to the Bucket-level IAM */publicstaticvoidaddBucketIamMember(StringprojectId,StringbucketName){// The ID of your GCP project// String projectId = "your-project-id";// The ID of your GCS bucket// String bucketName = "your-unique-bucket-name";// For more information please read:// https://cloud.google.com/storage/docs/access-control/iamStoragestorage=StorageOptions.newBuilder().setProjectId(projectId).build().getService();PolicyoriginalPolicy=storage.getIamPolicy(bucketName,Storage.BucketSourceOption.requestedPolicyVersion(3));Stringrole="roles/storage.objectViewer";Stringmember="group:example@google.com";// getBindingsList() returns an ImmutableList and copying over to an ArrayList so it's mutable.List<Binding>bindings=newArrayList(originalPolicy.getBindingsList());// Create a new binding using role and memberBinding.BuildernewMemberBindingBuilder=Binding.newBuilder();newMemberBindingBuilder.setRole(role).setMembers(Arrays.asList(member));bindings.add(newMemberBindingBuilder.build());// Update policy to add memberPolicy.BuilderupdatedPolicyBuilder=originalPolicy.toBuilder();updatedPolicyBuilder.setBindings(bindings).setVersion(3);PolicyupdatedPolicy=storage.setIamPolicy(bucketName,updatedPolicyBuilder.build());System.out.printf("Added %s with role %s to %s\n",member,role,bucketName);}}
/** * TODO(developer): Uncomment the following lines before running the sample. */// The ID of your GCS bucket// const bucketName = 'your-unique-bucket-name';// The role to grant// const roleName = 'roles/storage.objectViewer';// The members to grant the new role to// const members = [// 'user:jdoe@example.com',// 'group:admins@example.com',// ];// Imports the Google Cloud client libraryconst{Storage}=require('@google-cloud/storage');// Creates a clientconststorage=newStorage();asyncfunctionaddBucketIamMember(){// Get a reference to a Google Cloud Storage bucketconstbucket=storage.bucket(bucketName);// For more information please read:// https://cloud.google.com/storage/docs/access-control/iamconst[policy]=awaitbucket.iam.getPolicy({requestedPolicyVersion:3});// Adds the new roles to the bucket's IAM policypolicy.bindings.push({role:roleName,members:members,});// Updates the bucket's IAM policyawaitbucket.iam.setPolicy(policy);console.log(`Added the following member(s) with role ${roleName} to ${bucketName}:`);members.forEach(member=>{console.log(` ${member}`);});}addBucketIamMember().catch(console.error);
use Google\Cloud\Storage\StorageClient;/** * Adds a new member / role IAM pair to a given Cloud Storage bucket. * * @param string $bucketName The name of your Cloud Storage bucket. * (e.g. 'my-bucket') * @param string $role The role to which the given member should be added. * (e.g. 'roles/storage.objectViewer') * @param string[] $members The member(s) to be added to the role. * (e.g. ['group:example@google.com']) */function add_bucket_iam_member(string $bucketName, string $role, array $members): void{ $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); $policy = $bucket->iam()->policy(['requestedPolicyVersion' => 3]); $policy['version'] = 3; $policy['bindings'][] = [ 'role' => $role, 'members' => $members ]; $bucket->iam()->setPolicy($policy); printf('Added the following member(s) to role %s for bucket %s' . PHP_EOL, $role, $bucketName); foreach ($members as $member) { printf(' %s' . PHP_EOL, $member); }}
fromgoogle.cloudimportstoragedefadd_bucket_iam_member(bucket_name,role,member):"""Add a new member to an IAM Policy"""# bucket_name = "your-bucket-name"# role = "IAM role, e.g., roles/storage.objectViewer"# member = "IAM identity, e.g., user: name@example.com"storage_client=storage.Client()bucket=storage_client.bucket(bucket_name)policy=bucket.get_iam_policy(requested_policy_version=3)policy.bindings.append({"role":role,"members":{member}})bucket.set_iam_policy(policy)print(f"Added {member} with role {role} to {bucket_name}.")
defadd_bucket_iam_memberbucket_name:# The ID of your GCS bucket# bucket_name = "your-unique-bucket-name"require"google/cloud/storage"storage=Google::Cloud::Storage.newbucket=storage.bucketbucket_namerole="roles/storage.objectViewer"member="group:example@google.com"bucket.policyrequested_policy_version:3do|policy|policy.bindings.insertrole:role,members:[member]endputs"Added #{member} with role #{role} to #{bucket_name}"end
Rust
usegoogle_cloud_iam_v1::model::Binding;usegoogle_cloud_storage::client::StorageControl;pubasyncfnsample(client:&StorageControl,bucket_id:&str,role:&str,member:&str,)->anyhow::Result<()>{letmutpolicy=client.get_iam_policy().set_resource(format!("projects/_/buckets/{bucket_id}")).send().await?;policy.bindings.push(Binding::new().set_role(role).set_members([member]));letupdated_policy=client.set_iam_policy().set_resource(format!("projects/_/buckets/{bucket_id}")).set_policy(policy).send().await?;println!("Successfully added binding for {member} to bucket {bucket_id} policy: {updated_policy:?}");Ok(())}
PRINCIPAL_IDENTIFIER identifies who you are
granting bucket access to. For example, user:jeffersonloveshiking@gmail.com. For a
list of principal identifier formats, see Principal identifiers.
namespacegcs=::google::cloud::storage;using::google::cloud::StatusOr;[](gcs::Clientclient,std::stringconst&bucket_name){autopolicy=client.GetNativeBucketIamPolicy(bucket_name,gcs::RequestedPolicyVersion(3));if(!policy)throwstd::move(policy).status();std::cout << "The IAM policy for bucket " << bucket_name << " is " << *policy << "\n";}
importcom.google.cloud.Binding;importcom.google.cloud.Policy;importcom.google.cloud.storage.Storage;importcom.google.cloud.storage.StorageOptions;publicclassListBucketIamMembers{publicstaticvoidlistBucketIamMembers(StringprojectId,StringbucketName){// The ID of your GCP project// String projectId = "your-project-id";// The ID of your GCS bucket// String bucketName = "your-unique-bucket-name";// For more information please read:// https://cloud.google.com/storage/docs/access-control/iamStoragestorage=StorageOptions.newBuilder().setProjectId(projectId).build().getService();Policypolicy=storage.getIamPolicy(bucketName,Storage.BucketSourceOption.requestedPolicyVersion(3));// Print binding informationfor(Bindingbinding:policy.getBindingsList()){System.out.printf("Role: %s Members: %s\n",binding.getRole(),binding.getMembers());// Print condition if one is setbooleanbindingIsConditional=binding.getCondition()!=null;if(bindingIsConditional){System.out.printf("Condition Title: %s\n",binding.getCondition().getTitle());System.out.printf("Condition Description: %s\n",binding.getCondition().getDescription());System.out.printf("Condition Expression: %s\n",binding.getCondition().getExpression());}}}}
/** * TODO(developer): Uncomment the following lines before running the sample. */// The ID of your GCS bucket// const bucketName = 'your-unique-bucket-name';// Imports the Google Cloud client libraryconst{Storage}=require('@google-cloud/storage');// Creates a clientconststorage=newStorage();asyncfunctionviewBucketIamMembers(){// For more information please read:// https://cloud.google.com/storage/docs/access-control/iamconstresults=awaitstorage.bucket(bucketName).iam.getPolicy({requestedPolicyVersion:3});constbindings=results[0].bindings;console.log(`Bindings for bucket ${bucketName}:`);for(constbindingofbindings){console.log(` Role: ${binding.role}`);console.log(' Members:');constmembers=binding.members;for(constmemberofmembers){console.log(` ${member}`);}constcondition=binding.condition;if(condition){console.log(' Condition:');console.log(` Title: ${condition.title}`);console.log(` Description: ${condition.description}`);console.log(` Expression: ${condition.expression}`);}}}viewBucketIamMembers().catch(console.error);
fromgoogle.cloudimportstoragedefview_bucket_iam_members(bucket_name):"""View IAM Policy for a bucket"""# bucket_name = "your-bucket-name"storage_client=storage.Client()bucket=storage_client.bucket(bucket_name)policy=bucket.get_iam_policy(requested_policy_version=3)forbindinginpolicy.bindings:print(f"Role: {binding['role']}, Members: {binding['members']}")
defview_bucket_iam_membersbucket_name:# The ID of your GCS bucket# bucket_name = "your-unique-bucket-name"require"google/cloud/storage"storage=Google::Cloud::Storage.newbucket=storage.bucketbucket_namepolicy=bucket.policyrequested_policy_version:3policy.bindings.eachdo|binding|puts"Role: #{binding.role}"puts"Members: #{binding.members}"# if a conditional binding exists print the condition.ifbinding.conditionputs"Condition Title: #{binding.condition.title}"puts"Condition Description: #{binding.condition.description}"puts"Condition Expression: #{binding.condition.expression}"endendend
Rust
usegoogle_cloud_storage::client::StorageControl;pubasyncfnsample(client:&StorageControl,bucket_id:&str)->anyhow::Result<()>{letpolicy=client.get_iam_policy().set_resource(format!("projects/_/buckets/{bucket_id}")).send().await?;println!("IAM policy for bucket {}: {:?}",bucket_id,policy);Ok(())}
BUCKET_NAME is the name of the bucket you are
revoking access to. For example, my-bucket.
PRINCIPAL_IDENTIFIER identifies who you are
revoking access from. For example, user:jeffersonloveshiking@gmail.com. For a
list of principal identifier formats, see Principal identifiers.
IAM_ROLE is the IAM role
you are revoking. For example, roles/storage.objectViewer.
usingGoogle.Cloud.Storage.V1;usingSystem;usingSystem.Linq;publicclassRemoveBucketIamMemberSample{publicvoidRemoveBucketIamMember(stringbucketName="your-unique-bucket-name",stringrole="roles/storage.objectViewer",stringmember="serviceAccount:dev@iam.gserviceaccount.com"){varstorage=StorageClient.Create();varpolicy=storage.GetBucketIamPolicy(bucketName,newGetBucketIamPolicyOptions{RequestedPolicyVersion=3});// Set the policy schema version. For more information, please refer to https://cloud.google.com/iam/docs/policies#versions.policy.Version=3;foreach(varbindinginpolicy.Bindings.Where(c=>c.Role==role).ToList()){// Remove the role/member combo from the IAM policy.binding.Members=binding.Members.Where(m=>m!=member).ToList();// Remove role if it contains no members.if(binding.Members.Count==0){policy.Bindings.Remove(binding);}}// Set the modified IAM policy to be the current IAM policy.storage.SetBucketIamPolicy(bucketName,policy);Console.WriteLine($"Removed {member} with role {role} from {bucketName}");}}
import("context""fmt""io""time""cloud.google.com/go/iam""cloud.google.com/go/storage")// removeBucketIAMMember removes the bucket IAM member.funcremoveBucketIAMMember(wio.Writer,bucketNamestring)error{// bucketName := "bucket-name"ctx:=context.Background()client,err:=storage.NewClient(ctx)iferr!=nil{returnfmt.Errorf("storage.NewClient: %w",err)}deferclient.Close()ctx,cancel:=context.WithTimeout(ctx,time.Second*10)defercancel()bucket:=client.Bucket(bucketName)policy,err:=bucket.IAM().Policy(ctx)iferr!=nil{returnfmt.Errorf("Bucket(%q).IAM().Policy: %w",bucketName,err)}// Other valid prefixes are "serviceAccount:", "user:"// See the documentation for more values.// https://cloud.google.com/storage/docs/access-control/iam// member string, role iam.RoleNameidentity:="group:cloud-logs@google.com"varroleiam.RoleName="roles/storage.objectViewer"policy.Remove(identity,role)iferr:=bucket.IAM().SetPolicy(ctx,policy);err!=nil{returnfmt.Errorf("Bucket(%q).IAM().SetPolicy: %w",bucketName,err)}// NOTE: It may be necessary to retry this operation if IAM policies are// being modified concurrently. SetPolicy will return an error if the policy// was modified since it was retrieved.fmt.Fprintf(w,"Removed %v with role %v from %v\n",identity,role,bucketName)returnnil}
importcom.google.cloud.Binding;importcom.google.cloud.Policy;importcom.google.cloud.storage.Storage;importcom.google.cloud.storage.StorageOptions;importjava.util.ArrayList;importjava.util.List;publicclassRemoveBucketIamMember{publicstaticvoidremoveBucketIamMember(StringprojectId,StringbucketName){// The ID of your GCP project// String projectId = "your-project-id";// The ID of your GCS bucket// String bucketName = "your-unique-bucket-name";// For more information please read:// https://cloud.google.com/storage/docs/access-control/iamStoragestorage=StorageOptions.newBuilder().setProjectId(projectId).build().getService();PolicyoriginalPolicy=storage.getIamPolicy(bucketName,Storage.BucketSourceOption.requestedPolicyVersion(3));Stringrole="roles/storage.objectViewer";Stringmember="group:example@google.com";// getBindingsList() returns an ImmutableList and copying over to an ArrayList so it's mutable.List<Binding>bindings=newArrayList(originalPolicy.getBindingsList());// Remove role-member binding without a condition.for(intindex=0;index < bindings.size();index++){Bindingbinding=bindings.get(index);booleanfoundRole=binding.getRole().equals(role);booleanfoundMember=binding.getMembers().contains(member);booleanbindingIsNotConditional=binding.getCondition()==null;if(foundRole && foundMember && bindingIsNotConditional){bindings.set(index,binding.toBuilder().removeMembers(member).build());break;}}// Update policy to remove memberPolicy.BuilderupdatedPolicyBuilder=originalPolicy.toBuilder();updatedPolicyBuilder.setBindings(bindings).setVersion(3);PolicyupdatedPolicy=storage.setIamPolicy(bucketName,updatedPolicyBuilder.build());System.out.printf("Removed %s with role %s from %s\n",member,role,bucketName);}}
/** * TODO(developer): Uncomment the following lines before running the sample. */// The ID of your GCS bucket// const bucketName = 'your-unique-bucket-name';// The role to revoke// const roleName = 'roles/storage.objectViewer';// The members to revoke the roles from// const members = [// 'user:jdoe@example.com',// 'group:admins@example.com',// ];// Imports the Google Cloud client libraryconst{Storage}=require('@google-cloud/storage');// Creates a clientconststorage=newStorage();asyncfunctionremoveBucketIamMember(){// Get a reference to a Google Cloud Storage bucketconstbucket=storage.bucket(bucketName);// For more information please read:// https://cloud.google.com/storage/docs/access-control/iamconst[policy]=awaitbucket.iam.getPolicy({requestedPolicyVersion:3});// Finds and updates the appropriate role-member group, without a condition.constindex=policy.bindings.findIndex(binding=>binding.role===roleName && !binding.condition);constrole=policy.bindings[index];if(role){role.members=role.members.filter(member=>members.indexOf(member)===-1);// Updates the policy object with the new (or empty) role-member groupif(role.members.length===0){policy.bindings.splice(index,1);}else{policy.bindings.index=role;}// Updates the bucket's IAM policyawaitbucket.iam.setPolicy(policy);}else{// No matching role-member group(s) were foundthrownewError('No matching role-member group(s) found.');}console.log(`Removed the following member(s) with role ${roleName} from ${bucketName}:`);members.forEach(member=>{console.log(` ${member}`);});}removeBucketIamMember().catch(console.error);
use Google\Cloud\Storage\StorageClient;/** * Removes a member / role IAM pair from a given Cloud Storage bucket. * * @param string $bucketName The name of your Cloud Storage bucket. * (e.g. 'my-bucket') * @param string $role The role from which the specified member should be removed. * (e.g. 'roles/storage.objectViewer') * @param string $member The member to be removed from the specified role. * (e.g. 'group:example@google.com') */function remove_bucket_iam_member(string $bucketName, string $role, string $member): void{ $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); $iam = $bucket->iam(); $policy = $iam->policy(['requestedPolicyVersion' => 3]); $policy['version'] = 3; foreach ($policy['bindings'] as $i => $binding) { // This example only removes member from bindings without a condition. if ($binding['role'] == $role && !isset($binding['condition'])) { $key = array_search($member, $binding['members']); if ($key !== false) { unset($binding['members'][$key]); // If the last member is removed from the binding, clean up the // binding. if (count($binding['members']) == 0) { unset($policy['bindings'][$i]); // Ensure array keys are sequential, otherwise JSON encodes // the array as an object, which fails when calling the API. $policy['bindings'] = array_values($policy['bindings']); } else { // Ensure array keys are sequential, otherwise JSON encodes // the array as an object, which fails when calling the API. $binding['members'] = array_values($binding['members']); $policy['bindings'][$i] = $binding; } $iam->setPolicy($policy); printf('User %s removed from role %s for bucket %s' . PHP_EOL, $member, $role, $bucketName); return; } } } throw new \RuntimeException('No matching role-member group(s) found.');}
fromgoogle.cloudimportstoragedefremove_bucket_iam_member(bucket_name,role,member):"""Remove member from bucket IAM Policy"""# bucket_name = "your-bucket-name"# role = "IAM role, e.g. roles/storage.objectViewer"# member = "IAM identity, e.g. user: name@example.com"storage_client=storage.Client()bucket=storage_client.bucket(bucket_name)policy=bucket.get_iam_policy(requested_policy_version=3)forbindinginpolicy.bindings:print(binding)ifbinding["role"]==roleandbinding.get("condition")isNone:binding["members"].discard(member)bucket.set_iam_policy(policy)print(f"Removed {member} with role {role} from {bucket_name}.")
defremove_bucket_iam_memberbucket_name:# The ID of your GCS bucket# bucket_name = "your-unique-bucket-name"# For more information please read: https://cloud.google.com/storage/docs/access-control/iamrequire"google/cloud/storage"storage=Google::Cloud::Storage.newbucket=storage.bucketbucket_namerole="roles/storage.objectViewer"member="group:example@google.com"bucket.policyrequested_policy_version:3do|policy|policy.bindings.eachdo|binding|ifbinding.role==role && binding.condition.nil?binding.members.deletememberendendendputs"Removed #{member} with role #{role} from #{bucket_name}"end
Rust
usegoogle_cloud_storage::client::StorageControl;pubasyncfnsample(client:&StorageControl,bucket_id:&str,role:&str,member:&str,)->anyhow::Result<()>{letmutpolicy=client.get_iam_policy().set_resource(format!("projects/_/buckets/{bucket_id}")).send().await?;ifletSome(binding)=policy.bindings.iter_mut().find(|b|b.role==role){binding.members.retain(|m|m!=member);}policy.bindings.retain(|b|!b.members.is_empty());letupdated_policy=client.set_iam_policy().set_resource(format!("projects/_/buckets/{bucket_id}")).set_policy(policy).send().await?;println!("Successfully removed {member} with role {role} from bucket {bucket_id}");println!("The updated policy is: {:?}",updated_policy);Ok(())}
JSON_FILE_NAME is the path for the file
that you created in Step 3.
BUCKET_NAME is the name of the bucket from
which you want to remove access. For example, my-bucket.
Use IAM Conditions on buckets
The following sections show you how to add and remove
IAM Conditions on your buckets. To view the
IAM Conditions for your bucket, see
Viewing the IAM policy for a bucket. For more information
about using IAM Conditions with Cloud Storage, see
Conditions.
In the list of buckets, click the name of the bucket that you want to add
a new condition for.
In the Bucket details page, click the Permissions tab.
The IAM policy that applies to the bucket appears in
the Permissions section.
Click + Grant access.
For New principals, fill out the principals to which you want to grant
access to your bucket.
For each role to which you want to apply a condition:
Select a Role to grant the principals.
Click Add condition to open the Edit condition form.
Fill out the Title of the condition. The Description field is
optional.
Use the Condition builder to build your condition visually, or use the
Condition editor tab to enter the CEL expression.
Click Save to return to the Add principal form. To add
multiple roles, click Add another role.
Click Save.
To learn how to get detailed error information about failed Cloud Storage
operations in the Google Cloud console, see
Troubleshooting.
Command line
Create a JSON or YAML file that defines the condition, including the
title of the condition, the attribute-based logic
expression for the condition, and, optionally, a description for
the condition.
BUCKET_NAME is the name of the bucket you are
granting the principal access to. For example, my-bucket.
PRINCIPAL_IDENTIFIER identifies who the
condition applies to. For example, user:jeffersonloveshiking@gmail.com. For a
list of principal identifier formats, see Principal identifiers.
IAM_ROLE is the IAM role
you are granting to the principal. For example, roles/storage.objectViewer.
CONDITION_FILE is the file you created in the
previous step.
Alternatively, you can include the condition directly in the command
with the --condition flag instead of the --condition-from-file flag.
usingGoogle.Apis.Storage.v1.Data;usingGoogle.Cloud.Storage.V1;usingSystem;usingSystem.Collections.Generic;publicclassAddBucketConditionalIamBindingSample{/// <summary>/// Adds a conditional Iam policy to a bucket./// </summary>/// <param name="bucketName">The name of the bucket.</param>/// <param name="role">The role that members may assume.</param>/// <param name="member">The identifier of the member who may assume the provided role.</param>/// <param name="title">Title for the expression.</param>/// <param name="description">Description of the expression.</param>/// <param name="expression">Describes the conditions that need to be met for the policy to be applied./// It's represented as a string using Common Expression Language syntax.</param>publicPolicyAddBucketConditionalIamBinding(stringbucketName="your-unique-bucket-name",stringrole="roles/storage.objectViewer",stringmember="serviceAccount:dev@iam.gserviceaccount.com",stringtitle="title",stringdescription="description",stringexpression="resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")"){varstorage=StorageClient.Create();varpolicy=storage.GetBucketIamPolicy(bucketName,newGetBucketIamPolicyOptions{RequestedPolicyVersion=3});// Set the policy schema version. For more information, please refer to https://cloud.google.com/iam/docs/policies#versions.policy.Version=3;Policy.BindingsDatabindingToAdd=newPolicy.BindingsData{Role=role,Members=newList<string>{member},Condition=newExpr{Title=title,Description=description,Expression=expression}};policy.Bindings.Add(bindingToAdd);varbucketIamPolicy=storage.SetBucketIamPolicy(bucketName,policy);Console.WriteLine($"Added {member} with role {role} "+$"to {bucketName}");returnbucketIamPolicy;}}
import("context""fmt""io""time""cloud.google.com/go/iam/apiv1/iampb""cloud.google.com/go/storage""google.golang.org/genproto/googleapis/type/expr")// addBucketConditionalIAMBinding adds bucket conditional IAM binding.funcaddBucketConditionalIAMBinding(wio.Writer,bucketName,role,member,title,description,expressionstring)error{// bucketName := "bucket-name"// role := "bucket-level IAM role"// member := "bucket-level IAM member"// title := "condition title"// description := "condition description"// expression := "condition expression"ctx:=context.Background()client,err:=storage.NewClient(ctx)iferr!=nil{returnfmt.Errorf("storage.NewClient: %w",err)}deferclient.Close()ctx,cancel:=context.WithTimeout(ctx,time.Second*10)defercancel()bucket:=client.Bucket(bucketName)policy,err:=bucket.IAM().V3().Policy(ctx)iferr!=nil{returnfmt.Errorf("Bucket(%q).IAM().V3().Policy: %w",bucketName,err)}policy.Bindings=append(policy.Bindings,&iampb.Binding{Role:role,Members:[]string{member},Condition:&expr.Expr{Title:title,Description:description,Expression:expression,},})iferr:=bucket.IAM().V3().SetPolicy(ctx,policy);err!=nil{returnfmt.Errorf("Bucket(%q).IAM().V3().SetPolicy: %w",bucketName,err)}// NOTE: It may be necessary to retry this operation if IAM policies are// being modified concurrently. SetPolicy will return an error if the policy// was modified since it was retrieved.fmt.Fprintf(w,"Added %v with role %v to %v with condition %v %v %v\n",member,role,bucketName,title,description,expression)returnnil}
importcom.google.cloud.Binding;importcom.google.cloud.Condition;importcom.google.cloud.Policy;importcom.google.cloud.storage.Storage;importcom.google.cloud.storage.StorageOptions;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.List;publicclassAddBucketIamConditionalBinding{/** Example of adding a conditional binding to the Bucket-level IAM */publicstaticvoidaddBucketIamConditionalBinding(StringprojectId,StringbucketName){// The ID of your GCP project// String projectId = "your-project-id";// The ID of your GCS bucket// String bucketName = "your-unique-bucket-name";// For more information please read:// https://cloud.google.com/storage/docs/access-control/iamStoragestorage=StorageOptions.newBuilder().setProjectId(projectId).build().getService();PolicyoriginalPolicy=storage.getIamPolicy(bucketName,Storage.BucketSourceOption.requestedPolicyVersion(3));Stringrole="roles/storage.objectViewer";Stringmember="group:example@google.com";// Create a conditionStringconditionTitle="Title";StringconditionDescription="Description";StringconditionExpression="resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")";Condition.BuilderconditionBuilder=Condition.newBuilder();conditionBuilder.setTitle(conditionTitle);conditionBuilder.setDescription(conditionDescription);conditionBuilder.setExpression(conditionExpression);// getBindingsList() returns an ImmutableList, we copy over to an ArrayList so it's mutableList<Binding>bindings=newArrayList(originalPolicy.getBindingsList());// Add condition to a bindingBinding.BuildernewBindingBuilder=Binding.newBuilder().setRole(role).setMembers(Arrays.asList(member)).setCondition(conditionBuilder.build());bindings.add(newBindingBuilder.build());// Update policy with new conditional bindingPolicy.BuilderupdatedPolicyBuilder=originalPolicy.toBuilder();updatedPolicyBuilder.setBindings(bindings).setVersion(3);storage.setIamPolicy(bucketName,updatedPolicyBuilder.build());System.out.printf("Added %s with role %s to %s with condition %s %s %s\n",member,role,bucketName,conditionTitle,conditionDescription,conditionExpression);}}
/** * TODO(developer): Uncomment the following lines before running the sample. */// The ID of your GCS bucket// const bucketName = 'your-unique-bucket-name';// The role to grant// const roleName = 'roles/storage.objectViewer';// The members to grant the new role to// const members = [// 'user:jdoe@example.com',// 'group:admins@example.com',// ];// Create a condition// const title = 'Title';// const description = 'Description';// const expression = 'resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")';// Imports the Google Cloud client libraryconst{Storage}=require('@google-cloud/storage');// Creates a clientconststorage=newStorage();asyncfunctionaddBucketConditionalBinding(){// Get a reference to a Google Cloud Storage bucketconstbucket=storage.bucket(bucketName);// Gets and updates the bucket's IAM policyconst[policy]=awaitbucket.iam.getPolicy({requestedPolicyVersion:3});// Set the policy's version to 3 to use condition in bindings.policy.version=3;// Adds the new roles to the bucket's IAM policypolicy.bindings.push({role:roleName,members:members,condition:{title:title,description:description,expression:expression,},});// Updates the bucket's IAM policyawaitbucket.iam.setPolicy(policy);console.log(`Added the following member(s) with role ${roleName} to ${bucketName}:`);members.forEach(member=>{console.log(` ${member}`);});console.log('with condition:');console.log(` Title: ${title}`);console.log(` Description: ${description}`);console.log(` Expression: ${expression}`);}addBucketConditionalBinding().catch(console.error);
use Google\Cloud\Storage\StorageClient;/** * Adds a conditional IAM binding to a bucket's IAM policy. * * @param string $bucketName The name of your Cloud Storage bucket. * (e.g. 'my-bucket') * @param string $role The role that will be given to members in this binding. * (e.g. 'roles/storage.objectViewer') * @param string[] $members The member(s) associated with this binding. * (e.g. ['group:example@google.com']) * @param string $title The title of the condition. (e.g. 'Title') * @param string $description The description of the condition. * (e.g. 'Condition Description') * @param string $expression The condition specified in CEL expression language. * (e.g. 'resource.name.startsWith("projects/_/buckets/bucket-name/objects/prefix-a-")') * * To see how to express a condition in CEL, visit: * @see https://cloud.google.com/storage/docs/access-control/iam#conditions. */function add_bucket_conditional_iam_binding(string $bucketName, string $role, array $members, string $title, string $description, string $expression): void{ $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); $policy = $bucket->iam()->policy(['requestedPolicyVersion' => 3]); $policy['version'] = 3; $policy['bindings'][] = [ 'role' => $role, 'members' => $members, 'condition' => [ 'title' => $title, 'description' => $description, 'expression' => $expression, ], ]; $bucket->iam()->setPolicy($policy); printf('Added the following member(s) with role %s to %s:' . PHP_EOL, $role, $bucketName); foreach ($members as $member) { printf(' %s' . PHP_EOL, $member); } printf('with condition:' . PHP_EOL); printf(' Title: %s' . PHP_EOL, $title); printf(' Description: %s' . PHP_EOL, $description); printf(' Expression: %s' . PHP_EOL, $expression);}
fromgoogle.cloudimportstoragedefadd_bucket_conditional_iam_binding(bucket_name,role,title,description,expression,members):"""Add a conditional IAM binding to a bucket's IAM policy."""# bucket_name = "your-bucket-name"# role = "IAM role, e.g. roles/storage.objectViewer"# members = {"IAM identity, e.g. user: name@example.com}"# title = "Condition title."# description = "Condition description."# expression = "Condition expression."storage_client=storage.Client()bucket=storage_client.bucket(bucket_name)policy=bucket.get_iam_policy(requested_policy_version=3)# Set the policy's version to 3 to use condition in bindings.policy.version=3policy.bindings.append({"role":role,"members":members,"condition":{"title":title,"description":description,"expression":expression,},})bucket.set_iam_policy(policy)print(f"Added the following member(s) with role {role} to {bucket_name}:")formemberinmembers:print(f" {member}")print("with condition:")print(f" Title: {title}")print(f" Description: {description}")print(f" Expression: {expression}")
defadd_bucket_conditional_iam_bindingbucket_name:# The ID of your GCS bucket# bucket_name = "your-unique-bucket-name"require"google/cloud/storage"storage=Google::Cloud::Storage.newbucket=storage.bucketbucket_namerole="roles/storage.objectViewer"member="group:example@google.com"title="Title"description="Description"expression="resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")"bucket.policyrequested_policy_version:3do|policy|policy.version=3policy.bindings.insert(role:role,members:member,condition:{title:title,description:description,expression:expression})endputs"Added #{member} with role #{role} to #{bucket_name} with condition #{title}#{description}#{expression}"end
Rust
usegoogle_cloud_iam_v1::model::{Binding,GetPolicyOptions};usegoogle_cloud_storage::client::StorageControl;usegoogle_cloud_type::model::Expr;pubasyncfnsample(client:&StorageControl,bucket_id:&str,service_account:&str,)->anyhow::Result<()>{constROLE:&str="roles/storage.objectViewer";constTITLE:&str="A service account can read prefix-a-*";letmutpolicy=client.get_iam_policy().set_resource(format!("projects/_/buckets/{bucket_id}")).set_options(GetPolicyOptions::new().set_requested_policy_version(3)).send().await?;letcondition=Expr::new().set_expression(format!(r#"resource.name.startsWith("projects/_/buckets/{bucket_id}/objects/prefix-a-")"#)).set_title(TITLE).set_description(format!("Allows {service_account} read access to objects starting with `prefix-a-`"));letbinding=Binding::new().set_role(ROLE).set_members([format!("serviceAccount:{service_account}")]).set_condition(condition);policy.version=3;policy.bindings.push(binding);letupdated_policy=client.set_iam_policy().set_resource(format!("projects/_/buckets/{bucket_id}")).set_policy(policy).send().await?;println!("Successfully added conditional IAM binding to bucket {bucket_id}: {updated_policy:?}");Ok(())}
VERSION is the
IAM policy version, which is required to be 3
for buckets with IAM Conditions.
IAM_ROLE is the role to which the condition
applies. For example, roles/storage.objectViewer.
PRINCIPAL_IDENTIFIER identifies who the
condition applies to. For example, user:jeffersonloveshiking@gmail.com.
For a list of principal identifier formats, see
Principal identifiers.
TITLE is the title of the condition. For
example, expires in 2019.
DESCRIPTION is an optional description of
the condition. For example, Permission revoked on New Year's.
usingGoogle.Apis.Storage.v1.Data;usingGoogle.Cloud.Storage.V1;usingSystem;usingSystem.Linq;publicclassRemoveBucketConditionalIamBindingSample{publicPolicyRemoveBucketConditionalIamBinding(stringbucketName="your-unique-bucket-name",stringrole="roles/storage.objectViewer",stringtitle="title",stringdescription="description",stringexpression="resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")"){varstorage=StorageClient.Create();varpolicy=storage.GetBucketIamPolicy(bucketName,newGetBucketIamPolicyOptions{RequestedPolicyVersion=3});// Set the policy schema version. For more information, please refer to https://cloud.google.com/iam/docs/policies#versions.policy.Version=3;varbindingsToRemove=policy.Bindings.Where(binding=>binding.Role==role && binding.Condition!=null && binding.Condition.Title==title && binding.Condition.Description==description && binding.Condition.Expression==expression).ToList();if(bindingsToRemove.Count() > 0){foreach(varbindinginbindingsToRemove){policy.Bindings.Remove(binding);}// Set the modified IAM policy to be the current IAM policy.policy=storage.SetBucketIamPolicy(bucketName,policy);Console.WriteLine("Conditional Binding was removed.");}else{Console.WriteLine("No matching conditional binding found.");}returnpolicy;}}
import("context""fmt""io""time""cloud.google.com/go/storage")// removeBucketConditionalIAMBinding removes bucket conditional IAM binding.funcremoveBucketConditionalIAMBinding(wio.Writer,bucketName,role,title,description,expressionstring)error{// bucketName := "bucket-name"// role := "bucket-level IAM role"// title := "condition title"// description := "condition description"// expression := "condition expression"ctx:=context.Background()client,err:=storage.NewClient(ctx)iferr!=nil{returnfmt.Errorf("storage.NewClient: %w",err)}deferclient.Close()ctx,cancel:=context.WithTimeout(ctx,time.Second*10)defercancel()bucket:=client.Bucket(bucketName)policy,err:=bucket.IAM().V3().Policy(ctx)iferr!=nil{returnfmt.Errorf("Bucket(%q).IAM().V3().Policy: %w",bucketName,err)}// Find the index of the binding matching inputs.i:=-1forj,binding:=rangepolicy.Bindings{ifbinding.Role==role && binding.Condition!=nil{condition:=binding.Conditionifcondition.Title==title&&
condition.Description==description&&
condition.Expression==expression{i=j}}}ifi==-1{returnfmt.Errorf("no matching binding group found")}// Get a slice of the bindings, removing the binding at index i.policy.Bindings=append(policy.Bindings[:i],policy.Bindings[i+1:]...)iferr:=bucket.IAM().V3().SetPolicy(ctx,policy);err!=nil{returnfmt.Errorf("Bucket(%q).IAM().V3().SetPolicy: %w",bucketName,err)}// NOTE: It may be necessary to retry this operation if IAM policies are// being modified concurrently. SetPolicy will return an error if the policy// was modified since it was retrieved.fmt.Fprintln(w,"Conditional binding was removed")returnnil}
importcom.google.cloud.Binding;importcom.google.cloud.Condition;importcom.google.cloud.Policy;importcom.google.cloud.storage.Storage;importcom.google.cloud.storage.StorageOptions;importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;publicclassRemoveBucketIamConditionalBinding{/** Example of removing a conditional binding to the Bucket-level IAM */publicstaticvoidremoveBucketIamConditionalBinding(StringprojectId,StringbucketName){// The ID of your GCP project// String projectId = "your-project-id";// The ID of your GCS bucket// String bucketName = "your-unique-bucket-name";// For more information please read:// https://cloud.google.com/storage/docs/access-control/iamStoragestorage=StorageOptions.newBuilder().setProjectId(projectId).build().getService();PolicyoriginalPolicy=storage.getIamPolicy(bucketName,Storage.BucketSourceOption.requestedPolicyVersion(3));Stringrole="roles/storage.objectViewer";// getBindingsList() returns an ImmutableList and copying over to an ArrayList so it's mutable.List<Binding>bindings=newArrayList(originalPolicy.getBindingsList());// Create a condition to compare againstCondition.BuilderconditionBuilder=Condition.newBuilder();conditionBuilder.setTitle("Title");conditionBuilder.setDescription("Description");conditionBuilder.setExpression("resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")");Iteratoriterator=bindings.iterator();while(iterator.hasNext()){Bindingbinding=(Binding)iterator.next();booleanfoundRole=binding.getRole().equals(role);booleanconditionsEqual=conditionBuilder.build().equals(binding.getCondition());// Remove condition when the role and condition are equalif(foundRole && conditionsEqual){iterator.remove();break;}}// Update policy to remove conditional bindingPolicy.BuilderupdatedPolicyBuilder=originalPolicy.toBuilder();updatedPolicyBuilder.setBindings(bindings).setVersion(3);PolicyupdatedPolicy=storage.setIamPolicy(bucketName,updatedPolicyBuilder.build());System.out.println("Conditional Binding was removed.");}}
/** * TODO(developer): Uncomment the following lines before running the sample. */// The ID of your GCS bucket// const bucketName = 'your-unique-bucket-name';// The role to grant// const roleName = 'roles/storage.objectViewer';// The members to grant the new role to// const members = [// 'user:jdoe@example.com',// 'group:admins@example.com',// ];// Create a condition// const title = 'Title';// const description = 'Description';// const expression = 'resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")';// Imports the Google Cloud client libraryconst{Storage}=require('@google-cloud/storage');// Creates a clientconststorage=newStorage();asyncfunctionremoveBucketConditionalBinding(){// Get a reference to a Google Cloud Storage bucketconstbucket=storage.bucket(bucketName);// Gets and updates the bucket's IAM policyconst[policy]=awaitbucket.iam.getPolicy({requestedPolicyVersion:3});// Set the policy's version to 3 to use condition in bindings.policy.version=3;// Finds and removes the appropriate role-member group with specific condition.constindex=policy.bindings.findIndex(binding=>
binding.role===roleName&&
binding.condition&&
binding.condition.title===title&&
binding.condition.description===description&&
binding.condition.expression===expression);constbinding=policy.bindings[index];if(binding){policy.bindings.splice(index,1);// Updates the bucket's IAM policyawaitbucket.iam.setPolicy(policy);console.log('Conditional Binding was removed.');}else{// No matching role-member group with specific condition were foundthrownewError('No matching binding group found.');}}removeBucketConditionalBinding().catch(console.error);
use Google\Cloud\Storage\StorageClient;/** * Removes a conditional IAM binding from a bucket's IAM policy. * * To see how to express a condition in CEL, visit: * @see https://cloud.google.com/storage/docs/access-control/iam#conditions. * * @param string $bucketName The name of your Cloud Storage bucket. * (e.g. 'my-bucket') * @param string $role the role that will be given to members in this binding. * (e.g. 'roles/storage.objectViewer') * @param string $title The title of the condition. (e.g. 'Title') * @param string $description The description of the condition. * (e.g. 'Condition Description') * @param string $expression Te condition specified in CEL expression language. * (e.g. 'resource.name.startsWith("projects/_/buckets/bucket-name/objects/prefix-a-")') */function remove_bucket_conditional_iam_binding(string $bucketName, string $role, string $title, string $description, string $expression): void{ $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); $policy = $bucket->iam()->policy(['requestedPolicyVersion' => 3]); $policy['version'] = 3; $key_of_conditional_binding = null; foreach ($policy['bindings'] as $key => $binding) { if ($binding['role'] == $role && isset($binding['condition'])) { $condition = $binding['condition']; if ($condition['title'] == $title && $condition['description'] == $description && $condition['expression'] == $expression) { $key_of_conditional_binding = $key; break; } } } if ($key_of_conditional_binding != null) { unset($policy['bindings'][$key_of_conditional_binding]); // Ensure array keys are sequential, otherwise JSON encodes // the array as an object, which fails when calling the API. $policy['bindings'] = array_values($policy['bindings']); $bucket->iam()->setPolicy($policy); print('Conditional Binding was removed.' . PHP_EOL); } else { print('No matching conditional binding found.' . PHP_EOL); }}
fromgoogle.cloudimportstoragedefremove_bucket_conditional_iam_binding(bucket_name,role,title,description,expression):"""Remove a conditional IAM binding from a bucket's IAM policy."""# bucket_name = "your-bucket-name"# role = "IAM role, e.g. roles/storage.objectViewer"# title = "Condition title."# description = "Condition description."# expression = "Condition expression."storage_client=storage.Client()bucket=storage_client.bucket(bucket_name)policy=bucket.get_iam_policy(requested_policy_version=3)# Set the policy's version to 3 to use condition in bindings.policy.version=3condition={"title":title,"description":description,"expression":expression,}policy.bindings=[bindingforbindinginpolicy.bindingsifnot(binding["role"]==roleandbinding.get("condition")==condition)]bucket.set_iam_policy(policy)print("Conditional Binding was removed.")
defremove_bucket_conditional_iam_bindingbucket_name:# The ID of your GCS bucket# bucket_name = "your-unique-bucket-name"require"google/cloud/storage"storage=Google::Cloud::Storage.newbucket=storage.bucketbucket_namerole="roles/storage.objectViewer"title="Title"description="Description"expression="resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")"bucket.policyrequested_policy_version:3do|policy|policy.version=3binding_to_remove=nilpolicy.bindings.eachdo|b|condition={title:title,description:description,expression:expression}ifb.role==role && b.condition&&
b.condition.title==title&&
b.condition.description==description&&
b.condition.expression==expressionbinding_to_remove=bendendifbinding_to_removepolicy.bindings.removebinding_to_removeputs"Conditional Binding was removed."elseputs"No matching conditional binding found."endendend
Rust
usegoogle_cloud_iam_v1::model::GetPolicyOptions;usegoogle_cloud_storage::client::StorageControl;pubasyncfnsample(client:&StorageControl,bucket_id:&str)->anyhow::Result<()>{constROLE:&str="roles/storage.objectViewer";constTITLE:&str="A service account can read prefix-a-*";letmutpolicy=client.get_iam_policy().set_resource(format!("projects/_/buckets/{bucket_id}")).set_options(GetPolicyOptions::new().set_requested_policy_version(3)).send().await?;policy.version=3;policy.bindings.retain(|b|{// Remove the bindings matching the role *and* the condition title.b.role!=ROLE||b.condition.as_ref().is_none_or(|c|c.title!=TITLE)});letupdated_policy=client.set_iam_policy().set_resource(format!("projects/_/buckets/{bucket_id}")).set_policy(policy).send().await?;println!("Successfully removed conditional IAM binding from bucket {bucket_id}");println!("The updated policy is: {:?}",updated_policy);Ok(())}
Where BUCKET_NAME is the name of the bucket
whose IAM policy you want to modify. For example, my-bucket.
Best practices
You should set the minimum role needed to give the principal
the required access. For example, if a team member only needs to read
objects stored in a bucket, grant them the Storage Object Viewer
(roles/storage.objectViewer) role instead of the Storage Object Admin
(roles/storage.objectAdmin) role. Similarly, if the team member needs full
control of objects in the bucket but not the bucket itself, grant them the
Storage Object Admin (roles/storage.objectAdmin) role instead of the
Storage Admin (roles/storage.admin) role.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2026-06-09 UTC."],[],[]]