1.1 IAM Roles, Service Accounts, and Least Privilege for Data
Key Takeaways
- The Google Cloud resource hierarchy (Organization > Folders > Projects > Resources) enforces strictly additive IAM inheritance, meaning permissions granted at higher tiers cannot be overridden or revoked at subordinate levels.
- Primitive roles (Owner, Editor, Viewer) violate least-privilege principles by granting unsegmented permissions across all services; production data platforms require granular predefined roles or tightly scoped IAM policies.
- Separating compute execution permissions (roles/bigquery.jobUser) in the billing project from data read permissions (roles/bigquery.dataViewer) at the dataset level forms the core architectural pattern for secure multi-tenant analytics.
- Workload Identity on GKE and Workload Identity Federation eliminate the security risks of long-lived service account JSON keys by using short-lived OpenID Connect and OAuth 2.0 tokens for containers and external pipelines.
- IAM Conditions using Common Expression Language (CEL) enable Attribute-Based Access Control (ABAC) to enforce temporal constraints, bucket prefix boundaries, and destination dataset controls dynamically.
1.1 IAM Roles, Service Accounts, and Least Privilege for Data
[!IMPORTANT] For the Google Cloud Professional Data Engineer exam, primitive roles (
roles/owner,roles/editor,roles/viewer) are strictly treated as production anti-patterns. Production exam scenarios require selecting precise predefined roles that decouple compute execution from storage access, combined with keyless service account authentication.
Designing an enterprise data platform on Google Cloud requires implementing a comprehensive defense-in-depth security model. Data engineers manage high-throughput analytical assets—ranging from raw ingested telemetry streams to curated, customer-facing business intelligence marts. A single overly permissive IAM binding can expose sensitive financial records, permit unauthorized slot consumption, or allow the catastrophic deletion of petabyte-scale data lakes.
In this section, we examine the mechanics of Identity and Access Management (IAM), evaluate the resource hierarchy, analyze role taxonomies, and implement least-privilege patterns across BigQuery, Cloud Storage, and Cloud Pub/Sub. We also explore keyless authentication architectures and dynamic Attribute-Based Access Control (ABAC) using IAM Conditions.
The Google Cloud Resource Hierarchy and Role Inheritance
All Google Cloud resources are organized into a strict structural hierarchy: Organization > Folders > Projects > Resources (such as BigQuery datasets and tables, Cloud Storage buckets and objects, Pub/Sub topics and subscriptions, and Dataflow jobs).
Organization (example.com)
└── Folder (Data Platform)
├── Folder (Analytics Production)
│ └── Project (prj-analytics-prod)
│ ├── BigQuery Dataset (marketing_mart)
│ └── Cloud Storage Bucket (curated-data)
└── Folder (Staging & Ingestion)
└── Project (prj-ingestion-prod)
├── Pub/Sub Topic (telemetry-events)
└── Dataflow Job (streaming-ingest)
Understanding how IAM policies propagate down this hierarchy is vital for both enterprise system design and exam scenarios. IAM policy evaluation operates under two fundamental, inviolable rules:
- Inheritance is strictly additive: Permissions accumulate down the hierarchy. The effective policy for any resource is the union of the IAM policy set on that resource and the policies inherited from all parent projects, folders, and the organization. If a user or service account is granted
roles/storage.objectAdminat the Folder level, that identity possesses full object administrative access across every Cloud Storage bucket inside every project contained within that folder. - No downward restriction: You cannot override, negate, or subtract an inherited permission at a subordinate tier. If a data analyst possesses
roles/editorat the project level, you cannot restrict them to read-only access on a single BigQuery dataset within that project. Consequently, broad role grants must never be placed at the Organization or Folder tier for operational personnel.
Scoping IAM Bindings at the Resource Level
To enforce the principle of least privilege, access grants should be placed as close to the leaf nodes of the hierarchy as technically possible:
- Organization and Folder Level: Reserved strictly for centralized governance teams (e.g., Cloud Security Administrators, Organization Policy Admins, and automated Security Command Center scanners).
- Project Level: Used to grant administrative ownership over specific project boundaries, billing job execution (
roles/bigquery.jobUser), or infrastructure provisioning rights. - Resource Level: Bound directly to specific BigQuery datasets, Cloud Storage buckets, or Pub/Sub topics to isolate access to business data.
Primitive Roles vs. Predefined Roles vs. Custom Roles
Google Cloud provides three distinct classes of IAM roles. Selecting the appropriate role class involves evaluating granularity, administrative maintenance overhead, and security exposure.
1. Primitive Roles (Legacy)
Primitive roles include Owner, Editor, and Viewer. These roles predate fine-grained IAM and grant broad, sweeping permissions across virtually every Google Cloud service:
roles/viewer: Grants read-only visibility into configurations and data across nearly all services in the project.roles/editor: Grants permissions to view, modify, create, and destroy existing cloud resources, including deleting storage buckets, deploying Compute Engine instances, and modifying network firewall rules.roles/owner: Full administrative control, including managing billing accounts, modifying IAM policies, and deleting entire projects.
The Production Anti-Pattern: On the PDE exam, any multiple-choice option suggesting the use of primitive roles (roles/editor, roles/owner, roles/viewer) for routine data engineering workloads is incorrect. An automated ETL pipeline granted roles/editor can inadvertently delete unrelated datasets, spin up unapproved infrastructure, or cause privilege escalation.
2. Predefined Roles (Recommended Best Practice)
Predefined roles are authored, validated, and actively maintained by Google Cloud. They bundle granular permissions tailored to standard operational job functions (e.g., roles/bigquery.dataViewer, roles/storage.objectViewer, roles/pubsub.publisher).
Automatic Maintenance and Feature Parity: Google Cloud automatically updates predefined roles whenever new features, APIs, or service drivers are released. When Google introduced the BigQuery Storage Write API, Google automatically updated roles/bigquery.dataEditor and roles/bigquery.admin to include the appropriate streaming permissions (bigquery.tables.updateData). Enterprise data pipelines utilizing predefined roles experienced zero downtime or configuration drift.
3. Custom Roles
When predefined roles do not match an organization's specific compliance constraints, administrators can assemble granular API permissions into a custom role (e.g., combining bigquery.tables.get and bigquery.tables.getData while deliberately omitting table export or copy permissions).
The Custom Role Maintenance Dilemma: While custom roles offer surgical precision, they introduce severe operational maintenance overhead:
- No Automatic Updates: Custom roles do not automatically inherit new granular permissions released by Google Cloud. If Google updates a client library or introduces an optimized API method, custom roles must be updated manually by an administrator.
- API Fragility: Unannounced updates to SDKs or CLI tools may require auxiliary permissions (such as
resourcemanager.projects.get). When missing, automated pipelines fail unexpectedly. - Limited Scope: Custom roles cannot be created at the folder level; they are strictly bound to either an individual project or an organization.
Exam Guidance: Always select predefined roles combined with resource-level scoping or IAM Conditions over custom roles, unless the exam scenario explicitly states that no predefined role satisfies a strict corporate policy.
| Feature / Attribute | Primitive Roles | Predefined Roles | Custom Roles |
|---|---|---|---|
| Granularity | Coarse-grained (all project services) | Fine-grained (service-specific job function) | Highly surgical (user-selected permissions) |
| Maintenance | None (static legacy definitions) | Fully managed by Google Cloud | High; manual administrative updates required |
| Production Suitability | Strictly prohibited in production | Industry standard best practice | Exception-only (when predefined roles are too broad) |
| API Evolution | Static | Automatic incorporation of new APIs | Fragile; breaks when underlying APIs update |
| Scope of Creation | Built-in project level | Global across Google Cloud | Project or Organization level only |
| IAM Conditions Support | Unsupported | Supported via CEL expressions | Supported via CEL expressions |
Implementing Least Privilege in Core Data Services
Enterprise data platforms require decoupling compute resources from data storage assets. This decoupling enables multi-tenant architectures where different departments query shared datasets using their own dedicated compute budgets.
BigQuery: Decoupling Compute and Storage Permissions
A central design pattern evaluated on the exam involves a business intelligence team that needs to query data in a centralized analytics warehouse without being permitted to alter schemas, access other business units' data, or bill queries to the data warehouse project.
+-------------------------------------------------------------------------+
| Project: prj-bi-compute |
| (Compute & Billing Project - Slot Reservations / On-Demand Billing) |
| |
| IAM Binding on Project: |
| - Group: bi-analysts@example.com -> roles/bigquery.jobUser |
+-------------------------------------------------------------------------+
|
| Submits Query Job
v
+-------------------------------------------------------------------------+
| Project: prj-data-warehouse |
| (Storage Project - Centralized Datasets & Tables) |
| |
| IAM Binding on Dataset 'sales_reporting': |
| - Group: bi-analysts@example.com -> roles/bigquery.dataViewer |
| |
| IAM Binding on Dataset 'hr_confidential': |
| - Group: bi-analysts@example.com -> [NO ACCESS] |
+-------------------------------------------------------------------------+
To execute this model, data engineers combine distinct predefined roles across project boundaries:
roles/bigquery.jobUser: Granted on the compute/billing project (prj-bi-compute). It confersbigquery.jobs.create, enabling the identity to run queries, export data, and cancel its own jobs. Critically, it grants zero data read permissions.roles/bigquery.dataViewer: Granted directly on the target dataset (sales_reporting) in the storage project. It allows the identity to read table schemas, metadata, and table contents. By omitting this role from other datasets (e.g.,hr_confidential), the identity is strictly isolated.roles/bigquery.dataEditor: Granted to ETL/ELT service accounts on specific datasets to create, append, truncate, and delete tables and partitions without granting project-level administrative control.roles/bigquery.admin: Full administrative control over BigQuery resources within a project. Must be restricted exclusively to cloud data platform administrators.
Authorized Views and Authorized Datasets
When analysts require access to aggregated or filtered data (e.g., viewing sales totals without seeing customer names), granting table-level read permissions is insufficient. BigQuery provides Authorized Views and Authorized Datasets:
- A view is created in a separate reporting dataset containing SQL aggregation (
SELECT region, SUM(revenue) FROM raw_dataset.orders GROUP BY region). - The view is authorized within the underlying source dataset (
raw_dataset). - Analysts are granted
roles/bigquery.dataVieweron the reporting view's dataset, with no permissions granted onraw_dataset. BigQuery authorizes the view to access the underlying tables on behalf of the querying user.
Column-Level Security (Policy Tags) and Row-Level Security
- Column-Level Security: Leverages Dataplex Catalog taxonomy policy tags. Columns containing sensitive data (such as SSNs or salaries) are tagged. Users must be granted the
roles/datacatalog.categoryFineGrainedReaderrole on the specific policy tag to query the unmasked column; otherwise, the query fails or returns masked data. - Row-Level Security: Enforced via
CREATE ROW ACCESS POLICYDDL statements directly on BigQuery tables. Access is filtered dynamically based on the querying principal's session identity (e.g.,SESSION_USER() = sales_rep_emailor group membership viaIS_GROUP_MEMBER()).
Cloud Storage: Data Lake Access Controls
Cloud Storage acts as the primary landing and staging zone for raw enterprise data. Modern data architectures mandate enabling Uniform Bucket-Level Access (UBLA):
- Uniform Bucket-Level Access (UBLA): Disables legacy object-level Access Control Lists (ACLs) and unifies all access management under Cloud IAM. Enabling UBLA is required for Google Cloud security posture certifications and simplifies compliance audits.
Core Cloud Storage predefined roles include:
roles/storage.objectViewer: Grants read-only access to object data and metadata (storage.objects.get,storage.objects.list). Ideal for Dataflow pipelines reading raw staging files.roles/storage.objectCreator: Grants write-only access to upload new objects (storage.objects.create). It does not grant read, overwrite, or delete permissions. This role is ideal for external ingestion partners or automated sensor gateways dropping files into an ingestion bucket.roles/storage.objectUser: Grants read, write, and delete permissions to objects, but does not allow modifying bucket configurations or IAM policies.roles/storage.admin: Full control over buckets and objects. Reserved for infrastructure automation pipelines.
Cloud Pub/Sub: Streaming Ingestion Decoupling
Pub/Sub decouples event producers from stream processing consumers:
roles/pubsub.publisher: Bound to application servers or IoT gateways to publish messages to a specific topic (pubsub.topics.publish).roles/pubsub.subscriber: Bound to Dataflow streaming workers or Cloud Run consumers to pull or consume messages from a subscription (pubsub.subscriptions.consume).- Service Agent Permissions: When configuring Pub/Sub BigQuery subscriptions or Cloud Storage dead-letter sinks, the Pub/Sub Service Agent (
service-<project-number>@gcp-sa-pubsub.iam.gserviceaccount.com) must be explicitly grantedroles/bigquery.dataEditoron the destination table orroles/storage.objectCreatoron the dead-letter bucket.
| Service | Role Name | Key Permissions | Standard Production Application |
|---|---|---|---|
| BigQuery | roles/bigquery.jobUser | bigquery.jobs.create | Assigned at project level to allow running queries in compute projects |
| BigQuery | roles/bigquery.dataViewer | bigquery.tables.getData, bigquery.tables.list | Assigned at dataset level to permit data reading without modifying schemas |
| BigQuery | roles/bigquery.dataEditor | Create, append, update, truncate tables | Assigned to ETL service accounts writing curated tables |
| Cloud Storage | roles/storage.objectViewer | Read object payloads and metadata | Assigned to Dataflow worker service accounts reading raw files |
| Cloud Storage | roles/storage.objectCreator | storage.objects.create (no read/delete) | Assigned to external third-party dropboxes and ingest sources |
| Cloud Storage | roles/storage.admin | Bucket lifecycle, deletion, IAM | Reserved for Terraform and platform automation service accounts |
| Pub/Sub | roles/pubsub.publisher | pubsub.topics.publish | Assigned to edge ingest gateways and application event publishers |
| Pub/Sub | roles/pubsub.subscriber | pubsub.subscriptions.consume | Assigned to streaming Dataflow pipelines and Cloud Run services |
Service Accounts, Keyless Architecture, and Impersonation
Automated pipelines, orchestration tools, and compute workloads authenticate to Google Cloud APIs using Service Accounts rather than human user credentials.
Service Account Categories
- User-Managed Service Accounts: Created explicitly by data engineers for dedicated application tasks (e.g.,
sa-dataflow-etl@prj-prod.iam.gserviceaccount.com). Administrators control their lifecycle, IAM bindings, and rotation. - Google-Managed Service Accounts (Service Agents): Created automatically by Google Cloud when an API is enabled. Service agents follow the naming pattern
service-<project-number>@gcp-sa-<service>.iam.gserviceaccount.com. They are granted predefined service agent roles internally to perform orchestration actions (such as Cloud Dataflow launching worker VMs). - Default Service Accounts: Compute Engine automatically provisions a default service account (
<project-number>-compute@developer.gserviceaccount.com) and historically bound it to the primitiveEditorrole. In production data platforms, default service accounts represent a major security vulnerability and should be disabled or replaced with custom least-privilege service accounts.
The Critical Hazard of Service Account JSON Keys
Downloading static private keys (JSON key files) introduces severe security liabilities into enterprise systems:
- Credential Leakage: Long-lived private keys are frequently checked into public source repositories, stored unencrypted on developer workstations, or embedded in container images.
- Bypass of Corporate Controls: Static keys do not participate in Single Sign-On (SSO), Multi-Factor Authentication (MFA), or conditional access policies.
- Indefinite Validity: A compromised private key remains valid for up to 10 years unless an administrator manually revokes it.
Best Practice: Enforce the organization policy constraint constraints/iam.disableServiceAccountKeyCreation. Instead of static keys, enterprise architectures must employ keyless authentication.
+-------------------------------------------------------------------------+
| Keyless Authentication Strategies |
+-------------------------------------------------------------------------+
|
+-------------------------------+-------------------------------+
| | |
v v v
+-------------------+ +-------------------+ +-------------------+
| Workload Identity | | Workload Identity | | Service Account |
| on GKE | | Federation | | Impersonation |
| (Container Native)| | (AWS/GitHub/On-Prem)| | (Short-Lived Auth)|
+-------------------+ +-------------------+ +-------------------+
| Maps KSA directly | | Exchanges OIDC / | | Generates 1-hour |
| to GSA via GKE | | SAML tokens for | | tokens via IAM |
| metadata server. | | short-lived GCP | | Credentials API. |
| Zero secret keys. | | access tokens. | | Full audit trail. |
+-------------------+ +-------------------+ +-------------------+
1. Workload Identity on Google Kubernetes Engine (GKE)
Workload Identity is the recommended approach for running containerized data processing workloads (e.g., Apache Spark on GKE, Trino, or containerized Apache Beam runners) that interact with Google Cloud APIs:
- A Kubernetes Service Account (KSA) is created inside the GKE cluster namespace.
- An IAM Google Service Account (GSA) is created with least-privilege roles (e.g.,
roles/bigquery.dataEditor). - An IAM binding grants the KSA permission to assume the GSA via the
roles/iam.workloadIdentityUserrole. - Pods running under the KSA automatically query the local GKE metadata server (
http://metadata.google.internal), which transparently provides short-lived OAuth 2.0 access tokens. No Kubernetes secrets or private keys are ever generated.
2. Workload Identity Federation (WIF)
Workload Identity Federation extends keyless authentication to workloads running outside Google Cloud—such as GitHub Actions CI/CD pipelines, AWS Lambda ETL workers, or on-premises Apache Airflow instances:
- The external workload obtains an OpenID Connect (OIDC) or SAML 2.0 identity token from its native identity provider (IdP).
- The workload sends the token to Google Cloud's Security Token Service (STS).
- STS validates the signature, maps the token attributes, and exchanges it for a short-lived Google Cloud federated access token.
- External pipelines access BigQuery or Cloud Storage securely without storing static GCP credentials.
3. Service Account Impersonation
When human engineers or automated orchestration tools (like Terraform) require elevated privileges, they should use Service Account Impersonation rather than downloading keys:
- The human user's corporate identity is granted the
roles/iam.serviceAccountTokenCreatorrole on the target service account. - The user invokes
gcloudor client libraries specifying--impersonate-service-account=sa-deployer@prj-prod.iam.gserviceaccount.com. - Cloud IAM generates a short-lived access token (valid for up to 1 hour).
- Cloud Audit Logs record both the authenticating human principal and the impersonated service account, ensuring full non-repudiation and traceability.
IAM Conditions: Attribute-Based Access Control (ABAC)
IAM Conditions enable data architects to define dynamic access boundaries based on Common Expression Language (CEL). Rather than granting permanent access, conditions evaluate environmental, temporal, and resource attributes during each API invocation.
Common CEL Production Use Cases for Data Engineers
- Cloud Storage Prefix Path Restriction: Restricting an external ingest service account to write only within an incoming staging directory inside a shared bucket:
resource.type == "storage.googleapis.com/Object" && resource.name.startsWith("projects/_/buckets/company-lake/objects/staging/partner_a/") - Time-Bounded Access for Temporary Contractors: Granting data analysts temporary dataset access during a scheduled sprint that terminates automatically:
request.time < timestamp("2026-12-31T23:59:59Z") - Business Hours Access Restriction: Permitting query job execution only during standard corporate operating hours to prevent off-hours data exfiltration:
request.time.getHours("America/New_York") >= 8 && request.time.getHours("America/New_York") <= 18 - BigQuery Destination Table Scoping: Allowing export jobs only when the destination Cloud Storage bucket belongs to an authorized corporate compliance bucket:
resource.name.startsWith("projects/_/buckets/authorized-exports/")
Exam Traps and Antipatterns Summary
| Antipattern / Trap | Why It Fails | Correct Exam Solution |
| :--- | :--- | :--- | :--- |
| Granting roles/editor to Dataflow worker VMs | Violates least privilege; grants excessive administrative permissions across the entire project | Create a dedicated user-managed service account with roles/dataflow.worker and granular data roles |
| Downloading service account JSON keys for CI/CD | Creates severe security exposure and static credential leakage risk | Implement Workload Identity Federation using OIDC tokens |
| Granting roles/bigquery.admin to resolve query access issues | Over-provisions administrative control and exposes schema deletion permissions | Grant roles/bigquery.jobUser on compute project and roles/bigquery.dataViewer on specific dataset |
| Creating custom IAM roles for every data pipeline | High maintenance toil; custom roles do not inherit new API permissions and break over time | Use predefined roles combined with resource-level scoping and IAM Conditions |
| Using object-level ACLs on Cloud Storage buckets | Fragile, inconsistent permissions that complicate compliance auditing | Enforce Uniform Bucket-Level Access (UBLA) with IAM role bindings |
A business intelligence analyst needs to execute SQL queries in BigQuery against sales data stored in a central data warehouse project. The security policy mandates that analysts must be able to query tables in the sales_reporting dataset, but they must not be able to read tables in other datasets within the same project, nor should they be able to alter schemas or delete resources. How should permissions be structured according to least-privilege principles?
An engineering team is deploying an Apache Beam pipeline packaged as a containerized workload on Google Kubernetes Engine (GKE). The pipeline reads streaming records from Cloud Storage and writes transformed records into BigQuery. Enterprise security policy strictly forbids generating, downloading, or storing persistent private key files in Kubernetes Secrets. Which architectural approach satisfies this requirement?
A cloud security architect is reviewing an organization's IAM strategy and notices that the data engineering team has created dozens of custom IAM roles for individual BigQuery and Cloud Storage tasks. Why does Google Cloud recommend using predefined roles instead of maintaining numerous custom roles?