Below is an explanation and two common workarounds:
The Issue
When you use a custom service account for a Dataflow job that reads from Pub/Sub, Dataflow creates an internal “watermark tracking” subscription on the source topic. That subscription is named along the lines of:
<SOURCE_SUB_NAME>__df_internal
To create that tracking subscription, Dataflow calls Pub/Sub’s Subscription.Create API. Unfortunately, even if you grant roles like Pub/Sub Subscriber (or even narrow the Pub/Sub Editor role) on the source topic, the API call to create the subscription requires a broader scope—typically at the project level. In practice, you’ve noticed that only by granting roles/pubsub.editor on the entire project does the subscription creation succeed. But that violates the Principle of Least Privilege (PLP), since it opens access to resources beyond what your job should need.
Workaround Options
1. Pre-Create the Tracking Subscription
One common way to work around this is to pre-create the watermark tracking subscription manually. Then, configure your pipeline to use that pre-existing subscription instead of letting Dataflow create one at runtime. This way:
- Your Dataflow job won’t try to call Subscription.Create, and
- Your service account can get by with a more limited role (e.g., Pub/Sub Subscriber).
This method keeps privilege as narrow as possible because you avoid needing the project‐wide Pub/Sub Editor role.
2. Use IAM Conditions (Where Supported)
If you must allow Dataflow to create the watermark tracking subscription automatically, you might consider using IAM Conditions to restrict the Pub/Sub Editor role. With IAM Conditions you can limit the effective permissions to only resources whose names start with your expected tracking pattern. For example, you can bind roles/pubsub.editor to the job’s custom service account with a condition similar to:
bindings:
- members:
- serviceAccount:your-job-sa@example.iam.gserviceaccount.com
role: roles/pubsub.editor
condition:
title: RestrictToTrackingSubscriptions
description: "Allow Pub/Sub Editor only on subscriptions with __df_internal prefix."
expression: resource.name.matches("projects/your-project/subscriptions/.*__df_internal.*")
Note:
The IAM conditions syntax and expression capabilities may have limitations. Be sure to test that this conditional binding actually restricts access as expected. In some cases the Pub/Sub API may not take full advantage of conditions, meaning that even a conditionally bound role might be effectively broader than intended.
Recommended Approach
Given the current constraints of Dataflow’s internal behavior, the PLP best practice is to pre-create the watermark tracking subscription. This avoids the necessity of granting project-wide Pub/Sub Editor privileges to your job’s custom service account. Pre-creating the subscription ensures that your service account only—and precisely—has the roles needed to read from the source topic, staying true to the Principle of Least Privilege.
By choosing one of these approaches, you can balance Dataflow’s operational needs with a more secure, least-privileged setup.