Understanding policies

Access control for Google Cloud resources is managed by Identity and Access Management (IAM) policies, which are attached to resources. You can attach only one IAM policy to each resource. The IAM policy controls access to the resource itself, as well as any descendants of that resource that inherit the policy.

This page shows IAM policies in JSON format. You can also use the gcloud command-line tool to retrieve policies in YAML format.

Policy structure

An IAM policy is a collection of role bindings and metadata. A role binding specifies what access should be granted to a resource. It associates, or binds, one or more principals with a single IAM role and any context-specific conditions that change how and when the role is granted. The metadata includes additional information about the policy, such as an etag and version to facilitate policy management.

Each role binding can include the following fields:

  • A principal, also known as a member or identity, which can be a user account, service account, Google group, or domain.

    Each IAM policy can contain up to 1,500 principals. Up to 250 of these principals can be Google groups.

    IAM counts all appearances of each principal in the policy's bindings. It does not deduplicate principals that appear in more than one binding. For example, if the principal user:alice@example.com appears in 50 bindings, then you could add another 1,450 principals across all bindings in the policy.

  • A role, which is a named collection of permissions that provide the ability to perform actions on Google Cloud resources.

  • A condition, which is an optional 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 control whether access is granted based on the context for a request.

    If a role binding contains a condition, it is referred to as a conditional role binding.

    Some Google Cloud services do not accept conditions in IAM policies. For a list of services and resource types that accept conditions, see Resource types that accept conditional role bindings.

The metadata for an IAM policy includes the following fields:

  • An etag field, which is used for concurrency control, and ensures that policies are updated consistently. For details, see Using etags in a policy on this page.
  • A version field, which specifies the schema version for a given policy. For details, see Policy versions on this page.

For organizations, folders, projects, and billing accounts, the IAM policy can also contain an auditConfig field, which specifies the types of activity that generate audit logs for each service. To learn how to configure this part of an IAM policy, see Configuring Data Access audit logs.

In general, when you update an IAM policy, your changes take effect within 60 seconds. In some cases, though, it can take up to 7 minutes for the change to fully propagate across Google Cloud.

Using etags in a policy

When multiple systems try to write to the same IAM policy at the same time, there is a risk that those systems might overwrite each other's changes. This risk exists because updating an IAM policy involves multiple operations:

  1. Reading the existing policy
  2. Modifying the policy
  3. Writing the entire policy

If System A reads a policy, and System B immediately writes an updated version of that policy, then System A will not be aware of the changes from System B. When System A writes its own changes to the policy, System B's changes could be lost.

To help prevent this issue, Identity and Access Management (IAM) supports concurrency control through the use of an etag field in the policy. Every IAM policy contains an etag field, and the value of this field changes each time a policy is updated. If an IAM policy contains an etag field, but no role bindings, then the policy does not grant any IAM roles.

The etag field contains a value such as BwUjMhCsNvY=. When you update the policy, be sure to include the etag field in the updated policy. If the policy has been modified since you retrieved it, the etag value will not match, and the update will fail. For the REST API, you receive the HTTP status code 409 Conflict, and the response body is similar to the following:

{
  "error": {
    "code": 409,
    "message": "There were concurrent policy changes. Please retry the whole read-modify-write with exponential backoff.",
    "status": "ABORTED"
  }
}

If you receive this error, retry the entire series of operations: read the policy again, modify it as needed, and write the updated policy. You should perform retries automatically, with exponential backoff, in any tools that you use to manage IAM policies.

To learn how to update policies using the read-modify-write pattern, see Granting, changing, and revoking access.

Example: Simple policy

Consider the following example policy that binds a principal to a role:

{
  "bindings": [
    {
      "members": [
        "user:jie@example.com"
      ],
      "role": "roles/owner"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

In the example above, jie@example.com is granted the Owner basic role without any conditions. This role gives jie@example.com almost unlimited access.

Example: Policy with multiple role bindings

Consider the following example policy that contains more than one role binding. Each role binding grants a different role:

{
  "bindings": [
    {
      "members": [
        "user:jie@example.com"
      ],
      "role": "roles/resourcemanager.organizationAdmin"
    },
    {
      "members": [
        "user:raha@example.com",
        "user:jie@example.com"
      ],
      "role": "roles/resourcemanager.projectCreator"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

In the example above, Jie (jie@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 Jie and Raha (raha@example.com) are granted the ability to create projects via the Project Creator role (roles/resourcemanager.projectCreator). Together, these role bindings grant fine-grained access to both Jie and Raha, and Jie is granted more access than Raha.

Example: Policy with conditional role binding

Consider the following IAM policy, which binds principals to a predefined role and uses a condition expression to 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_2022",
          "description": "Expires on July 1, 2022",
          "expression":
            "request.time < timestamp('2022-07-01T00:00:00.000Z')"
      }
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 3
}

In this example, the version field is set to 3, because the policy contains a condition expression. The role binding in the policy is conditional; it grants the role to the Google group prod-dev@example.com and the service account prod-dev-example@appspot.gserviceaccount.com, but only until July 1, 2022.

For details about the features that each policy version supports, see Policy versions on this page.

Example: Policy with conditional and unconditional role bindings

Consider the following IAM policy, which contains both conditional and unconditional role bindings for the same role:

{
  "bindings": [
    {
      "members": [
        "serviceAccount:prod-dev-example@appspot.gserviceaccount.com"
       ],
       "role": "roles/appengine.deployer"
    },
    {
      "members": [
        "group:prod-dev@example.com",
        "serviceAccount:prod-dev-example@appspot.gserviceaccount.com"
      ],
      "role": "roles/appengine.deployer",
      "condition": {
        "title": "Expires_July_1_2022",
        "description": "Expires on July 1, 2022",
        "expression":
          "request.time < timestamp('2022-07-01T00:00:00.000Z')"
      }
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 3
}

In this example, the service account serviceAccount:prod-dev-example@appspot.gserviceaccount.com is included in two role bindings for the same role. The first role binding does not have a condition. The second role binding has a condition that only grants the role until July 1, 2022.

Effectively, this policy always grants the role to the service account. In IAM, conditional role bindings do not override role bindings with no conditions. If a principal is bound to a role, and the role binding does not have a condition, then the principal always has that role. Adding the principal to a conditional role binding for the same role has no effect.

In contrast, the Google group group:prod-dev@example.com is included only in the conditional role binding. Therefore, it has the role only before July 1, 2022.

Example: Policy that binds a role to a deleted principal

Consider the following example policy. This policy binds a role to a user, donald@example.com, whose account was deleted:

{
  "bindings": [
    {
      "members": [
        "deleted:user:donald@example.com?uid=123456789012345678901"
      ],
      "role": "roles/owner"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

If you create a new user named donald@example.com, the policy's role bindings for the deleted user do not apply to the new user. This behavior prevents new users from inheriting roles that were granted to deleted users. If you want to grant roles to the new user, add the new user to the policy's role bindings, as shown in Policies with deleted principals on this page.

In addition, the user's name now includes the prefix deleted: and the suffix ?uid=numeric-id, where numeric-id is the deleted user's unique numeric ID. In this example, instead of user:donald@example.com, the policy shows the identifier deleted:user:donald@example.com?uid=123456789012345678901.

Service accounts and groups have the same behavior as users. If you delete a service account or group, then view a policy that includes that principal, the deleted principal's name has the prefix deleted: and the suffix ?uid=numeric-id.

Default policies

All resources that accept IAM policies are created with default IAM policies. Most resources' default policies are empty. However, some resources' default policies automatically contain certain role bindings. For example, when you create a new project, the IAM policy for the project automatically has a role binding that grants you the Owner role (roles/owner) on the project.

These role bindings are created by the system, so the user doesn't need getIamPolicy or setIamPolicy permissions on the resource for the role bindings to be created.

To learn if a resource is created with an IAM policy, refer to the resource's documentation.

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 an 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 following:

  • The policy set on the resource
  • 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 a scenario where you grant a user, Raha, two different IAM roles at two different levels in the resource hierarchy.

To grant Raha a role at the organization level, you set the following policy on your organization:

{
  "bindings": [
    {
      "members": [
        "user:raha@example.com"
      ],
      "role": "roles/storage.objectViewer"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

This policy grants Raha the Storage Object Viewer role (roles/storage.objectViewer), which contains get and list permissions for projects and Cloud Storage objects. Because you set the policy on your organization, Raha can use these permissions for all projects and all Cloud Storage objects in your organization.

To grant Raha a role at the project level, you set the following policy on the project myproject-123:

{
  "bindings": [
    {
      "members": [
        "user:raha@example.com"
      ],
      "role": "roles/storage.objectCreator"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

This policy grants Raha the Storage Object Creator role (roles/storage.objectCreator), which lets them create Cloud Storage objects. Because you set the policy on myproject-123, Raha can create Cloud Storage objects only in myproject-123.

Now that there are two role bindings that grant Raha access to the target Cloud Storage objects under myproject-123, the following policies apply:

  • A policy at the organization level grants the ability to list and get all Cloud Storage objects under this organization.
  • A policy at the project level, for the project myproject-123, grants the ability to create objects within that project.

The table below summarizes Raha'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 Raha 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, IAM might 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 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 IAM policy specifies a version field as part of the policy's metadata. Consider the highlighted portion below:

{
  "bindings": [
    {
      "members": [
        "user:jie@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 role bindings. The newer version can 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

IAM policies can use the following policy versions:

Version Description
1 The first version of the IAM syntax schema for policies. Supports binding one role to one or more principals. Does not support conditional role bindings.
2 Reserved for internal use.
3 Introduces the condition field in the role binding, which constrains the role binding via context-based and attribute-based rules. For more information, see the overview of IAM Conditions.

Specifying a policy version when getting a policy

For the REST API and client libraries, when you get an IAM policy, we recommend that you specify a policy version in the request. When a request specifies a policy version, IAM assumes that the caller is aware of the features in that policy version and can handle them correctly.

If the request does not specify a policy version, IAM assumes that the caller wants a version 1 policy.

When you get a policy, IAM checks the policy version in the request, or the default version if the request did not specify a version. IAM also checks the policy for fields that are not supported in a version 1 policy. It uses this information to decide what type of response to send:

  • If the policy does not contain any conditions, then IAM always returns a version 1 policy, regardless of the version number in the request.
  • If the policy contains conditions, and the caller requested a version 3 policy, then IAM returns a version 3 policy that includes the conditions. For an example, see scenario 1 on this page.
  • If the policy contains conditions, and the caller requested a version 1 policy or did not specify a version, then IAM returns a version 1 policy.

    For role bindings that include a condition, IAM appends the string _withcond_ to the role name, followed by a hash value; for example, roles/iam.serviceAccountAdmin_withcond_2b17cc25d2cd9e2c54d8. The condition itself is not present. For an example, see scenario 2 on this page.

This behavior prevents issues with older client libraries that are not aware of conditional role bindings. For details, see Client library support for policy versions on this page.

Scenario 1: Policy version that fully supports IAM Conditions

Suppose you call the following REST API method to get the IAM policy for a project:

POST https://cloudresourcemanager.googleapis.com/v1/projects/project-id:getIamPolicy

The request body contains the following text:

{
  "options": {
    "requestedPolicyVersion": 3
  }
}

The response contains the project's IAM policy. If the policy contains at least one conditional role binding, its version field is set to 3:

{
  "bindings": [
    {
      "members": [
        "user:user@example.com"
      ],
      "role": "roles/iam.securityReviewer",
      "condition": {
          "title": "Expires_July_1_2022",
          "description": "Expires on July 1, 2022",
          "expression": "request.time < timestamp('2022-07-01T00:00:00.000Z')"
      }
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 3
}

If the policy does not contain conditional role bindings, its version field is set to 1, even though the request specified version 3:

{
  "bindings": [
    {
      "members": [
        "user:user@example.com"
      ],
      "role": "roles/iam.securityReviewer",
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 1
}

Scenario 2: Policy version with limited support for IAM Conditions

Suppose you call the following REST API method to get the IAM policy for a project:

POST https://cloudresourcemanager.googleapis.com/v1/projects/project-id:getIamPolicy

The request body is empty; it does not specify a version number. As a result, IAM uses the default policy version, 1.

The policy contains a conditional role binding. Because the policy version is 1, the condition does not appear in the response. To indicate that the role binding uses a condition, IAM appends the string _withcond_ to the role name, followed by a hash value:

{
  "bindings": [
    {
      "members": [
        "user:user@example.com"
      ],
      "role": "roles/iam.securityReviewer_withcond_58e135cabb940ad9346c"
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 1
}

Specifying a policy version when setting a policy

When you set an IAM policy, we recommend that you specify a policy version in the request. When a request specifies a policy version, IAM assumes that the caller is aware of the features in that policy version and can handle them correctly.

If the request does not specify a policy version, IAM allows only the fields that can appear in a version 1 policy. As a best practice, do not change conditional role bindings in a version 1 policy; because the policy does not show the condition for each role binding, you do not know when or where the role binding is actually granted. Instead, get the version 3 representation of the policy, which shows the condition for each role binding, and use that representation to update the role bindings.

Scenario: Policy versions in requests and responses

Suppose you use the REST API to get an IAM policy, and you specify version 3 in the request. The response contains the following policy, which uses version 3:

{
  "bindings": [
    {
      "members": [
        "user:raha@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
}

You decide that raha@example.com should have the Storage Admin role (roles/storage.admin) throughout the week, not just on weekdays. You remove the condition from the role binding and send a REST API request to set the policy; once again, you specify version 3 in the request:

{
  "bindings": [
    {
      "members": [
        "user:raha@example.com"
      ],
      "role": "roles/storage.admin"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 3
}

The response contains the updated policy:

{
  "bindings": [
    {
      "members": [
        "user:raha@example.com"
      ],
      "role": "roles/storage.admin"
    }
  ],
  "etag": "BwWd8I+ZUAQ=",
  "version": 1
}

The policy in the response uses version 1, even though the request specified version 3, because the policy uses only fields that are supported in a version 1 policy.

Client library support for policy versions

Some client libraries for Google Cloud support only version 1 policies. If your client library does not support later policy versions, you cannot use features that are available only in later versions. For example, IAM Conditions requires support for policy version 3.

If you use IAM features that are not available in version 1 policies, such as IAM Conditions, use a client library that supports that policy version and sets it correctly in the request.

The following Google API Client Libraries for IAM support policy version 3:

Language Versions that support policy version 3
C# Google.Apis >=v1.41.1
Go google-api-go-client >=v0.10.0
Java
Node.js googleapis >=v43.0.0
PHP google/apiclient >=v2.4.0
Python google-api-python-client >=v1.7.11
Ruby google-api-client >=v0.31.0

You can use these client libraries to manage version 3 IAM policies on resources for the following services:

  • IAM
  • Cloud KMS
  • Cloud Storage
  • Compute Engine
  • Resource Manager

Other client libraries, including the Google Cloud Client Libraries, support only version 1 policies.

gcloud support for policy versions

You can manage version 3 IAM policies with the gcloud tool. To update to the latest version, run gcloud components update.

Policies with deleted principals

If a role binding in a policy includes a deleted principal, and you add a role binding for a new principal with the same name, the role binding is always applied to the new principal.

For example, consider this policy that includes a role binding to a deleted user, donald@example.com, and a deleted service account, my-service-account@project-id.iam.gserviceaccount.com:

{
  "bindings": [
    {
      "members": [
        "deleted:serviceAccount:my-service-account@project-id.iam.gserviceaccount.com?uid=123456789012345678901",
        "deleted:user:donald@example.com?uid=234567890123456789012"
      ],
      "role": "roles/owner"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

Suppose you create a new user that is also named donald@example.com, and you want to bind the new user to the Project Creator role (roles/resourcemanager.projectCreator), which enables users to create Google Cloud projects. To bind the new user, update the policy as shown in this example:

{
  "bindings": [
    {
      "members": [
        "deleted:serviceAccount:my-service-account@project-id.iam.gserviceaccount.com?uid=123456789012345678901",
        "deleted:user:donald@example.com?uid=234567890123456789012"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "user:donald@example.com"
      ],
      "role": "roles/resourcemanager.projectCreator"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

To make it easier to audit your IAM policies, you can also remove the deleted user from the role binding to the Owner role:

{
  "bindings": [
    {
      "members": [
        "deleted:serviceAccount:my-service-account@project-id.iam.gserviceaccount.com?uid=123456789012345678901"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "user:donald@example.com"
      ],
      "role": "roles/resourcemanager.projectCreator"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

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 principals 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 might 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.

What's next