Access control for Google Cloud resources is managed by Cloud IAM policies. A Cloud IAM policy is attached to a resource, and restricts access to both the resource itself as well as any child resources through policy inheritance.
This topic provides JSON examples of Cloud IAM policies, although YAML is also supported.
Policy structure
A policy is a collection of bindings, audit configuration, and metadata. A
binding specifies how access should be granted on resources. It associates (or
binds) one or more members with a single role and any context-specific
conditions that change how and when the role is granted. The AuditConfig
field specifies the configuration data for how access attempts should be
audited. The metadata includes additional information about the policy, such as
an etag and version to facilitate policy management. Each part is described
below:
- A list of bindings. Each binding includes the following fields:
- A member, also known as an identity or principal, can be a user account, service account, Google group, or domain.
- A role is a named collection of permissions that grant access to perform actions on Google Cloud resources.
- A condition is a logic expression that further constrains the role binding based on attributes about the request, such as its origin, the target resource, and so on. Conditions are typically used to express restrictions according to the context when the access request is made.
- An
AuditConfig
field, which is used to configure audit logging for the policy. - Metadata, which includes the following fields:
- An
etag
field, which is used for concurrency control, and ensures that policies are updated consistently. - A
version
field, which specifies the schema version for a given policy. Usage of theversion
field is explained in more detail in policy versions section.
- An
A role binding in a Cloud IAM policy is the combination of both the role and a list of members. If a role binding also contains a condition, it is referred to as a conditional role binding.
Using etags in a policy
When you have multiple systems trying to write to the same Cloud IAM policy at the same time, there is a risk that those systems might overwrite each other's changes. This risk arises because modifying an Cloud IAM policy involves three operations: retrieving the current policy, modifying its content as desired, and then setting the new policy in its entirety. If two systems are doing this at once, it is possible that one of those systems will set an updated policy not realizing that the policy had been changed between when it was initially retrieved and now.
To avoid such scenarios, Cloud IAM supports concurrency control through
the use of an etag
field in the policy. Whenever you retrieve a policy, be
sure that you use the etag
from the retrieved policy when you submit
your modified policy. If the policy has been modified since you retrieved it,
the etag
will not match and your update will fail.
When this occurs, retry the entire operation: retrieve the policy again, apply your modifications, and submit the updated policy. We recommend that you perform this retry logic automatically in any code or scripts that you use to manage Cloud IAM policies.
Example: Simple policy
Consider the following example policy that binds a member to a role:
{
"bindings": [
{
"members": [
"user:jim@example.com"
],
"role": "roles/owner"
}
],
"etag": "BwUjMhCsNvY=",
"version": 1
}
In the example above, jim@example.com
is granted the
Owner primitive role
without any conditions. The binding to a primitive role is often overly
permissive; in this case, the Owner role contains over 1,000 permissions. We
recommend that you grant a
predefined role or a
custom role instead of a primitive role,
as these role types are designed to be limited in scope and in the number of
their permissions.
Example: Policy with multiple bindings
Consider the following example policy that contains more than one binding. Each binding grants a different role:
{
"bindings": [
{
"members": [
"user:jim@example.com"
],
"role": "roles/resourcemanager.organizationAdmin"
},
{
"members": [
"user:alice@example.com",
"user:jim@example.com"
],
"role": "roles/resourcemanager.projectCreator"
}
],
"etag": "BwUjMhCsNvY=",
"version": 1
}
In the example above, Jim (jim@example.com
) is granted the Organization
Admin predefined role
(roles/resourcemanager.organizationAdmin
) in the first role binding. This role
contains permissions for organizations, folders, and limited projects
operations. In the second role binding, both Jim and Alice (alice@example.com
) are
granted the ability to create projects via the Project Creator role
(roles/resourcemanager.projectCreator
). Together, these bindings grant fine-
grained access to both Jim and Alice, where access granted to Alice is the subset
of the access granted to Jim.
Example: Conditional policy
Consider the following example policy that binds members to a predefined role, and includes a condition expression to further constrain the role binding:
{
"bindings": [
{
"members": [
"group:prod-dev@example.com",
"serviceAccount:prod-dev-example@appspot.gserviceaccount.com"
],
"role": "roles/appengine.Deployer",
"condition": {
"title": "Expires_July_1_2020",
"description": "Expires on July 1, 2020",
"expression":
"request.time < timestamp(\"2020-07-01T00:00:00.000Z\")"
}
}
],
"etag": "BwWKmjvelug=",
"version": 3
}
Note that in the example above, the policy version is set to 3
. This is
because conditional policy is configured as policy schema version 3
.
See Policy versions for more information.
The example above provides more granular access than the first two examples. A
Google group (prod-dev@example.com
) -- which contains multiple user accounts -
- and a service account (prod-dev-example@appspot.gserviceaccount.com
) are
granted the App Engine Deployer predefined role (roles/appengine.deployer
).
Additionally, the role binding is further constrained by a date/time
condition (thus becoming a conditional role binding): these members' ability to
deploy App Engine apps will expire at the specified time.
Policy limitations
The following limitations apply for Cloud IAM policies:
Every Google Cloud resource that supports a Cloud IAM policy at its level in the resource hierarchy can have a maximum of one policy. For example, organizations, folders, projects, or individual resources (such as Compute Engine disks, images, and more).
Each policy can contain up to a total of 1,500
members
across all of its bindings, regardless of the member types. In addition, the Google Group member type is limited to 250 across all role bindings in one policy.In general, any policy changes will take effect within 60 seconds after either calling
setIamPolicy()
or by updating a role binding in the Cloud Console. However, under certain circumstances, it may take up to 7 minutes for policy changes to fully propagate across the system.Some GCP services do not currently support resource-level conditional policies. For example, a conditional policy that constrains access to a service's resource can be set on the project, but a conditional policy set on the resource itself is not supported.
Policy inheritance and the resource hierarchy
Google Cloud resources are organized hierarchically, where the organization node is the root node in the hierarchy, then optionally folders, then projects. Most of other resources are created and managed under a project. Each resource has exactly one parent, except the root node in the hierarchy. See the Resource Hierarchy topic for more information.
The resource hierarchy is important to consider when setting Cloud IAM policy. When setting a policy at a higher level in the hierarchy, such as at the organization level, folder level, or project level, the granted access scope includes the resource level where this policy is attached to and all resources under that level. For example, a policy set at the organization level applies to the organization and all resources under the organization. Similarly, a policy set at the project level applies to the project and all resources in the project.
Policy inheritance is the term that describes how policies apply to resources beneath their level in the resource hierarchy. Effective policy is the term that describes how all parent policies in the resource hierarchy are inherited for a resource. It is the union of:
- The policy set on the resource, and
- The policies set on all of resource's ancestry resource levels in the hierarchy
Each new role binding (inherited from parent resources) that affect the resource's effective policy are evaluated independently. A specific access request to the resource is granted if any of the higher-level role bindings grant access to the request.
If a new role binding is introduced to any level of resource's inherited policy, the access grant scope increases.
Example: Policy inheritance
To understand policy inheritance, consider the following example policy that is set at the organization level:
Organization-level policy
{
"bindings": [
{
"members": [
"user:alice@example.com"
],
"role": "roles/storage.objectViewer"
}
],
"etag": "BwUjMhCsNvY=",
"version": 1
}
The Storage Object Viewer role (roles/storage.objectViewer
) contains get
and
list
permissions for projects and Cloud Storage objects. When set at the
organization level, this role binding is applied to levels under the
organization, including all projects and all Cloud Storage objects under
those projects.
To further demonstrate policy inheritance, consider what happens when a policy
is further set at myproject-123
:
Project-level policy
{
"bindings": [
{
"members": [
"user:alice@example.com"
],
"role": "roles/storage.objectCreator"
}
],
"etag": "BwUjMhCsNvY=",
"version": 1
}
In the example above, the Storage Object Creator role
(roles/storage.objectCreator
) grants Alice the ability to create
Cloud Storage objects, under myproject-123
. Now that there are two role
bindings that grant Alice access to the target Cloud Storage objects under
myproject-123
.
- A policy at the organization level grants the ability to list and get all Cloud Storage objects under this organization
- A policy at
myproject-123
grants the ability to create objects, undermyproject-123
, where the policy is attached.
The table below summarizes Alice's effective policy:
Permissions granted via "storage.objectViewer" role at organization level | Permissions granted via "storage.objectCreator" role at "myproject-123" | Effective grant scope for Alice under "myproject-123" |
---|---|---|
resourcemanager.projects.get resourcemanager.projects.list storage.objects.get storage.objects.list |
resourcemanager.projects.get resourcemanager.projects.list storage.objects.create |
resourcemanager.projects.get resourcemanager.projects.list storage.objects.get storage.objects.list storage.objects.create |
Policy versions
Over time, Cloud IAM may add new features that significantly add or change fields in the policy schema. To avoid breaking your existing integrations that rely on consistency in the policy structure, such changes are introduced in new policy schema versions.
If you are integrating with Cloud IAM for the first time, we recommend using the most recent policy schema version available at that time. Below, we'll discuss the different versions available and how to use each. We'll also describe how to specify your desired version and walk you through some troubleshooting scenarios.
Every existing Cloud IAM policy specifies a version
field as
part of the policy's metadata. Consider the highlighted portion below:
{ "bindings": [ { "members": [ "user:jim@example.com" ], "role": "roles/owner" } ], "etag": "BwUjMhCsNvY=", "version": 1 }
This field specifies the syntax schema version of the policy. Each version of the policy contains a specific syntax schema that can be used by bindings. The newer version may contain role bindings with the newer syntax schema that is unsupported by earlier versions. This field is not intended to be used for any purposes other than policy syntax schema control.
Valid policy versions and version calculation
The policy version is determined by the syntax schema version by the role bindings contained in the policy. The following policy versions are valid:
Version | Description |
---|---|
1 |
The first version of Cloud IAM policy schema. Supports binding one role to one or more members. Does not support conditional bindings. |
2 |
Invalid. For internal use only. |
3 |
Introduces the |
Specifying a policy version when getting a policy
When getting a policy, we recommend specifying a policy version. By explicitly
requesting a specific policy version, the client making the call to get a policy
declares that it knows how to handle the Cloud IAM policy of that
version. If no policy version is specified, it is set to version 1
by default.
Cloud IAM calculates the policy version of the stored policy. If
the policy content currently leverages features only available in higher
versions than requested, the getIamPolicy()
operation fails. The failure
scenario is demonstrated in Scenario 2 below. In the success
case, the returned policy contains the policy version that reflects the content
of the policy.
This policy version control is enabled primarily for handling older versions of
client libraries that do not understand how to handle version 3
Cloud IAM policies with conditional role bindings. Therefore, older
versions of client libraries are prevented from unintentionally removing or
modifying a conditional role binding in the policy. See below
for further details.
Scenario 1: Getting a policy with the highest policy version
Consider the following REST command to get policy on a project.
POST https://cloudresourcemanager.googleapis.com/v1/projects/[PROJECT-ID]:getIamPolicy
The request body should be set to the following:
{
"options": {
"requestedPolicyVersion": 3
}
}
The response body will contain the project's Cloud IAM policy:
{
"bindings": [
{
"members": [
"user:user@example.com"
],
"role": "roles/iam.securityReviewer",
"condition": {
"title": "Expires_July_1_2020",
"description": "Expires on July 1, 2020",
"expression": "request.time < timestamp(\"2020-07-01T00:00:00.000Z\")"
}
}
],
"etag": "BwWKmjvelug=",
"version": 3
}
In another case, a similar request on another project may request version 3
,
but receive a version 1
policy, because the second project has policy of
version 1
based on its content. In this case, because the policy does not
contain a conditional role binding, it only requires the functionality available
in the version 1
schema.
{
"bindings": [
{
"members": [
"user:user@example.com"
],
"role": "roles/iam.securityReviewer",
}
],
"etag": "BwWKmjvelug=",
"version": 1
}
Scenario 2: Requesting a policy with an insufficient version
Consider that the policy in Scenario 1 above contains a conditional role
binding. In this case, its calculated policy version would be 3
. Suppose that
you then try to request a lower version, such as 1
:
POST https://cloudresourcemanager.googleapis.com/v1/projects/[PROJECT-ID]:getIamPolicy
With an empty request body, or a request body as follows:
{
"options": {
"requestedPolicyVersion": 1
}
}
The response will contain an error:
"Requested policy version (1) cannot be less than the existing policy version
(3). For more information please refer to
https://cloud.google.com/iam/docs/policies#versions."
Specifying policy version when setting policy
You can specify a policy version when creating or modifying a policy. The
version you choose is an indication of the policy schema version that your
client is capable of understanding. If not specified, it is considered as the
default value of version 1
.
Cloud IAM calculates the policy version based on the content of the
policy. If the specified policy schema version is lower than calculated policy
version, the setIamPolicy()
operation fails.
Scenario 1: Updating a higher-version policy with a lower-version policy
Consider the following policy that is currently in effect, and returned from
the getIamPolicy()
operation.
{
"bindings": [
{
"members": [
"user:alice@example.com"
],
"role": "roles/storage.admin",
"condition": {
"title": "Weekday_access",
"description": "Monday thru Friday access only in America/Chicago",
"expression": "request.time.getDayOfWeek(\"America/Chicago\") >= 1 && request.time.getDayOfWeek(\"America/Chicago\") <= 5"
}
}
],
"etag": "BwUjMhCsNvY=",
"version": 3
}
This policy contains a conditional role binding and is version 3
. The policy
is updated as the following. Alice is then granted unconditional access to
Cloud Storage resources as the storage admin by setting:
{
"bindings": [
{
"members": [
"user:alice@example.com"
],
"role": "roles/storage.admin"
}
],
"etag": "BwUjMhCsNvY=",
"version": 3
}
As recommended, the specified version is set to 3
. This is the maximum policy
version that your client supports. Note that it is required in this case that
you specify version 3
in the setIamPolicy()
request to successfully update
the policy. This is the protection against accidentally overwriting a version
3
policy by a client that only supports policy with maximum version lower than
3
. In this case, you will receive an error, stating that "Specified policy
version (1) cannot be less than the existing policy version (3)"
.
Upon successfully setting this policy with version 3
specified, the returned
response contains the following:
{
"bindings": [
{
"members": [
"user:alice@example.com"
],
"role": "roles/storage.admin"
}
],
"etag": "BwUjMhCsNvY=",
"version": 1
}
The returned policy in the response contains the calculated version based on
the content of the successfully set policy. In this case, it is set to 1
.
Scenario 2: Updating a policy with insufficient version
Consider the following policy that specifies the incorrect version:
{
"bindings": [
{
"members": [
"user:user@example.com"
],
"role": "roles/iam.securityReviewer",
"condition": {
"title": "Expires_July_1_2020",
"description": "Expires on July 1, 2020",
"expression": "request.time < timestamp(\"2020-07-01T00:00:00.000Z\")"
}
}
],
"etag": "BwWKmjvelug=",
"version": 1
}
In this case the user-specified policy version is lower than the calculated
policy version. The setIamPolicy()
request fails. The response will contain
an error:
"Specified policy version (1) must be at least 3 based on the policy's
contents. For more information, please refer to
https://cloud.google.com/iam/docs/policies#versions."
To fix this issue, either update the policy version to 3
(if your client is
capable of understanding this policy version), or remove the condition.
Client library and code support for policy versions
Currently, not all Google Cloud client libraries support
Cloud IAM policy versions greater than 1
. If you use a client
library version that was built before Cloud IAM policy version 3
was
introduced, your client library will not be able to handle version 3
policies.
In this case, the client library may receive an error when attempting to set or
get a policy with calculated policy version 3
.
We recommend the following actions for managing Cloud IAM policies through a client library:
Always ensure that your preferred client library supports the newest policy version, and always set the proper policy version value when interacting with policies on your Google Cloud resources using the latest client.
Always specify the most recent policy version when getting or setting a policy. Currently, it is version
3
.
Minimum supported versions
Only the
Google APIs Client Libraries
currently support Cloud IAM policy versions greater than 1
.
Google Cloud Client Libraries do not
support policy versions greater than 1
.
Each service and their respective client libraries are listed below.
Google APIs Client Libraries
The minimum library version per language is supported for:
- Cloud Storage API
- Cloud KMS API
- Compute Engine Alpha API
- Compute Engine Beta API
- Resource Manager API
- Cloud IAM API
Supported language libraries are listed below:
Python: google-api-python-client v1.7.11
Node.js: googleapis v43.0.0
Java:
- google-api-services-storage v1-rev20190910-1.30.3
- google-api-services-compute alpha-rev20190815-1.28.0
- google-api-services-compute beta-rev20190815-1.28.0
- google-api-services-cloudresourcemanager v2-rev20190807-1.28.0
- google-api-services-cloudkms v1-rev20190824 -1.28.0
- google-api-services-iam v1-rev20190906-1.28.0
Google Cloud Client Libraries
The following libraries do not support policy version 3
:
- Cloud Storage API
- Cloud KMS API
Unsupported language libraries are listed below:
C#:
Python:
PHP:
Ruby:
Go:
Node.js:
Java:
Policy best practices
The following best practices apply to organizations with many Google Cloud users:
When managing multiple user accounts with the same access configurations, use Google groups instead. Put each individual user account into the group, and grant the intended roles to the group instead of individual user accounts.
Permissions granted at the organization level: Carefully consider which members are granted access permissions at the organization level. For most organizations, only a few specific teams (such as Security and Network teams) should be granted access at this level of the resource hierarchy.
Permissions granted at the folder levels: Consider reflecting your organization's operation structure by using tiers of folders, where each parent/child folder can be configured with different sets of access grants that are aligned with business and operation needs. For example, a parent folder might reflect a department, one of its child folder might reflect resource access and operation by a group, and another child folder might reflect a small team. Both of these two folders may contain projects for their team's operation needs. Using folders in this way can ensure proper access separation, while respecting policies inherited from parent folder(s) and organization. This practice requires less policy maintenance when creating and managing Google Cloud resources.
Permissions granted at the project level: Grant role bindings at the project level only as required for specific groups or for individual granular permissions. For easier manageability, especially with many projects, we highly recommend setting policies at a folder level when possible.
Specify policy version: We highly recommend using Google Cloud provided tools, such as the Cloud Console and the
gcloud
tool, to manage Cloud IAM policies. When interacting with the REST API, always specify the latest policy version when sending agetIamPolicy()
orsetIamPolicy()
request. Always ensure that your preferred client library supports the latest policy version, and always specify the latest policy version when getting or setting policies through your client library.