Principal access boundary policies

Principal access boundary (PAB) policies let you restrict the resources that principals can access.

For example, you can use principal access boundary policies to prevent your principals from accessing resources in other organizations, which can help prevent phishing attacks or data exfiltration.

To learn about the other types of access control policies that Identity and Access Management (IAM) offers, see Policy types.

How principal access boundary policies work

By default, principals are eligible to access any Google Cloud resource. This means that if a principal has a permission on the resource and isn't denied that permission, then they can use that permission to access the resource.

With principal access boundary policies, you can restrict the resources that a principal is eligible to access. If a principal access boundary policy makes a principal ineligible to access a resource, then their access to that resource is limited, regardless of the roles they've been granted.

When principals try to access resources that they aren't eligible to access, principal access boundary policies can block some, but not all, Identity and Access Management (IAM) permissions. To learn more about which permissions are blocked, see Permissions that principal access boundary can block.

Principal access boundary policies are made up of principal access boundary rules. Each principal access boundary rule defines a set of resources that the affected principals are eligible to access. You can create up to 1000 principal access boundary policies in your organization.

After you create a principal access boundary policy, you create a policy binding to apply the policy to a set of principals.

A principal can be subject to one or more principal access boundary policies. Each principal is only eligible to access the resources listed in those policies. For all other resources, the principal's access to that resource is limited, even if you grant roles to the principal on that resource.

Because principal access boundary policies are associated with principals and not with resources, you can use them to prevent principals from accessing resources that you don't own. For example, consider the following scenario:

Principal access boundary policy preventing access to a resource

Principal access boundary policy preventing access to a resource

  • The principal Tal (tal@altostrat.com) is part of the Google Workspace organization altostrat.com.
  • Tal is granted the Storage Admin (roles/storage.admin) role on a Cloud Storage bucket in a different organization, cymbalgroup.com. This role contains the storage.objects.get permission, which is required to view objects in the bucket.
  • There are no deny policies in cymbalgroup.com that prevent Tal from using the storage.objects.get permission.

With just allow and deny policies, altostrat.com can't prevent Tal from viewing objects in this external bucket. No altostrat.com principals have permission to edit the bucket's allow policy, so they can't revoke Tal's role. They also don't have permission to create any deny policies in cymbalgroup.com, so they can't use a deny policy to prevent Tal from accessing the bucket.

However, with principal access boundary policies, altostrat.com administrators can ensure that Tal can't view objects in the cymbalgroup.com bucket, or any bucket outside of altostrat.com. To do this, the administrators can create a principal access boundary policy saying that altostrat.com principals are only eligible to access resources in altostrat.com. Then, they can create a policy binding to attach this policy to all principals in the organization altostrat.com. With such a policy in place, Tal won't be able to view objects in the cymbalgroup.com bucket, even though they're granted the Storage Admin role on the bucket.

Fail-open evaluation

During the principal access boundary policy Preview release, principal access boundary policies fail open. This means that, if IAM can't evaluate a principal access boundary policy, it ignores the principal access boundary policy and proceeds to evaluate the relevant allow and deny policies.

Permissions that principal access boundary policies block

When principals try to access a resource that they aren't eligible to access, principal access boundary policies prevent them from using some, but not all, Identity and Access Management (IAM) permissions to access the resource.

If a principal access boundary policy blocks a permission, then IAM enforces principal access boundary policies for that permission. In other words, it prevents any principals that aren't eligible to access a resource from using that permission to access the resource.

If a principal access boundary policy doesn't block a permission, then principal access boundary policies have no effect on whether principals can use the permission.

For example, imagine that a principal, Lee (lee@example.com), is granted the Dataflow Developer role (roles/dataflow.developer). This role includes the dataflow.jobs.snapshot permission, which lets Lee take snapshots of Dataflow jobs. Lee is also subject to a principal access boundary policy that makes them ineligible to access resources outside of example.com. However, if principal access boundary policies don't block the dataflow.jobs.snapshot permission, then Lee can still take snapshots of Dataflow jobs in organizations outside of example.com.

The permissions that a principal access boundary policy blocks depends on the principal access boundary enforcement version.

Principal access boundary enforcement versions

Each principal access boundary policy specifies an enforcement version, which identifies a predefined list of IAM permissions that the principal access boundary policy can block. You specify the enforcement version when you create or update a principal access boundary policy. If you don't specify an enforcement version, IAM uses the latest enforcement version, and will continue to use that version until you update it.

Periodically, IAM adds new principal access boundary enforcement versions that can block additional permissions. Each new version can also block all of the permissions in the previous version.

To block the permissions in a new enforcement version, you must update your principal access boundary policies to use the new version. If you want the enforcement version to update automatically as new versions are released, you can use the value latest when creating the policy. However, we don't recommend using this value, because it might cause principals to lose access to resources unexpectedly.

For a full list of the permissions that each enforcement version blocks, see Permissions that principal access boundary policies block.

Bind principal access boundary policies to principal sets

To bind a principal access boundary policy to a principal set, you create a policy binding that specifies both the principal access boundary policy that you want to enforce and the principal set that you want to enforce it for. After you bind the policy to a principal set, the principals in that principal set can access only the resources that are included in the principal access boundary policy's rules.

You can bind a principal access boundary policy to any number of principal sets. Each principal set can have up to 10 principal access boundary policies bound to it.

To learn how to manage principal access boundary policies, see Create and apply principal access boundary policies.

Supported principal sets

The following table lists the types of principal sets that you can bind principal access boundary policies to. Each row contains the following:

  • The type of principal set
  • The principals in that type of principal set
  • The format of IDs for that type of principal set
  • The Resource Manager resource (project, folder, or organization) that parents policy bindings for that type of principal set
Principal set Details Policy bindings' parent resource
Workforce identity pool

Contains all identities in the specified workforce identity pool.

Format: //iam.googleapis.com/locations/global/workforcePools/WORKFORCE_POOL_ID

The organization that owns the workforce identity pool
Workload identity pool

Contains all identities in the specified workload identity pool.

Format: //iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/WORKLOAD_POOL_ID

The project that owns the workload identity pool
Google Workspace domain

Contains all identities in the specified Google Workspace domain.

Format: //iam.googleapis.com/locations/global/workspace/WORKSPACE_ID

To learn how to find your workspace ID, see Find your customer ID.

The organization that owns the Google Workspace domain
Project's principal set

Contains all service accounts and workload identity pools in the specified project.

Format: //cloudresourcemanager.googleapis.com/projects/PROJECT_ID

The project
Folder's principal set

Contains all service accounts and all workload identity pools in any project in the specified folder.

Format: //cloudresourcemanager.googleapis.com/folders/FOLDER_ID

The folder
Organization's principal set

Contains the following identities:

  • All identities in all domains associated with your Google Workspace customer ID
  • All workforce identity pools in your organization
  • All service accounts and workload identity pools in any project in the organization

Format: //cloudresourcemanager.googleapis.com/organizations/ORGANIZATION_ID

The organization

Conditional policy bindings for principal access boundary policies

You can use condition expressions in policy bindings for principal access boundary policies to further refine which principals the policy applies to.

Condition expressions for policy bindings consist of one or more statements joined by up to 10 logical operators (&&, ||, or !). Each statement expresses an attribute-based control rule that applies to the policy binding, and ultimately determines whether the policy applies.

You can use the principal.type and principal.subject attributes in conditions for policy bindings. No other attributes are supported in conditions for policy bindings.

  • The principal.type attribute indicates what type of principal is in the request—for example, service accounts, or identities in a workload identity pool. You can use conditions with this attribute to control which types of principals a principal access boundary policy applies to.

    For example, if you add the following condition expression to a binding for a principal access boundary policy, then the policy only applies to service accounts:

    principal.type == 'iam.googleapis.com/ServiceAccount'
    
  • The principal.subject attribute indicates the identity of the principal in the request—for example, cruz@example.com. You can use conditions with this attribute to control exactly which principals are subject to a principal access boundary policy.

    For example, if you add the following condition expression to a binding for a principal access boundary policy, then the policy won't apply for the user special-admin@example.com:

    principal.subject != 'special-admin@example.com'
    

To learn more about the values that you can use for these conditions, see the conditions attribute reference.

Policy interactions

IAM evaluates each principal access boundary policy in combination with your allow and deny policies, and with your other principal access boundary policies. All of these policies are used to determine whether a principal can access a resource.

Interaction with other policy types

When a principal tries to access a resource, IAM evaluates all relevant principal access boundary, allow, and deny policies to see if the principal is allowed to access the resource. If any one of these policies indicates that the principal shouldn't be able to access the resource, IAM prevents access.

As a result, if a principal access boundary policy would prevent a principal from accessing a resource, then IAM prevents them from accessing that resource, regardless of the allow and deny policies attached to the resource.

Additionally, principal access boundary policies alone don't give principals access to resources. While principal access boundary policies can make a principal eligible to access a resource, only allow policies can actually grant the principal access to the resource.

To learn more about IAM policy evaluation, see Policy evaluation.

Interaction between principal access boundary policies

If multiple principal access boundary policies apply to a principal, then the principal is eligible to access all resources in those principal access boundary policies. This means that, if a principal is already subject to a principal access boundary policy, you can't use a new principal access boundary policy to reduce the resources that they're eligible to access.

Instead, to reduce the resources that a principal is eligible to access, you need to do the following:

  1. Create a new principal access boundary policy
  2. Bind it to a principal set that contains the principal
  3. Exempt the principal from the existing principal access boundary policy.

For example, imagine that you have an organization, example.com. You don't want principals in example.com to access resources outside of the organization, so you create a principal access boundary policy that makes principals eligible to access resources in example.com and bind it to the principal set for the organization.

Now imagine that you have a project, dev-project, with the project number 123456789012. Because of the way that principal sets for Resource Manager resources are structured, principals in this project are included in the following principal sets:

  • The principal set for dev-project
  • The principal set for example.com

You decide that you don't want principals in this project to be eligible to access all resources in example.com—you only want them to be eligible to access resources in dev-project. So, you create a new principal access boundary policy that makes principals eligible to access resources in dev-project and bind it to the principal set for dev-project.

However, just creating this policy doesn't make principals in dev-project ineligible to access other resources in example.com. This is because these principals are still subject to the principal access boundary policy bound to example.com, which makes them eligible to access all resources in example.com. To make the principals in dev-project ineligible to access other resources in example.com, you must ensure that they aren't subject to the principal access boundary policy bound to the organization's principal set.

To do this, you add the following condition to the policy binding for the principal access boundary policy bound to the organization:

  "condition": {
    "title": "Exempt principals in dev-project principal set",
    "expression": "!principal.subject.startsWith('principal://iam.googleapis.com/projects/123456789012') && !principal.subject.endsWith('dev-project.iam.gserviceaccount.com')"
  }

The first expression in the condition matches all workload identity pool identities in dev-project, and the second expression matches all service accounts in dev-project.

After you add this condition to the policy binding, principals in dev-project are no longer eligible to access all resources in example.com—instead, they're only eligible to access resources in dev-project.

You can also use additional principal access boundary policies to increase the resources that principals are eligible to access. For example, if you decide that you want the principals in dev-project to also be eligible to access resources in staging-project, you can create a new principal access boundary policy that makes principals eligible to access resources in staging-project and bind it to the principal set for dev-project. Now, principals in dev-project are eligible to access resources in both dev-project and staging-project.

To learn how to create principal access boundary policies and bind them to principal sets, see Create and apply principal access boundary policies. To learn how to update existing principal access boundary policies, see Edit principal access boundary policies.

Policy inheritance

Principal access boundary policies are attached to principal sets, not Resource Manager resources. As a result, they aren't inherited through the resource hierarchy in the same way that allow and deny policies are.

However, principal sets for Resource Manager parent resources—that is, folders and organizations—always include all of the principals in their descendants' principal sets. So, for example, if a principal is included in a project's principal set, it is also included in the principal sets of any parent folders or organizations.

For example, consider an organization, example.com. This organization is associated with the domain example.com, and has the following Resource Manager resources:

Resource hierarchy for example.com

Resource hierarchy for example.com

  • An organization, example.com
  • A project, project-1, that's a child of the organization
  • A folder, folder-a, that's a child of the organization
  • Two projects, project-2 and project-3, that are children of folder-a

These resources' principal sets contain the following identities:

Principal set Google Workspace identities in the example.com domain Workforce identity federation pools in example.com Service accounts and workload identity pools in project-1 Service accounts and workload identity pools in project-2 Service accounts and workload identity pools in project-3
Principal set for example.com
Principal set for folder-a
Principal set for project-1
Principal set for project-2
Principal set for project-3

As a result, the following principals are affected by the following principal access boundary policies:

  • A Google Workspace identity in the example.com domain is in the principal set for example.com and will be affected by principal access boundary policies bound to that principal set.

  • A service account in project-1 is in the principal sets for project-1 and example.com and will be affected by principal access boundary policies bound to either of those principal sets.

  • A service account in project-3 is in the principal sets for project-3, folder-a, and example.com, and will be affected by principal access boundary policies bound to any of those principal sets.

Principal access boundary policies and cached resources

Certain Google Cloud services cache publicly visible resources. For example, Cloud Storage caches objects that are publicly readable.

Whether principal access boundary can prevent ineligible principals from viewing a publicly visible resource depends on whether the resource is cached:

  • If the resource is cached, then principal access boundary can't prevent principals from viewing the resource
  • If the resource isn't cached, then principal access boundary prevents ineligible principals from viewing the resource

In all cases, principal access boundary policies prevent ineligible principals from modifying or deleting publicly visible resources.

Structure of a principal access boundary policy

A principal access boundary policy is a collection of metadata and principal access boundary policy details. The metadata provides information like the policy name and when the policy was created. The policy details define what the policy does—for example, the resources that affected principals are eligible to access.

For example, the following principal access boundary policy makes the principals who are subject to the policy eligible to access the resources in the organization with the ID 0123456789012.

{
  "name": "organizations/0123456789012/locations/global/principalAccessBoundaryPolicies/example-policy",
  "uid": "puid_0123456789012345678",
  "etag": "W/\"Gh/PcTdJD/AWHUhPW45kdw==\"",
  "displayName": "Example policy",
  "annotations": {
    "example-key": "example-value"
  },
  "createTime": "2024-01-02T15:01:23Z",
  "updateTime": "2024-01-02T15:01:23Z",
  "details": {
    "rules": [
      {
        "description": "Example principal access boundary policy rule",
        "resources": [
          "//cloudresourcemanager.googleapis.com/organizations/0123456789012"
        ],
        "effect": "ALLOW"
      }
    ],
    "enforcementVersion": "1"
  }
}

The following sections describe the fields in a principal access boundary policy's metadata and details.

Metadata

Principal access boundary policies contain the following metadata:

  • name: The name of the principal access boundary policy. This name has the format organizations/ORGANIZATION_ID/locations/global/principalAccessBoundaryPolicies/PAB_POLICY_ID, where ORGANIZATION_ID is the numeric ID of the organization where the principal access boundary policy was created and PAB_POLICY_ID is the principal access boundary policy's alphanumeric ID.
  • uid: A unique ID assigned to the principal access boundary policy.
  • etag: An identifier for the policy's current state. This value changes when you update the policy. To prevent conflicting updates, the etag value must match the value that is stored in IAM. If the etag values don't match, the request fails.
  • displayName: A human-readable name for the principal access boundary policy.
  • annotations: Optional. A list of user-defined key-value pairs. You can use these annotations to add extra metadata to the policy—for example, who created the policy, or whether the policy was deployed by an automated pipeline. For more information about annotations, see Annotations.
  • createTime: The time when the principal access boundary policy was created.
  • updateTime: The time when the principal access boundary policy was last updated.

Details

Each principal access boundary policy contains a details field. This field contains the principal access boundary policy rules and enforcement version:

  • rules: A list of principal access boundary rules, which define the resources that affected principals are eligible to access. Each rule contains the following fields:

    • description: A human-readable description for the rule.
    • resources: A list of Resource Manager resources (projects, folders, and organizations) that you want principals to be eligible to access. Any principal that is subject to this policy is eligible to access these resources.

      Each principal access boundary policy can reference a maximum of 500 resources across all rules in the policy.

    • effect: The relationship that principals have with the resources listed in the resources field. The only effect that you can specify in principal access boundary rules is "ALLOW". This relationship makes the principals eligible to access the resources listed in the rule.

  • enforcementVersion: The enforcement version that IAM uses when enforcing the policy. The principal access boundary policy version determines which permissions the principal access boundary policy can block.

    For more information about principal access boundary policy versions, see Principal access boundary enforcement versions on this page.

Structure of a policy binding

A policy binding for a principal access boundary policy contains the name of a policy, the name of the principal set to bind the policy to, and metadata describing the policy binding. It can also contain conditions that modify the exact principals that the policy applies to.

For example, the following policy binding binds the policy example-policy to all principals in the example.com organization, which has the ID 0123456789012. The policy binding also contains a condition that prevents the policy from being enforced for the principal super-admin@example.com.

{
  "name": "organizations/0123456789012/locations/global/policyBindings/example-policy-binding",
  "uid": "buid_01234567890123456789", 
  "etag": "W/\"cRMdDXbT82aLuZlvoL9Gqg==\"",
  "displayName": "Example policy binding",
  "annotations": {
    "example-key": "example-value"
  },
  "target": {
    "principalSet": "//cloudresourcemanager.googleapis.com/organizations/0123456789012"
  },
  "policyKind": "PRINCIPAL_ACCESS_BOUNDARY",
  "policy": "organizations/0123456789012/locations/global/principalAccessBoundaryPolicies/example-policy",
  "policyUid": "puid_0123456789012345678",
  "condition": {
    "title": "Exempt principal",
    "description": "Don't enforce the policy for super-admin@example.com",
    "expression": "principal.subject != 'super-admin@example.com'"
  },
  "createTime": "2024-01-02T17:00:16Z",
  "updateTime": "2024-01-02T17:00:16Z"
}

Each policy binding contains the following fields:

  • name: The name of the policy binding. This name has the format RESOURCE_TYPE/RESOURCE_ID/locations/global/policyBindings/BINDING_ID, where RESOURCE_TYPE/RESOURCE_ID is the type and ID of the policy binding's parent resource and BINDING_ID is the policy binding's alphanumeric ID.
  • uid: A unique ID assigned to the policy binding.
  • etag: An identifier for the policy's current state. This value changes when you update the policy. To prevent conflicting updates, the etag value must match the value that is stored in IAM. If the etag values don't match, the request fails.
  • displayName: A human-readable name for the policy binding.
  • annotations: Optional. A list of user-defined key-value pairs. You can use these annotations to add extra metadata to the policy binding—for example, who created the policy binding, or whether the policy binding was deployed by an automated pipeline. For more information about annotations, see Annotations.
  • target: The principal set to bind the policy to. The value has the format {"principalSet": PRINCIPAL_SET}, where PRINCIPAL_SET is the ID of the principal set that you want to bind the policy to.

    Each target can have up to 10 policies bound to it.

  • policyKind: The type of policy that the policy binding references. For policy bindings for principal access boundary policies, this value is always PRINCIPAL_ACCESS_BOUNDARY.

  • policy: The principal access boundary policy to bind to the target principal set.

  • policyUid: A unique ID assigned to the principal access boundary policy referenced in the policy field.

  • condition: Optional. A logic expression that affects which principals IAM enforces the policy for. If the condition evaluates to true or cannot be evaluated, Identity and Access Management enforces the policy for the principal making the request. If the condition evaluates to false, Identity and Access Management doesn't enforce the policy for the principal. For more information, see Principal access boundary and conditions on this page.

  • createTime: The time when the policy binding was created.

  • updateTime: The time when the policy binding was last updated.

Use cases

The following are common situations where you might want to use principal access boundary policies, and examples of the principal access boundary policies and policy bindings that you might create in each situation. To learn how to create principal access boundary policies and bind them to principal sets, see Create and apply principal access boundary policies.

Restrict principals to resources in your organization

You can use principal access boundary policies to ensure that principals in your organization are only eligible to access resources within your organization.

For example, imagine that you want to ensure that all principals in the organization example.com are only eligible to access resources within example.com. The principals that are in example.com include all identities in the example.com domain, all workforce identity pools in example.com, and all service accounts and workload identity pools in any project in example.com.

You don't have any principal access boundary policies that apply to any of the principals in your organization. As a result, all principals are eligible to access all resources.

To make principals ineligible to access resources outside of example.com, you create a principal access boundary policy that makes principals eligible to access resources in example.com:

{
  "name": "organizations/0123456789012/locations/global/principalAccessBoundaryPolicies/example-org-only",
  "displayName": "Boundary for principals in example.org",
  "details": {
    "rules": [
      {
        "description": "Principals are only eligible to access resources in example.org",
        "resources": [
            "//cloudresourcemanager.googleapis.com/organizations/0123456789012"
        ],
        "effect": "ALLOW"
      }
    ],
    "enforcementVersion": "1"
  }
}

Then, you create a policy binding to bind this policy to the principal set:

{
  "name": "organizations/0123456789012/locations/global/policyBindings/example-org-only-binding",
  "displayName": "Bind policy to all principals in example.com",
  "target": {
    "principalSet": "//cloudresourcemanager.googleapis.com/organizations/0123456789012"
  },
  "policyKind": "PRINCIPAL_ACCESS_BOUNDARY",
  "policy": "organizations/0123456789012/locations/global/principalAccessBoundaryPolicies/example-org-only"
}

Now, all principals in example.com are only eligible to access resources in example.com. They're prevented from using permissions that are blocked by the principal access boundary policy to access resources outside of example.com, even if they have those permissions on those resources.

Restrict service accounts to resources in a single project

You can use principal access boundary policies to ensure that service accounts in a specific project are only eligible to access resources within that project.

For example, imagine that you have a project, example-dev. You create a few service accounts in the project to act as the identities for the Compute Engine instances in the project. However, you only want these service accounts to be able to access resources within the project.

You have a principal access boundary policy that makes all principals in your organization, including the service accounts in example-dev, eligible to access resources in example.com. To see what this type of policy looks like, see Restrict principals to resources in your organization.

To make the service accounts in example-dev ineligible to access resources outside of example-dev, you first create a principal access boundary policy that makes principals eligible to access resources in example-dev

{
  "name": "organizations/0123456789012/locations/global/principalAccessBoundaryPolicies/example-dev-only",
  "displayName": "Boundary for principals in example-dev",
  "details": {
    "rules": [
      {
        "description": "Principals are only eligible to access resources in example-dev",
        "resources": [
          "//cloudresourcemanager.googleapis.com/projects/example-dev"
        ],
        "effect": "ALLOW"
      }
    ],
    "enforcementVersion": "1"
  }
}

Then, you create a policy binding to bind this policy to all principals in example-dev, and add a condition so that the policy binding only applies for service accounts:

{
  "name": "organizations/0123456789012/locations/global/policyBindings/example-dev-only-binding",
  "displayName": "Bind policy to all service accounts in example-dev",
  "target": {
    "principalSet": "//cloudresourcemanager.googleapis.com/projects/example-dev"
  },
  "policyKind": "PRINCIPAL_ACCESS_BOUNDARY",
  "policy": "organizations/0123456789012/locations/global/principalAccessBoundaryPolicies/example-dev-only",
  "condition": {
    "title": "Only service accounts",
    "description": "Only enforce the policy if the principal in the request is a service account",
    "expression": "principal.type == 'iam.googleapis.com/ServiceAccount'"
  }
}

However, this policy on its own doesn't restrict the service accounts' eligibility. This is because there's an existing principal access boundary policy that makes all principals in example.com eligible to access all resources in example.com. Principal access boundary policies are additive, so the service accounts in example-dev are still eligible to access all resources in example.com.

To ensure that service accounts in example-dev are only eligible to access resources in example-dev, you need to add a condition to the policy binding for the existing principal access boundary policy that prevents it from being enforced for the service accounts in example-dev:

{
  "name": "organizations/0123456789012/locations/global/policyBindings/example-org-only-binding",
  "displayName": "Bind policy to all principals in example.com",
  "target": {
    "principalSet": "//cloudresourcemanager.googleapis.com/organizations/0123456789012"
  },
  "policyKind": "PRINCIPAL_ACCESS_BOUNDARY",
  "policy": "organizations/0123456789012/locations/global/principalAccessBoundaryPolicies/example-org-only",
  "condition": {
    "title": "Exempt example-dev service accounts",
    "description": "Don't enforce the policy for service accounts in the example-dev project",
    "expression": "principal.type == 'iam.googleapis.com/ServiceAccount' && principal.subject.endsWith('example-dev.iam.gserviceaccount.com')"
  }
}

Now, the service accounts in example-dev are only eligible to access resources in example-dev. They're prevented from using permissions that are blocked by the principal access boundary policy to access resources outside of example-dev, even if they have those permission on those resources.

What's next