This document provides a comprehensive overview of all IAM permissions, OAuth scopes, and security configurations used by the Ona GCP Runner Terraform module.
The module creates a secure, least-privilege infrastructure for running Ona workspaces on Google Cloud Platform. It uses multiple service accounts with specific roles and OAuth scopes to ensure proper isolation and security.
The module creates 3 service accounts:
- Runner (
runner) — manages infrastructure and orchestrates workspace lifecycle - Environment VM (
environment_vm) — used by workspace VMs with minimal permissions - Proxy VM (
proxy_vm) — used by proxy VMs for load balancing and traffic routing
Note: Previous versions created additional service accounts for build cache, secret management, and pub/sub processing. These have been removed — their permissions are handled directly by the runner service account.
Purpose: Manages the runner infrastructure and orchestrates workspace lifecycle
Display Name: Ona Runner
Account ID: {runner_name}-runner
Description: Service account for runner infrastructure management
OAuth Scopes:
https://www.googleapis.com/auth/logging.write- Write access to Cloud Logging for centralized workspace logshttps://www.googleapis.com/auth/monitoring.write- Write access to Cloud Monitoring for workspace metrics and health checkshttps://www.googleapis.com/auth/compute- Full access to Compute Engine (required for dynamic VM lifecycle management: create, delete, start, stop, modify instances and disks)https://www.googleapis.com/auth/devstorage.read_write- Read/write access to Cloud Storage (required for build cache uploads, workspace persistence, and container image management)https://www.googleapis.com/auth/pubsub- Full access to Pub/Sub for event-driven workspace reconciliation and scalinghttps://www.googleapis.com/auth/cloud-platform- Access to additional Google Cloud services (see detailed justification below)
Why cloud-platform scope is needed (Security Note: This broad scope is required because specific OAuth scopes don't exist for these critical services):
- IAM Credentials API: Generate short-lived access tokens for other service accounts (enables secure impersonation pattern)
- Service Networking API: Manage VPC peering for Redis (required for workspace session storage)
- Redis API: Create and manage Redis instances (required for workspace state and session management)
- Secret Manager API: Access Redis authentication credentials and runner tokens
- Artifact Registry API: Manage container image repositories for workspace images
Security Mitigation: While cloud-platform is broad, access is limited by IAM permissions. The runner's custom IAM role restricts actual capabilities to only necessary operations.
The runner secrets key has additional resource-level bindings:
roles/secretmanager.secretAccessorto read the current key version.roles/secretmanager.secretVersionAdderto create the first version during migration.
Terraform owns the secret and these bindings, while the runner owns the secret version. The module does not place the key material in Terraform state.
IAM Roles:
- Custom Role:
{runner_name}_runner- Minimal permissions for infrastructure management (detailed below) roles/logging.logWriter- Write access to Cloud Logging for operational logsroles/monitoring.metricWriter- Write access to Cloud Monitoring for metrics and health dataroles/cloudtrace.agent- Write access to Cloud Trace for distributed tracingroles/redis.editor- Manage Redis instances for workspace state storage (not admin - cannot manage instance lifecycle, only read/write data)
Security Note: The runner uses minimal writer/editor roles instead of admin roles. It cannot create logging sinks, monitoring dashboards, or pub/sub infrastructure - these are managed by Terraform. This reduces the blast radius if the service account is compromised.
Purpose: Used by workspace VMs for accessing workspace-specific resources
Display Name: Ona Environment VM
Account ID: {runner_name}-env-vm
Description: Minimal service account for environment VMs
OAuth Scopes: None (uses IAM permissions only)
IAM Roles:
roles/monitoring.metricWriter- Write custom metrics for workspace monitoring (CPU, memory, disk usage, application-specific metrics)roles/logging.logWriter- Write logs to Cloud Logging for workspace activity and debuggingroles/artifactregistry.reader- Read container images from Artifact Registry for workspace setup
Security Rationale: Workspace VMs have minimal permissions - only metric writing, logging, and reading container images. No access to other workspaces, secrets, or infrastructure management. This limits blast radius if a workspace is compromised.
Purpose: Used by proxy VMs for load balancing and traffic routing
Display Name: Ona Proxy VM Service
Account ID: {runner_name}-proxy-vm
Description: Service account for Ona proxy VM instances
OAuth Scopes:
https://www.googleapis.com/auth/logging.write- Write access to Cloud Logging for proxy access logs and error reportinghttps://www.googleapis.com/auth/monitoring.write- Write access to Cloud Monitoring for proxy health metrics and performance datahttps://www.googleapis.com/auth/compute.readonly- Read-only access to Compute Engine (required to discover workspace VMs for load balancing)https://www.googleapis.com/auth/devstorage.read_only- Read-only access to Cloud Storage (required to serve static assets and workspace files)
IAM Roles:
roles/logging.logWriter- Write logs to Cloud Logging (access logs, error logs, security events)roles/monitoring.metricWriter- Write metrics to Cloud Monitoring (request rates, latency, error rates)- Custom Role:
{runner_name}_proxy_vm- Minimal compute permissions for service discovery:compute.instances.get- Get instance details for routingcompute.instances.list- List instances for service discoverycompute.networks.get- Get network information for proxy functionalitycompute.subnetworks.get- Get subnet information for routingcompute.zones.get- Get zone information for location awarenesscompute.regions.get- Get region information for location awarenesscompute.projects.get- Get project information for service discovery
roles/artifactregistry.reader- Read container images from Artifact Registry (pull proxy container images for updates)roles/run.viewer- Read-only access to Cloud Run services (for service discovery)
Security Rationale: Proxy VMs have minimal read-only access to infrastructure for service discovery and content serving. Custom role provides only essential compute permissions instead of broad viewer access. No write access to compute or storage prevents proxies from modifying infrastructure.
The runner service account uses a custom IAM role with minimal required permissions:
Instance Lifecycle Management:
compute.instances.create- Create new workspace VMscompute.instances.delete- Delete terminated workspace VMscompute.instances.get- Get instance detailscompute.instances.list- List instances for monitoringcompute.instances.start- Start stopped instancescompute.instances.stop- Stop running instancescompute.instances.setLabels- Set labels for resource managementcompute.instances.setMetadata- Configure instance metadatacompute.instances.setTags- Set network tags for firewall rulescompute.instances.attachDisk- Attach persistent diskscompute.instances.detachDisk- Detach persistent diskscompute.instances.setDiskAutoDelete- Configure disk auto-deletioncompute.instances.setServiceAccount- Assign service accounts to VMscompute.instances.listReferrers- Check if instance is detached from MIG (warm pool)
Disk Management:
compute.disks.create- Create persistent disks for workspacescompute.disks.delete- Delete unused persistent diskscompute.disks.get- Get disk informationcompute.disks.list- List disks for managementcompute.disks.setLabels- Label boot and data disks for hyperdisk boost and dual-disk lifecycle trackingcompute.disks.update- Preserve claimed warm-pool data disks by updating disk propertiescompute.disks.createSnapshot- Snapshot detached data disks for dual-disk recoverycompute.disks.use- Attach persistent disks to workspace VMscompute.disks.useReadOnly- Use persistent disks as read-only image sources
Snapshot Management:
compute.snapshots.delete- Delete data disk snapshots when environments are deletedcompute.snapshots.get- Get data disk snapshot information for recoverycompute.snapshots.list- List data disk snapshots for recovery and readiness checks
Network Resources:
compute.networks.get- Get network configurationcompute.networks.list- List available networkscompute.networks.use- Use networks for VM creationcompute.subnetworks.get- Get subnet configurationcompute.subnetworks.list- List available subnetscompute.subnetworks.use- Use subnets for VM creationcompute.addresses.create- Create static IP addressescompute.addresses.delete- Delete unused IP addressescompute.addresses.get- Get IP address informationcompute.addresses.use- Assign IP addresses to VMs
Operations Monitoring:
compute.globalOperations.get- Monitor global operationscompute.regionOperations.get- Monitor regional operationscompute.zoneOperations.get- Monitor zonal operations
Resource Information:
compute.machineTypes.get- Get machine type detailscompute.machineTypes.list- List available machine typescompute.diskTypes.get- Get disk type informationcompute.diskTypes.list- List available disk typescompute.images.get- Get VM image detailscompute.images.list- List available imagescompute.images.useReadOnly- Use images for VM creation
Instance Templates and Groups:
compute.instanceTemplates.create- Create instance templatescompute.instanceTemplates.delete- Delete instance templatescompute.instanceTemplates.get- Get template informationcompute.instanceTemplates.getIamPolicy- Get template IAM policiescompute.instanceTemplates.list- List instance templatescompute.instanceTemplates.setIamPolicy- Set template IAM policiescompute.instanceTemplates.useReadOnly- Use templates for VM creationcompute.instanceGroupManagers.get- Get instance group detailscompute.instanceGroupManagers.list- List instance groupscompute.instanceGroupManagers.create- Create instance groupscompute.instanceGroupManagers.delete- Delete instance groupscompute.instanceGroupManagers.update- Update instance groupscompute.instanceGroups.delete- Delete underlying instance groups (required when deleting MIGs)compute.instanceGroups.list- List instance group memberscompute.autoscalers.list- List warm pool autoscalers for orphan cleanup
Log Persistence for Environments and Prebuilds:
logging.logEntries.list- Read environment logs from Cloud Logging for prebuild creationlogging.logEntries.create- Write prebuild logs to Cloud Logging for persistencelogging.logs.delete- Delete prebuild logs when prebuild is deleted to prevent orphaned data
Repository Management:
artifactregistry.repositories.get- Get repository informationartifactregistry.repositories.list- List repositoriesartifactregistry.repositories.create- Create repositories for image cacheartifactregistry.repositories.delete- Delete unused repositoriesartifactregistry.repositories.update- Update repository configuration
Image Management:
artifactregistry.dockerimages.get- Get Docker image informationartifactregistry.dockerimages.list- List Docker imagesartifactregistry.repositories.downloadArtifacts- Download container imagesartifactregistry.repositories.uploadArtifacts- Upload container images
Secret Management:
secretmanager.secrets.create- Create workspace secretssecretmanager.secrets.delete- Delete unused secretssecretmanager.secrets.get- Get secret metadatasecretmanager.secrets.list- List secretssecretmanager.secrets.getIamPolicy- Get secret IAM policiessecretmanager.secrets.setIamPolicy- Set secret IAM policiessecretmanager.versions.access- Access secret valuessecretmanager.versions.add- Add new secret versionssecretmanager.versions.destroy- Delete secret versions
Message Processing:
pubsub.subscriptions.get- Get subscription informationpubsub.subscriptions.list- List subscriptionspubsub.subscriptions.consume- Consume messages from subscriptionspubsub.topics.get- Get topic informationpubsub.topics.list- List topics
Service Account Management (project-level on the runner custom role):
iam.serviceAccounts.getIamPolicy- Get service account IAM policiesiam.serviceAccounts.setIamPolicy- Set service account IAM policies
Per-SA bindings (granted via google_service_account_iam_member on
specific SAs only):
roles/iam.serviceAccountUser(i.e.iam.serviceAccounts.actAs) on the runner, environment_vm, and proxy_vm service accounts. Required to attach those SAs to the instances and instance templates the runner creates.
The runner service account directly holds permissions for build cache (GCS), secret management, and pub/sub event processing. These were previously delegated to separate service accounts via impersonation but are now consolidated on the runner SA for simplicity.
Comprehensive audit logging is enabled for security monitoring:
- Service:
secretmanager.googleapis.com - Log Types:
DATA_READ- Logs secret access (no exemptions)DATA_WRITE- Logs secret creation/updatesADMIN_READ- Logs metadata access
- Service:
compute.googleapis.com - Log Types:
ADMIN_READ- Logs administrative read operationsDATA_WRITE- Logs data modification operations
- Service:
iam.googleapis.com - Log Types:
ADMIN_READ- Logs IAM policy readsDATA_WRITE- Logs IAM policy changes
- Service:
storage.googleapis.com - Log Types:
DATA_READ- Logs storage access (exempts environment VM service account for performance)DATA_WRITE- Logs storage modifications
- Exemptions:
{runner_name}-env-vm@{project_id}.iam.gserviceaccount.com(for performance - workspace file access generates high log volume)
- Each service account has only the minimum permissions required for its function
- OAuth scopes are restricted to necessary services
- Custom IAM roles limit permissions to specific operations instead of using broad predefined roles
- No service account has admin-level permissions except where absolutely necessary
- Firewall rules are managed via Terraform (no dynamic firewall permissions granted to service accounts)
- VMs use private IP addresses where possible
- Redis uses private service access with VPC peering
- Load balancer provides controlled external access with health checks
- Workspace secrets are isolated using dedicated service account with custom minimal permissions
- Secret access is fully audited with no exemptions
- Runner token and Redis credentials are stored in Secret Manager
- Secrets are automatically cleaned up when workspaces are deleted
- Multiple specialized service accounts instead of one powerful account
- Service account impersonation provides temporal access control
- Each service account is limited to its specific operational domain
- Cross-service access is explicitly controlled through IAM bindings
- Comprehensive audit logging for all critical services (Secret Manager, Compute, IAM, Storage)
- Service account impersonation and usage is tracked
- Resource access patterns can be analyzed for anomaly detection
- Centralized logging with structured filters for security events
This permission model balances security with functionality, ensuring Ona can operate effectively while maintaining strong isolation, auditability, and defense-in-depth security controls.