gcp-spanner-set-iam-policy-instance
spanner.instances.setIamPolicy lets a principal grant any instance-level role to any principal, including itself. This affects ALL databases within the instance - a broader blast radius than database-scope setIamPolicy.
match (effective permission)
{
"action": "spanner.instances.setIamPolicy",
"resource_type": "google.spanner.admin.instance.v1.Instance"
}
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | <principal> |
| target | <any principal (self-grant or other)> |
| permissions | spanner.instances.setIamPolicy |
| conditions | iam_permission deny_assignment scp_or_org_policy |
| state logic | ACTIVE when spanner.instances.setIamPolicy is confirmed as an ACTIVE effective permission on the instance scope and no org policy or IAM deny policy blocks IAM mutations; CONDITIONAL(scp_or_org_policy) if an org policy restricts IAM policy modifications; BLOCKED when an IAM deny policy (resourcemanager.projects.setIamPolicy deny or spanner.instances.setIamPolicy deny) explicitly denies the action. Reference /rules/derived/gcp/iam-deny.yaml for deny-policy modeling. |
Narrative
{principal.name} holds spanner.instances.setIamPolicy on instance {instance.name} and can grant itself or any principal instance-level roles (e.g., roles/spanner.instanceAdmin, roles/spanner.databaseAdmin at instance scope), affecting all {count} databases in the instance. Note: only roles grantable at instance scope are accessible; project-level roles like roles/spanner.admin cannot be granted at instance scope IAM.
Raw rule rules/derived/gcp/spanner.yaml
id: gcp-spanner-set-iam-policy-instance
emits: CanGrantPermission
description: "spanner.instances.setIamPolicy lets a principal grant any instance-level role to any principal,\
\ including itself. This affects ALL databases within the instance \u2014 a broader blast radius than\
\ database-scope setIamPolicy."
match_effective_permission:
action: spanner.instances.setIamPolicy
resource_type: google.spanner.admin.instance.v1.Instance
emit:
source_type: Identity
target_type: Identity
source: <principal>
target: <any principal (self-grant or other)>
permissions:
- spanner.instances.setIamPolicy
conditions:
- iam_permission
- deny_assignment
- scp_or_org_policy
state_logic: ACTIVE when spanner.instances.setIamPolicy is confirmed as an ACTIVE effective permission
on the instance scope and no org policy or IAM deny policy blocks IAM mutations; CONDITIONAL(scp_or_org_policy)
if an org policy restricts IAM policy modifications; BLOCKED when an IAM deny policy (resourcemanager.projects.setIamPolicy
deny or spanner.instances.setIamPolicy deny) explicitly denies the action. Reference /rules/derived/gcp/iam-deny.yaml
for deny-policy modeling.
false_positive_note: spanner.instances.setIamPolicy is present in roles/spanner.admin and roles/spanner.instanceAdmin.
Unlike database-scope setIamPolicy, this permission applies to the entire instance and grants IAM
mutation rights over ALL databases in the instance simultaneously. Self-granting roles/spanner.admin
at the instance scope yields maximum privilege for all databases in the instance. This is a higher-value
escalation than database-scope setIamPolicy.
narrative: '{principal.name} holds spanner.instances.setIamPolicy on instance {instance.name} and can
grant itself or any principal instance-level roles (e.g., roles/spanner.instanceAdmin, roles/spanner.databaseAdmin
at instance scope), affecting all {count} databases in the instance. Note: only roles grantable at
instance scope are accessible; project-level roles like roles/spanner.admin cannot be granted at instance
scope IAM.'
derived_from:
- spanner.instances.setIamPolicy effective permission on Instance