Creating and managing access control lists (ACLs)

This page describes how to control access to buckets and objects
using Access Control Lists (ACLs). ACLs are a mechanism you can use to define
who has access to your buckets and objects, as well as what level of access they
have. To learn more about ACLs, read the Overview of ACLs.

Before you begin

Should you use ACLs?

In most cases, Cloud Identity and Access Management (Cloud IAM) is the
recommended method for controlling access to your resources, because it provides
enterprise-grade access control across all of Google Cloud Platform, and it allows
permissions granted to parent resources, such as projects, to be inherited
by child resources, such as buckets and objects. See Using Cloud IAM Permissions
for guides to working with Cloud IAM in Cloud Storage.

You most likely want to use ACLs if you need to customize access to individual
objects within a bucket, because Cloud IAM permissions apply to all
objects within a bucket. However, you should still use Cloud IAM for
any access that is common to all objects in a bucket, as this reduces the amount
of fine-grained managing you have to do.

Caution: Permissions can be granted either by ACLs or Cloud IAM
policies: a user only needs permission from one of these to access a bucket or
object. In general, permissions granted by Cloud IAM policies do not
appear in ACLs, and permissions granted by ACLs do not appear in
Cloud IAM policies. The only exception is for ACLs applied directly on
a bucket and certain bucket-level Cloud IAM policies, as described in
Cloud IAM relation to ACLs.

Do you need to set an ACL?

Depending on the permission that you want a bucket or object to
have, you might not need to set an ACL. Buckets and objects are
created with default ACLs that might already contain the permission that
you want the bucket or object to have.

XML API

As noted above, every bucket has a default object ACL that is applied to all
objects uploaded to that bucket that do not have a predefined ACL or (if you
are using the JSON API) an ACL specified in the request. Read more in
Default object ACLs.

On objects:

Console

Uploaded objects get the same ACLs as the bucket object, and the uploader
is added as owner to the ACL. If your object needs a different permission,
set an ACL.

gsutil

New objects are added with the default object ACL for the bucket. When
copying an object already stored in the cloud, you can override this
behavior with the -p option.

JSON API

By default, new objects are added with the default object ACL for the bucket.

XML API

New objects are added with the default object ACL for the bucket.

Which interface should you use?

The examples below show how to configure access control using the
Google Cloud Platform Console, the gsutil command line tool, the Cloud Storage Client
Libraries, and the XML and JSON APIs. Use these guidelines to choose which one to use:

If you are new to access control and only wish to modify ACLs for
individual objects, use the GCP Console.

If you are new to access control and wish to modify ACLs for buckets and
objects, use gsutil.

If you have experience with one of the Cloud Storage Client Libraries, use
it for managing your ACLs.

If you are specifying ACLs using an API, you should have previous experience
making HTTP requests. You can use your favorite tool or application to send
the HTTP requests. In the examples, we use the cURL tool. You can get authorization tokens to
use in the cURL examples from the OAuth 2.0 Playground.

Setting ACLs

The tool or API you use to set and get ACLs determines the ACL syntax you use.
The ACL syntaxes look different, but they contain the same ACL information: entries
that grant permissions to scopes.

Console

Note: You cannot use the GCP Console to set ACLs on buckets; the
Console can only be used to set ACLs on individual objects.

Node.js

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');
// Creates a client
const storage = new Storage();
/**
* TODO(developer): Uncomment the following line before running the sample.
*/
// const bucketName = 'Name of a bucket, e.g. my-bucket';
// const userEmail = 'Email of user to add, e.g. developer@company.com';
// Makes the user an owner of the bucket. You can use addAllUsers(),
// addDomain(), addProject(), addGroup(), and addAllAuthenticatedUsers()
// to grant access to different types of entities. You can also use "readers"
// and "writers" to grant different roles.
await storage.bucket(bucketName).acl.owners.addUser(userEmail);
console.log(`Added user ${userEmail} as an owner on bucket ${bucketName}.`);

Python

def add_bucket_owner(bucket_name, user_email):
"""Adds a user as an owner on the given bucket."""
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
# Reload fetches the current ACL from Cloud Storage.
bucket.acl.reload()
# You can also use `group()`, `domain()`, `all_authenticated()` and `all()`
# to grant access to different types of entities.
# You can also use `grant_read()` or `grant_write()` to grant different
# roles.
bucket.acl.user(user_email).grant_owner()
bucket.acl.save()
print('Added user {} as an owner on bucket {}.'.format(
user_email, bucket_name))

def add_blob_owner(bucket_name, blob_name, user_email):
"""Adds a user as an owner on the given blob."""
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(blob_name)
# Reload fetches the current ACL from Cloud Storage.
blob.acl.reload()
# You can also use `group`, `domain`, `all_authenticated` and `all` to
# grant access to different types of entities. You can also use
# `grant_read` or `grant_write` to grant different roles.
blob.acl.user(user_email).grant_owner()
blob.acl.save()
print('Added user {} as an owner on blob {} in bucket {}.'.format(
user_email, blob_name, bucket_name))

JSON API

When creating a bucket, you can specify the acl[] property in
an insert request. For an existing bucket, specify the acl[]
property in a patch or update request.

When creating an object, you can specify the acl[] property in
the request body or the predefinedAcl query parameter in an insert
request. For an existing object, specify the acl[] property or the
predefinedAcl query parameter in a patch or update request.

XML API

In the XML API, you work with ACLs in XML format. You must attach an
XML document to the body of requests to change bucket and object ACLs.
An XML document is returned when you get bucket and object ACLs. The XML
document contains the individual bucket or object ACL entries.

After creating a bucket with a PUT Bucket request, use a second
PUT Bucket request with the ?acl parameter to change the bucket ACL.

After uploading an object with a PUT Object request, change the ACL
with another PUT request using the ?acl parameter or the x-googl-acl request header.

Container for DisplayName and ID elements. This element is not required for objects since an object is always owned by the user who uploaded it. This element is used when you are using Amazon S3 ACL syntax in a migration scenario.

Amazon Simple Storage Service and Amazon S3 are trademarks of Amazon.com, Inc. or its affiliates in the United States and/or other countries.

ID

Google Cloud Storage ID of the bucket owner.

DisplayName

Not currently implemented. The value is always an empty string.

Entries

Container for zero or more Entry elements.

Entry

Container for Scope and Permission elements. An Entry must contain only one Scope and one Permission element.

Scope

Container for an ID, EmailAddress, or Domain element that defines the ACL scope. This element must have a type attribute that contains one of the following values: UserByID, UserByEmail, GroupByID, GroupByEmail, GroupByDomain, AllUsers, or AllAuthenticatedUsers.

ID

An identifier for the grantee when the permission entry is specified by ID.

EmailAddress

The email identifier for the grantee when the permission entry is specified by email.

Domain

The domain identifier for the grantee when the permission entry is specified by domain.

Name

Optional element that can be specified or that can be automatically added if the scope is UserByEmail or GroupByEmail.

Permission

The permission granted READ, WRITE, or FULL_CONTROL.

When working with ACLs using the XML API:

You can only use the XML format described above.

You cannot set duplicate scopes.

You can have many entries in your ACL XML, but you cannot have entries
with duplicate scopes. For example, you cannot have two entries with
the same scope element of jane@example.com.

When you set ACLs, you can choose to include the <Name> element
with your ACL entries. You can provide any value in the <Name>
element, and Cloud Storage remembers these values until the ACL is
removed or overwritten. This approach can be useful if you are using identifiers
that aren't easily identifiable, like Google Cloud Storage IDs.

When a UserByEmail or GroupByEmail scope contains a public Google profile.

If you use either of these scopes but do not provide a <Name>
element, Cloud Storage checks if the user or Google Group associated with the email
address has a public Google profile with a public name. If so,
Cloud Storage automatically populates the <Name> element with
the public name.

Applying a predefined ACL

Rather than specifying the entire ACL one entry at a time as shown above, you
can use a predefined ACL, which will automatically apply a number of entries
customized to a specific scenario. You can apply a predefined ACL to either a
bucket or an object by using gsutil, the JSON API, or the XML API.

Setting default object ACLs

To avoid setting ACLs every time you create a new object, you can set a default
object ACL on a bucket. After you do this, every new object that is added to
that bucket that does not explicitly have an ACL applied to it will have the
default applied to it. For example, you might want to specify that only a
certain group of users have access to most objects in a particular bucket. You
can change the default object ACL, and then add objects to the bucket. These
added objects have the default object ACL you specified automatically applied to
them; however, you can give specific objects different ACLs, in which case
those objects do not have the default ACL applied to them.

Important: If you change the default object ACL for a bucket, the change may
take time to propagate, and new objects created in the bucket may still get
the old default object ACL for a short period of time (see Consistency).
In order to make sure that new objects created in the bucket get the updated
default object ACL, you should wait at least 30 seconds between changing
the default object ACL and creating new objects.

To view and change the default object ACL for a bucket:

Console

You cannot set default object ACLs using the GCP Console. Use
gsutil instead.

Node.js

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');
// Creates a client
const storage = new Storage();
/**
* TODO(developer): Uncomment the following line before running the sample.
*/
// const bucketName = 'Name of a bucket, e.g. my-bucket';
// const userEmail = 'Email of user to add, e.g. developer@company.com';
// Makes the user an owner in the default ACL of the bucket. You can use
// addAllUsers(), addDomain(), addProject(), addGroup(), and
// addAllAuthenticatedUsers() to grant access to different types of entities.
// You can also use "readers" and "writers" to grant different roles.
await storage.bucket(bucketName).acl.default.owners.addUser(userEmail);
console.log(`Added user ${userEmail} as an owner on bucket ${bucketName}.`);

Python

def add_bucket_default_owner(bucket_name, user_email):
"""Adds a user as an owner in the given bucket's default object access
control list."""
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
# Reload fetches the current ACL from Cloud Storage.
bucket.acl.reload()
# You can also use `group`, `domain`, `all_authenticated` and `all` to
# grant access to different types of entities. You can also use
# `grant_read` or `grant_write` to grant different roles.
bucket.default_object_acl.user(user_email).grant_owner()
bucket.default_object_acl.save()
print('Added user {} as an owner in the default acl on bucket {}.'.format(
user_email, bucket_name))

def remove_bucket_default_owner(bucket_name, user_email):
"""Removes a user from the access control list of the given bucket's
default object access control list."""
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
# Reload fetches the current ACL from Cloud Storage.
bucket.acl.reload()
# You can also use `group`, `domain`, `all_authenticated` and `all` to
# remove access for different types of entities.
bucket.default_object_acl.user(user_email).revoke_read()
bucket.default_object_acl.user(user_email).revoke_write()
bucket.default_object_acl.user(user_email).revoke_owner()
bucket.default_object_acl.save()
print('Removed user {} from the default acl of bucket {}.'.format(
user_email, bucket_name))

When gsutil returns ACLs for buckets and objects with gsutil acl get,
they are in the same JSON format that you can use to set ACLs. ACLs in
JSON format use the JSON API property names, such as entity and role.

See the JSON API syntax for more information about how to interpret the output
or run gsutil help acls.

You can also use the JSON GET method of the ObjectAccessControls
resource to return a specific ACL entry.

Caution: ACLs work independently from Cloud IAM permissions. You
can use these two access control methods to customize your permissions. However,
if you grant access to your buckets and objects using Cloud IAM
permissions, such permissions do not appear in the ACLs for individual buckets
or objects (except for legacyBucket roles).

Changing ACLs

To change the ACL of an existing object or bucket:

Console

Note: You cannot use the GCP Console to change ACLs on buckets;
the Console can only be used to change ACLs on individual objects.

The following example shows how to grant the jane@gmail.com user OWNER permission
and the members of the gs-announce group READER permission on the
object paris.jpg:

gsutil

Define the ACLs in a file.

Pass the ACLs file to gsutil acl set, and specify the object to
set the ACLs on.

For example, to apply the ACLs from the file acls.txt on an object
named paris.jpg in the bucket example-travel-maps:

gsutil acl set acl.txt gs://example-travel-maps/paris.jpg

The contents of acl.txt are shown below. These ACLs grant the owners
of project 867489160491 along with the user jane@gmail.comOWNER permission for the object paris.jpg, and they grant the members
of the gs-announce group READER permission for this object:

Python

def remove_bucket_owner(bucket_name, user_email):
"""Removes a user from the access control list of the given bucket."""
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
# Reload fetches the current ACL from Cloud Storage.
bucket.acl.reload()
# You can also use `group`, `domain`, `all_authenticated` and `all` to
# remove access for different types of entities.
bucket.acl.user(user_email).revoke_read()
bucket.acl.user(user_email).revoke_write()
bucket.acl.user(user_email).revoke_owner()
bucket.acl.save()
print('Removed user {} from bucket {}.'.format(
user_email, bucket_name))

def remove_blob_owner(bucket_name, blob_name, user_email):
"""Removes a user from the access control list of the given blob in the
given bucket."""
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(blob_name)
# You can also use `group`, `domain`, `all_authenticated` and `all` to
# remove access for different types of entities.
blob.acl.user(user_email).revoke_read()
blob.acl.user(user_email).revoke_write()
blob.acl.user(user_email).revoke_owner()
blob.acl.save()
print('Removed user {} from blob {} in bucket {}.'.format(
user_email, blob_name, bucket_name))

If the ACL grants the owners of project 867489160491 and the user
jane@gmail.comOWNER permission, along with granting the members of the
gs-announce group READER permission, then the request looks like the
following example: