gcp-spanner-write-data

spanner.databases.write + spanner.sessions.create together constitute effective data-plane write access: the caller can open a session and execute DML (INSERT, UPDATE, DELETE) statements to modify arbitrary rows in any table in the database.

derived gcp emits CanWriteData

match (effective permission)

{ "action": "spanner.databases.write", "resource_type": "google.spanner.admin.database.v1.Database" }

where

?principal ALSO has EFFECTIVE spanner.sessions.create on the same database or instance scope database.state == READY

emit

source typeIdentity
target typeRelationalDatabase
source<principal>
target<Spanner Database node>
permissionsspanner.databases.write spanner.sessions.create
conditionsiam_permission
state logicACTIVE when both spanner.databases.write and spanner.sessions.create are confirmed ACTIVE effective permissions on the database or enclosing instance/project scope AND the database state is READY AND no VPC-SC perimeter blocks the Spanner API for the caller's network context; CONDITIONAL(iam_permission) when sessions.create is uncertain or held only at a broader scope that may be capped by an IAM deny policy; BLOCKED when a VPC-SC perimeter enforces and the caller is outside the perimeter.

Narrative

{principal.name} holds spanner.databases.write + spanner.sessions.create on database {database.name}; it can open a Spanner session and execute DML (INSERT/UPDATE/DELETE) to modify arbitrary rows in any table in the database.

Raw rule rules/derived/gcp/spanner.yaml

id: gcp-spanner-write-data
emits: CanWriteData
description: 'spanner.databases.write + spanner.sessions.create together constitute effective data-plane
  write access: the caller can open a session and execute DML (INSERT, UPDATE, DELETE) statements to modify
  arbitrary rows in any table in the database.'
match_effective_permission:
  action: spanner.databases.write
  resource_type: google.spanner.admin.database.v1.Database
where:
- ?principal ALSO has EFFECTIVE spanner.sessions.create on the same database or instance scope
- database.state == READY
emit:
  source_type: Identity
  target_type: RelationalDatabase
  source: <principal>
  target: <Spanner Database node>
  permissions:
  - spanner.databases.write
  - spanner.sessions.create
  conditions:
  - iam_permission
  state_logic: ACTIVE when both spanner.databases.write and spanner.sessions.create are confirmed ACTIVE
    effective permissions on the database or enclosing instance/project scope AND the database state is
    READY AND no VPC-SC perimeter blocks the Spanner API for the caller's network context; CONDITIONAL(iam_permission)
    when sessions.create is uncertain or held only at a broader scope that may be capped by an IAM deny
    policy; BLOCKED when a VPC-SC perimeter enforces and the caller is outside the perimeter.
  false_positive_note: "BOTH permissions are required: spanner.databases.write alone does not allow executing\
    \ DML without a session (sessions.create), and spanner.sessions.create alone does not grant data write\
    \ access. The permission evaluator must resolve BOTH at the effective (post-hierarchy) level. spanner.databases.write\
    \ is present in roles/spanner.admin, roles/spanner.databaseAdmin, and roles/spanner.databaseUser (and\
    \ above). It enables INSERT, UPDATE, DELETE DML operations and is not available in read-only roles\
    \ like roles/spanner.databaseReader. A principal with CanWriteData can corrupt database integrity,\
    \ modify sensitive application data, delete audit logs, or inject malicious data for downstream consumption\
    \ \u2014 this is a high-value attack path for supply-chain or data-integrity attacks. VPC-SC perimeters\
    \ that include the Spanner API block callers outside the perimeter regardless of IAM \u2014 emit BLOCKED\
    \ in that case."
  narrative: '{principal.name} holds spanner.databases.write + spanner.sessions.create on database {database.name};
    it can open a Spanner session and execute DML (INSERT/UPDATE/DELETE) to modify arbitrary rows in any
    table in the database.'
  derived_from:
  - spanner.databases.write effective permission on Database
  - spanner.sessions.create effective permission on same scope
move · open · esc close