IAM v2 Deny Policies
This reference guide details how to create, update, list, inspect, and delete
IAM v2 deny policies across Resource Manager attachment points (Organization,
Folder, Project) using the gcloud CLI.
Table of Contents
- 1. IAM v2 Overview & Mechanics
- 2. Deny Rule Structure & Specifications
- 3. Deny Policy Commands via gcloud CLI
- 4. Long-Running Operations (LRO) & Polling
- 5. Verification Plan
1. IAM v2 Overview & Mechanics
IAM deny policies define guardrails that prevent designated principals from using specified permissions, regardless of any roles granted by IAM allow policies.
- Precedence: Deny rules are evaluated before allow rules. If a permission is denied by a v2 policy, access is blocked even if an allow policy grants the role.
- Attachment Points:
- Organization:
cloudresourcemanager.googleapis.com/organizations/ORG_ID(numeric ID) - Folder:
cloudresourcemanager.googleapis.com/folders/FOLDER_ID(numeric ID) - Project:
cloudresourcemanager.googleapis.com/projects/PROJECT_ID
- Organization:
- Required Permissions:
roles/iam.denyAdmin(Deny Admin) on the target attachment point.
2. Deny Rule Structure & Specifications
A deny policy contains rules specifying denied principals, exception principals, denied permissions, and optional CEL conditions.
Deny Policy File Specification (YAML)
displayName: Block Public Deletion
rules:
- denyRule:
deniedPrincipals:
- "principalSet://goog/public:all"
exceptionPrincipals:
- "principal://goog/subject/admin@example.com"
deniedPermissions:
- "iam.googleapis.com/roles.delete"
- "resourcemanager.projects.delete"
denialCondition:
title: "Block_Public_Access"
expression: "request.time < timestamp('2030-01-01T00:00:00Z')"
Principal Identifiers in v2
principalSet://goog/public:all(All users on the internet)principal://goog/subject/USER_EMAIL(Specific user)principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/serviceaccounts/SA_EMAIL(Specific service account)principalSet://goog/group/GROUP_EMAIL(Google Group)
Permission Identifiers in v2
v2 denied permissions take the format SERVICE.googleapis.com/PERMISSION_NAME,
for example:
iam.googleapis.com/roles.deleteresourcemanager.projects.deletestorage.googleapis.com/buckets.delete
3. Deny Policy Commands via gcloud CLI
A. Create Deny Policy
# Project Level
gcloud iam policies create POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/projects/PROJECT_ID" \
--kind=denypolicies \
--policy-file=deny_policy.yaml
# Folder Level
gcloud iam policies create POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/folders/FOLDER_ID" \
--kind=denypolicies \
--policy-file=deny_policy.yaml
# Organization Level
gcloud iam policies create POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/organizations/ORG_ID" \
--kind=denypolicies \
--policy-file=deny_policy.yaml
B. Update Deny Policy
# Project Level
gcloud iam policies update POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/projects/PROJECT_ID" \
--kind=denypolicies \
--policy-file=updated_deny_policy.yaml
# Folder Level
gcloud iam policies update POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/folders/FOLDER_ID" \
--kind=denypolicies \
--policy-file=updated_deny_policy.yaml
# Organization Level
gcloud iam policies update POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/organizations/ORG_ID" \
--kind=denypolicies \
--policy-file=updated_deny_policy.yaml
C. List & Get Deny Policies
# List Deny Policies
# Project Level
gcloud iam policies list \
--attachment-point="cloudresourcemanager.googleapis.com/projects/PROJECT_ID" \
--kind=denypolicies
# Folder Level
gcloud iam policies list \
--attachment-point="cloudresourcemanager.googleapis.com/folders/FOLDER_ID" \
--kind=denypolicies
# Organization Level
gcloud iam policies list \
--attachment-point="cloudresourcemanager.googleapis.com/organizations/ORG_ID" \
--kind=denypolicies
# Get Deny Policy Details
# Project Level
gcloud iam policies get POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/projects/PROJECT_ID" \
--kind=denypolicies
# Folder Level
gcloud iam policies get POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/folders/FOLDER_ID" \
--kind=denypolicies
# Organization Level
gcloud iam policies get POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/organizations/ORG_ID" \
--kind=denypolicies
D. Delete Deny Policy
# Project Level
gcloud iam policies delete POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/projects/PROJECT_ID" \
--kind=denypolicies
# Folder Level
gcloud iam policies delete POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/folders/FOLDER_ID" \
--kind=denypolicies
# Organization Level
gcloud iam policies delete POLICY_NAME \
--attachment-point="cloudresourcemanager.googleapis.com/organizations/ORG_ID" \
--kind=denypolicies
4. Long-Running Operations (LRO) & Polling
Mutating deny policy commands (create, update, delete) execute
asynchronously as Long-Running Operations.
-
Automatic Wait:
gcloudCLI automatically polls and waits for operations to complete before returning. -
Manual LRO Inspection: To check the status of an operation explicitly, run the following command:
gcloud iam operations describe OPERATION_IDCheck that the returned status has
done: trueand contains no error payload.
5. Verification Plan
Depending on which mutating deny policy operation was executed (create,
update, or delete), run only its corresponding verification step to
confirm the change:
-
After
create:- Action: Run
gcloud iam policies get POLICY_NAME --attachment-point="<ATTACHMENT_POINT>" --kind=denypolicies. - Verification: Ensure the deny policy is returned with the specified rules and principal/permission bindings.
- Action: Run
-
After
update:- Action: Run
gcloud iam policies get POLICY_NAME --attachment-point="<ATTACHMENT_POINT>" --kind=denypolicies. - Verification: Verify that the rules and metadata reflect the updated configuration.
- Action: Run
-
After
delete:- Action: Run
gcloud iam policies list --attachment-point="<ATTACHMENT_POINT>" --kind=denypolicies. - Verification: Ensure the deleted policy name is no longer listed under the attachment point.
- Action: Run
After verifying the mutating change, remind the user that IAM deny policy changes take up to 7 minutes or longer to propagate across Google Cloud global infrastructure.