Deny access to resources

This page explains how to deny principals access by preventing them from using specific Identity and Access Management (IAM) permissions.

In IAM, you deny access with deny policies. Each deny policy is attached to a Google Cloud organization, folder, or project. A deny policy contains deny rules, which identify principals and list the permissions that the principals cannot use.

Deny policies are separate from allow policies, also known as IAM policies. An allow policy provides access to resources by granting IAM roles to principals.

You can manage deny policies with the Google Cloud CLI or the IAM v2beta REST API.

Before you begin

Required roles

To get the permissions that you need to manage deny policies, ask your administrator to grant you the following IAM roles on the organization:

  • To view deny policies: Deny Reviewer (roles/iam.denyReviewer)
  • To view, create, update, and delete deny policies: Deny Admin (roles/iam.denyAdmin)

For more information about granting roles, see Manage access.

These predefined roles contain the permissions required to manage deny policies. To see the exact permissions that are required, expand the Required permissions section:

Required permissions

  • To view deny policies:
    • iam.denypolicies.get
    • iam.denypolicies.list
  • To create, update, and delete deny policies:
    • iam.denypolicies.create
    • iam.denypolicies.delete
    • iam.denypolicies.get
    • iam.denypolicies.update

You might also be able to get these permissions with custom roles or other predefined roles.

Identify permissions to deny

Before you create a deny policy, you must decide which permissions you want to deny, and which principals should be denied these permissions.

You can deny a subset of all IAM permissions. For a list of permissions that you can deny, see Permissions supported in deny policies.

You manage deny policies with the v2beta REST API, which requires a special format for permission names. For example, the permission to create an IAM custom role is named as follows:

  • v1 API: iam.roles.create
  • v2beta API: iam.googleapis.com/roles.create

Identify the attachment point

Each deny policy is attached to an organization, folder, or project. To work with deny policies, you need an identifier for the resource that the deny policy is attached to, which is called the attachment point. This identifier uses one of the formats in the following table:

Attachment point format
Organization

cloudresourcemanager.googleapis.com/organizations/ORG_ID
Replace ORG_ID with the numeric organization ID. For the REST API, URL-encode the entire value.

Example for the gcloud CLI:
cloudresourcemanager.googleapis.com/organizations/123456789012

Example for the REST API:
cloudresourcemanager.googleapis.com%2Forganizations%2F123456789012

Folder

cloudresourcemanager.googleapis.com/folders/FOLDER_ID
Replace FOLDER_ID with the numeric folder ID. For the REST API, URL-encode the entire value.

Example for the gcloud CLI:
cloudresourcemanager.googleapis.com/folders/987654321098

Example for the REST API:
cloudresourcemanager.googleapis.com%2Ffolders%2F987654321098

Project

cloudresourcemanager.googleapis.com/projects/PROJECT_ID
Replace PROJECT_ID with the alphanumeric or numeric project ID. For the REST API, URL-encode the entire value.

Example for the gcloud CLI:
cloudresourcemanager.googleapis.com/projects/my-project

Example for the REST API:
cloudresourcemanager.googleapis.com%2Fprojects%2Fmy-project

Create a deny policy

You can add deny policies to organizations, folders, and projects. Each of these resources can have up to 5 deny policies.

Deny policies contain deny rules, which specify the following:

  • The permissions to deny.
  • The principals that are denied those permissions.
  • Optional: Principals that are exempt from the denial of permissions.

    For example, you can deny a permission to a group, but exempt specific users who belong to that group.

  • Optional: A condition expression that specifies when the principals cannot use the permissions, based on the resource's tags.

Deny policies are inherited through the resource hierarchy. For example, if you deny a permission at the organization level, that permission will also be denied on the folders and projects within that organization, and on the service-specific resources within each project.

Deny policies override allow policies. If a principal is granted a role that contains a specific permission, but a deny policy says that the principal cannot use that permission, then the principal cannot use the permission.

gcloud

To create a deny policy for a resource, start by creating a JSON file that contains the policy. A deny policy uses the following format:

{
  "displayName": "POLICY_NAME",
  "rules": [
    {
      "denyRule": DENY_RULE_1
    },
    {
      "denyRule": DENY_RULE_2
    },
    {
      "denyRule": DENY_RULE_N
    }
  ]
}

Provide the following values:

  • POLICY_NAME: The display name for the deny policy.
  • DENY_RULE_1, DENY_RULE_2, ...DENY_RULE_N: The deny rules in the policy. Each deny rule can contain these fields:

    For examples of deny rules, see Common use cases.

For example, the following deny policy contains one deny rule, which denies one permission to the user lucian@example.com:

{
  "displayName": "My deny policy.",
  "rules": [
    {
      "denyRule": {
        "deniedPrincipals": [
          "principal://goog/subject/lucian@example.com"
        ],
        "deniedPermissions": [
          "iam.googleapis.com/roles.create"
        ]
      }
    }
  ]
}

Next, run the gcloud beta iam policies create command:

gcloud beta iam policies create POLICY_ID \
    --attachment-point=ATTACHMENT_POINT \
    --kind=denypolicies \
    --policy-file=POLICY_FILE

Provide the following values:

  • POLICY_ID: The identifier for the deny policy.

  • ATTACHMENT_POINT: An identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

  • POLICY_FILE: The filepath for the JSON file that contains the deny policy.

By default, if this command succeeds, it does not print any output. To print a detailed response, add the flag --format=json to the command.

For example, the following command creates a deny policy named my-deny-policy for the project my-project, using a file named policy.json:

gcloud beta iam policies create my-deny-policy \
    --attachment-point=cloudresourcemanager.googleapis.com/projects/my-project \
    --kind=denypolicies \
    --policy-file=policy.json

REST

The policies.createPolicy method creates a deny policy for a resource.

Before using any of the request data, make the following replacements:

  • ENCODED_ATTACHMENT_POINT: A URL-encoded identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

  • POLICY_ID: An identifier for the deny policy.
  • POLICY_NAME: The display name for the deny policy.
  • DENY_RULE_1, DENY_RULE_2, ...DENY_RULE_N: The deny rules in the policy. Each deny rule can contain these fields:

    For examples of deny rules, see Common use cases.

HTTP method and URL:

POST https://iam.googleapis.com/v2beta/policies/ENCODED_ATTACHMENT_POINT/denypolicies?policyId=POLICY_ID

Request JSON body:

{
  "displayName": "POLICY_NAME",
  "rules": [
    {
      "denyRule": DENY_RULE_1
    },
    {
      "denyRule": DENY_RULE_2
    },

    {
      "denyRule": DENY_RULE_N
    }
  ]
}

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy/operations/89cb3e508bf1ff01",
  "metadata": {
    "@type": "type.googleapis.com/google.iam.v2beta.PolicyOperationMetadata",
    "createTime": "2021-09-28T19:06:12.455151Z"
  },
  "response": {
    "@type": "type.googleapis.com/google.iam.v2beta.Policy",
    "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy",
    "uid": "6665c437-a3b2-a018-6934-54dd16d3426e",
    "kind": "DenyPolicy",
    "displayName": "My deny policy.",
    "etag": "MTc3NDU4MjM4OTY0MzU5MjQ5OTI=",
    "createTime": "2021-09-28T19:06:12.455151Z",
    "updateTime": "2021-09-28T22:26:21.968687Z"
    "rules": [
      {
        "denyRule": {
          "deniedPrincipals": [
            "principal://goog/subject/lucian@example.com"
          ],
          "deniedPermissions": [
            "iam.googleapis.com/roles.create"
          ]
        }
      }
    ]
  }
}

The response identifies a long-running operation. You can monitor the status of the long-running operation to find out when it's complete. For details, see Check the status of a long-running operation on this page.

List deny policies

A resource can have up to 5 deny policies. You can list all of the deny policies that are attached to a resource, then view each deny policy to see the deny rules in each policy.

gcloud

To list the deny policies for a resource, run the gcloud beta iam policies list command:

gcloud beta iam policies list \
    --attachment-point=ATTACHMENT_POINT \
    --kind=denypolicies \
    --format=json

Provide the following value:

  • ATTACHMENT_POINT: An identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

For example, the following command lists deny policies attached to an organization whose numeric ID is 123456789012:

gcloud beta iam policies list \
    --attachment-point=cloudresourcemanager.googleapis.com/organizations/123456789012 \
    --kind=denypolicies \
    --format=json

REST

The policies.listPolicies method lists the deny policies for a resource.

Before using any of the request data, make the following replacements:

  • ENCODED_ATTACHMENT_POINT: A URL-encoded identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

HTTP method and URL:

GET https://iam.googleapis.com/v2beta/policies/ENCODED_ATTACHMENT_POINT/denypolicies

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "policies": [
    {
      "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1067607927478/denypolicies/test-policy",
      "uid": "6665c437-a3b2-a018-6934-54dd16d3426e",
      "kind": "DenyPolicy",
      "displayName": "My deny policy.",
      "createTime": "2021-09-28T19:06:12.455151Z",
      "updateTime": "2021-09-28T22:26:21.968687Z"
    },
    {
      "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1067607927478/denypolicies/test-policy-2",
      "uid": "8465d710-ea20-0a08-d92c-b2a3ebf766ab",
      "kind": "DenyPolicy",
      "displayName": "My second deny policy.",
      "createTime": "2021-10-05T19:21:53.595455Z",
      "updateTime": "2021-10-05T19:21:53.595455Z"
    },
    {
      "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1067607927478/denypolicies/test-policy-3",
      "uid": "ee9f7c2f-7e8c-b05c-d4e5-e03bfb2954e0",
      "kind": "DenyPolicy",
      "displayName": "My third deny policy.",
      "createTime": "2021-10-05T19:22:26.770543Z",
      "updateTime": "2021-10-05T19:22:26.770543Z"
    }
  ]
}

View a deny policy

You can view a deny policy to see the deny rules that it contains, including the permissions that are denied and the principals who cannot use those permissions.

gcloud

To get the deny policy for a resource, run the gcloud beta iam policies get command:

gcloud beta iam policies get POLICY_ID \
    --attachment-point=ATTACHMENT_POINT \
    --kind=denypolicies \
    --format=json

Provide the following values:

  • POLICY_ID: The identifier for the deny policy.

  • ATTACHMENT_POINT: An identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

For example, the following command gets the deny policy named my-deny-policy for the project my-project and saves it in a file named policy.json:

gcloud beta iam policies get my-deny-policy \
    --attachment-point=cloudresourcemanager.googleapis.com/projects/my-project \
    --kind=denypolicies \
    --format=json \
    > ./policy.json

REST

The policies.get method gets a deny policy for a resource.

Before using any of the request data, make the following replacements:

  • ENCODED_ATTACHMENT_POINT: A URL-encoded identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

  • POLICY_ID: An identifier for the deny policy.

HTTP method and URL:

GET https://iam.googleapis.com/v2beta/policies/ENCODED_ATTACHMENT_POINT/denypolicies/POLICY_ID

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy",
  "uid": "6665c437-a3b2-a018-6934-54dd16d3426e",
  "kind": "DenyPolicy",
  "displayName": "My deny policy.",
  "etag": "MTc3NDU4MjM4OTY0MzU5MjQ5OTI=",
  "createTime": "2021-10-05T19:22:26.770543Z",
  "updateTime": "2021-10-05T19:22:26.770543Z",
  "rules": [
    {
      "denyRule": {
        "deniedPrincipals": [
          "principal://goog/subject/lucian@example.com"
        ],
        "deniedPermissions": [
          "iam.googleapis.com/roles.create"
        ]
      }
    }
  ]
}

Update a deny policy

After you create a deny policy, you can update the deny rules that it contains, as well as its display name.

To update a deny policy, use the read-modify-write pattern:

  1. Read the current version of the policy.
  2. Modify the information in the policy as needed.
  3. Write the updated policy.

Read the deny policy

gcloud

To get the deny policy for a resource, run the gcloud beta iam policies get command:

gcloud beta iam policies get POLICY_ID \
    --attachment-point=ATTACHMENT_POINT \
    --kind=denypolicies \
    --format=json

Provide the following values:

  • POLICY_ID: The identifier for the deny policy.

  • ATTACHMENT_POINT: An identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

For example, the following command gets the deny policy named my-deny-policy for the project my-project and saves it in a file named policy.json:

gcloud beta iam policies get my-deny-policy \
    --attachment-point=cloudresourcemanager.googleapis.com/projects/my-project \
    --kind=denypolicies \
    --format=json \
    > ./policy.json

REST

The policies.get method gets a deny policy for a resource.

Before using any of the request data, make the following replacements:

  • ENCODED_ATTACHMENT_POINT: A URL-encoded identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

  • POLICY_ID: An identifier for the deny policy.

HTTP method and URL:

GET https://iam.googleapis.com/v2beta/policies/ENCODED_ATTACHMENT_POINT/denypolicies/POLICY_ID

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy",
  "uid": "6665c437-a3b2-a018-6934-54dd16d3426e",
  "kind": "DenyPolicy",
  "displayName": "My deny policy.",
  "etag": "MTc3NDU4MjM4OTY0MzU5MjQ5OTI=",
  "createTime": "2021-10-05T19:22:26.770543Z",
  "updateTime": "2021-10-05T19:22:26.770543Z",
  "rules": [
    {
      "denyRule": {
        "deniedPrincipals": [
          "principal://goog/subject/lucian@example.com"
        ],
        "deniedPermissions": [
          "iam.googleapis.com/roles.create"
        ]
      }
    }
  ]
}

Modify the deny policy

To modify the deny policy, you make changes to the copy of the policy that you previously read from IAM. You can update the display name, or you can add, change, or remove deny rules. The changes do not take effect until you write the updated policy.

For example, you could add a permission to an existing deny rule:

{
  "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy",
  "uid": "6665c437-a3b2-a018-6934-54dd16d3426e",
  "kind": "DenyPolicy",
  "displayName": "My deny policy.",
  "etag": "MTc3NDU4MjM4OTY0MzU5MjQ5OTI=",
  "createTime": "2021-10-05T19:22:26.770543Z",
  "updateTime": "2021-10-05T19:22:26.770543Z",
  "rules": [
    {
      "denyRule": {
        "deniedPrincipals": [
          "principal://goog/subject/lucian@example.com"
        ],
        "deniedPermissions": [
          "iam.googleapis.com/roles.create",
          "iam.googleapis.com/roles.delete"
        ]
      }
    }
  ]
}

Write the updated deny policy

After you modify the deny policy locally, you must write the updated deny policy to IAM.

Each deny policy contains an etag field that identifies the policy version. The etag changes each time you update the policy. When you write the updated policy, the etag in your request must match the current etag stored in IAM; if the values do not match, the request fails. This feature helps prevent concurrent changes from overwriting each other.

gcloud

To update the deny policy for a resource, run the gcloud beta iam policies update command:

gcloud beta iam policies update POLICY_ID \
    --attachment-point=ATTACHMENT_POINT \
    --kind=denypolicies \
    --policy-file=POLICY_FILE

Provide the following values:

  • POLICY_ID: The identifier for the deny policy.

  • ATTACHMENT_POINT: An identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

  • POLICY_FILE: The filepath for the JSON file that contains the deny policy.

By default, if this command succeeds, it does not print any output. To print a detailed response, add the flag --format=json to the command.

For example, the following command updates a deny policy named my-deny-policy for the project my-project, using a file named policy.json:

gcloud beta iam policies update my-deny-policy \
    --attachment-point=cloudresourcemanager.googleapis.com/projects/my-project \
    --kind=denypolicies \
    --policy-file=policy.json

REST

The policies.update method updates a deny policy.

Before using any of the request data, make the following replacements:

  • ENCODED_ATTACHMENT_POINT: A URL-encoded identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

  • POLICY_ID: An identifier for the deny policy.
  • POLICY: The updated deny policy.

    For example, to add a permission to the policy shown in the previous step, replace POLICY with the following:

    {
      "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy",
      "uid": "6665c437-a3b2-a018-6934-54dd16d3426e",
      "kind": "DenyPolicy",
      "displayName": "My deny policy.",
      "etag": "MTc3NDU4MjM4OTY0MzU5MjQ5OTI=",
      "createTime": "2021-10-05T19:22:26.770543Z",
      "updateTime": "2021-10-05T19:22:26.770543Z",
      "rules": [
        {
          "denyRule": {
            "deniedPrincipals": [
              "principal://goog/subject/lucian@example.com"
            ],
            "deniedPermissions": [
              "iam.googleapis.com/roles.create",
              "iam.googleapis.com/roles.delete"
            ]
          }
        }
      ]
    }

HTTP method and URL:

PUT https://iam.googleapis.com/v2beta/policies/ENCODED_ATTACHMENT_POINT/denypolicies/POLICY_ID

Request JSON body:

POLICY

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy/operations/8b2d0ab2daf1ff01",
  "metadata": {
    "@type": "type.googleapis.com/google.iam.v2alpha.PolicyOperationMetadata",
    "createTime": "2021-10-05T22:26:21.968687Z"
  },
  "response": {
    "@type": "type.googleapis.com/google.iam.v2alpha.Policy",
    "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy",
    "uid": "6665c437-a3b2-a018-6934-54dd16d3426e",
    "kind": "DenyPolicy",
    "displayName": "My deny policy.",
    "etag": "MTgxNTIxNDE3NTYxNjQxODYxMTI=",
    "createTime": "2021-10-05T19:22:26.770543Z",
    "updateTime": "2021-10-05T22:26:21.968687Z",
    "rules": [
      {
        "denyRule": {
          "deniedPrincipals": [
            "principal://goog/subject/lucian@example.com"
          ],
          "deniedPermissions": [
            "iam.googleapis.com/roles.create",
            "iam.googleapis.com/roles.delete"
          ]
        }
      }
    ]
  }
}

The response identifies a long-running operation. You can monitor the status of the long-running operation to find out when it's complete. For details, see Check the status of a long-running operation on this page.

Delete a deny policy

If you no longer want to enforce the rules in a deny policy, you can delete the deny policy.

Optionally, you can specify the etag for the policy version that you are deleting. If you specify the etag, it must match the current etag stored by IAM; if the values do not match, the request fails. You can use this feature to ensure that you are deleting the intended policy, rather than an updated version of that policy.

If you omit the etag from the request, IAM deletes the policy unconditionally.

gcloud

To delete a deny policy from a resource, run the gcloud beta iam policies delete command:

gcloud beta iam policies delete POLICY_ID \
    --attachment-point=ATTACHMENT_POINT \
    --kind=denypolicies

Provide the following values:

  • POLICY_ID: The identifier for the deny policy.

  • ATTACHMENT_POINT: An identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

Optionally, you can add the flag --etag=ETAG. Replace ETAG with the current etag value for the deny policy.

By default, if this command succeeds, it does not print any output. To print a detailed response, add the flag --format=json to the command.

For example, the following command deletes a deny policy named my-deny-policy from the project my-project:

gcloud beta iam policies delete my-deny-policy \
    --attachment-point=cloudresourcemanager.googleapis.com/projects/my-project \
    --kind=denypolicies

REST

The policies.delete method deletes a deny policy from a resource.

Before using any of the request data, make the following replacements:

  • ENCODED_ATTACHMENT_POINT: A URL-encoded identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

  • POLICY_ID: An identifier for the deny policy.
  • ETAG: Optional. An identifier for the version of the policy. If present, this value must match the current etag value for the policy.

HTTP method and URL:

DELETE https://iam.googleapis.com/v2beta/policies/ENCODED_ATTACHMENT_POINT/denypolicies/POLICY_ID?etag=ETAG

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy/operations/8223fe308bf1ff01",
  "metadata": {
    "@type": "type.googleapis.com/google.iam.v2beta.PolicyOperationMetadata",
    "createTime": "2021-10-05T19:45:00.133311Z"
  },
  "response": {
    "@type": "type.googleapis.com/google.iam.v2beta.Policy",
    "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy",
    "kind": "DenyPolicy",
    "displayName": "My deny policy.",
    "etag": "MTc3NDU4MjM4OTY0MzU5MjQ5OTI=",
    "createTime": "2021-09-28T19:06:12.455151Z",
    "updateTime": "2021-10-05T19:45:00.133311Z",
    "deleteTime": "2021-10-05T19:45:00.133311Z",
    "rules": [
      {
        "denyRule": {
          "deniedPrincipals": [
            "principal://goog/subject/lucian@example.com"
          ],
          "deniedPermissions": [
            "iam.googleapis.com/roles.create"
          ]
        }
      }
    ]
  }
}

The response identifies a long-running operation. You can monitor the status of the long-running operation to find out when it's complete. For details, see Check the status of a long-running operation on this page.

Check the status of a long-running operation

When you use the REST API, any method that changes a deny policy returns a long-running operation, or LRO. The long-running operation tracks the status of the request and indicates whether the change to the policy is complete. You can poll the long-running operation to monitor its status.

To poll a long-running operation, start by getting its current status:

REST

The policies.operations.get method returns the status of a long-running operation.

Before using any of the request data, make the following replacements:

  • ENCODED_ATTACHMENT_POINT: A URL-encoded identifier for the resource that the deny policy is attached to. To learn how to format this value, see Identify the attachment point on this page.

  • OPERATION_ID: The identifier for the operation. You receive this identifier in the response to your original request, as part of the operation name. Use the hexadecimal value at the end of the operation name. For example, 89cb3e508bf1ff01.

HTTP method and URL:

GET https://iam.googleapis.com/v2beta/policies/ENCODED_ATTACHMENT_POINT/operations/OPERATION_ID

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F1234567890123/denypolicies/my-policy/operations/89cb3e508bf1ff01",
  "done": true
}

If the operation's done field is not present, continue to monitor its status by getting the operation repeatedly. Use truncated exponential backoff to introduce a delay between each request. When the done field is set to true, the operation is complete, and you can stop getting the operation.

What's next