gcp-cloudscheduler-cross-project-pubsub

A Cloud Scheduler Pub/Sub job targeting a topic in a different project establishes cross-project trust - the Cloud Scheduler service agent must hold roles/pubsub.publisher in the external project.

derived gcp emits CrossProjectTrust

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'job': None} CanWriteData {'topic': None}

where

node_type(?job) == Scheduler node_type(?topic) == Topic ?job.project != ?topic.project Cloud Scheduler service agent holds pubsub.topics.publish on ?topic (cross-project binding)

emit

source typeResourcePolicy
target typeProject
source<Cloud Scheduler service agent's cross-project pubsub.topics.publish binding>
target<target project ?topic.project>
permissionspubsub.topics.publish
conditionsiam_permission resource_policy
state logicACTIVE when the Cloud Scheduler service agent unconditionally holds pubsub.topics.publish on the external topic AND the job's pubsubTarget.topicName references the external topic. CONDITIONAL(resource_policy) when the binding is conditional (IAM conditions restrict the grant). BLOCKED by org policy or IAM deny overriding the cross-project binding.

Narrative

{job.name} targets a Pub/Sub topic in {target_project.name} (a different project). The Cloud Scheduler service agent holds pubsub.topics.publish on that topic, establishing cross-project trust; can-control rolls this up to CanEnterProject.

Raw rule rules/derived/gcp/cloudscheduler.yaml

id: gcp-cloudscheduler-cross-project-pubsub
emits: CrossProjectTrust
description: "A Cloud Scheduler Pub/Sub job targeting a topic in a different project establishes cross-project\
  \ trust \u2014 the Cloud Scheduler service agent must hold roles/pubsub.publisher in the external project."
match:
- - job: null
  - CanWriteData
  - topic: null
where:
- node_type(?job) == Scheduler
- node_type(?topic) == Topic
- ?job.project != ?topic.project
- Cloud Scheduler service agent holds pubsub.topics.publish on ?topic (cross-project binding)
emit:
  source_type: ResourcePolicy
  target_type: Project
  source: <Cloud Scheduler service agent's cross-project pubsub.topics.publish binding>
  target: <target project ?topic.project>
  permissions:
  - pubsub.topics.publish
  derived_from:
  - ?job CanWriteData ?topic (gcp-cloudscheduler-explicit-pubsub-trigger or gcp-cloudscheduler-create-pubsub-job-write)
  - 'IAM binding: Cloud Scheduler service agent has pubsub.topics.publish on external topic'
  conditions:
  - iam_permission
  - resource_policy
  state_logic: ACTIVE when the Cloud Scheduler service agent unconditionally holds pubsub.topics.publish
    on the external topic AND the job's pubsubTarget.topicName references the external topic. CONDITIONAL(resource_policy)
    when the binding is conditional (IAM conditions restrict the grant). BLOCKED by org policy or IAM
    deny overriding the cross-project binding.
  false_positive_note: "Only emit when the job's target project differs from the job's project. The service\
    \ agent must have explicit pubsub.topics.publish on the external topic \u2014 it does NOT inherit\
    \ editor/owner roles. Confirm the binding is not conditionally scoped (e.g., time-bound or MFA-required)\
    \ before emitting ACTIVE."
  narrative: '{job.name} targets a Pub/Sub topic in {target_project.name} (a different project). The Cloud
    Scheduler service agent holds pubsub.topics.publish on that topic, establishing cross-project trust;
    can-control rolls this up to CanEnterProject.'
move · open · esc close