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.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
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 |
| 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. |
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.'