Understanding policies

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 the version field is explained in more detail in policy versions section.

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, under myproject-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 condition field in the role binding, which further constrains the role binding via context-based and attribute-based rules. See Conditions Overview for more information.

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:

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:

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 a getIamPolicy() or setIamPolicy() 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.

Oliko tästä sivusta apua? Kerro mielipiteesi

Palautteen aihe:

Tämä sivu
Cloud IAM Documentation