Skip to main content

Connect GCP Project

Connect your GCP project using Workload Identity Federation for secure, keyless authentication.

Prerequisites

  • GCP project with billing enabled
  • Owner or IAM Admin role on the project
  • gcloud CLI installed and configured

Workload Identity Federation allows NightOps to authenticate without storing service account keys.

Step 1: Enable Required APIs

PROJECT_ID="your-project-id"

gcloud services enable \
compute.googleapis.com \
sqladmin.googleapis.com \
container.googleapis.com \
run.googleapis.com \
cloudfunctions.googleapis.com \
iam.googleapis.com \
iamcredentials.googleapis.com \
cloudresourcemanager.googleapis.com \
--project=$PROJECT_ID

Step 2: Create Workload Identity Pool

gcloud iam workload-identity-pools create nightops-pool \
--location="global" \
--display-name="NightOps Pool" \
--description="Workload identity pool for NightOps integration" \
--project=$PROJECT_ID

Step 3: Add OIDC Provider

# Get the pool name
POOL_NAME=$(gcloud iam workload-identity-pools describe nightops-pool \
--location="global" \
--project=$PROJECT_ID \
--format="value(name)")

# Add NightOps as an OIDC provider
gcloud iam workload-identity-pools providers create-oidc nightops-provider \
--location="global" \
--workload-identity-pool="nightops-pool" \
--issuer-uri="https://auth.nightops.io" \
--allowed-audiences="nightops" \
--attribute-mapping="google.subject=assertion.sub,attribute.org_id=assertion.org_id" \
--project=$PROJECT_ID

Step 4: Create Service Account

gcloud iam service-accounts create nightops-sa \
--display-name="NightOps Service Account" \
--description="Service account for NightOps resource management" \
--project=$PROJECT_ID

Step 5: Grant Required Roles

SA_EMAIL="nightops-sa@${PROJECT_ID}.iam.gserviceaccount.com"

# Compute Engine
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SA_EMAIL}" \
--role="roles/compute.instanceAdmin.v1"

# Cloud SQL
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SA_EMAIL}" \
--role="roles/cloudsql.admin"

# GKE
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SA_EMAIL}" \
--role="roles/container.clusterAdmin"

# Cloud Run
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SA_EMAIL}" \
--role="roles/run.admin"

# Cloud Functions
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SA_EMAIL}" \
--role="roles/cloudfunctions.admin"

# Service Account User (for impersonation)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SA_EMAIL}" \
--role="roles/iam.serviceAccountUser"

Step 6: Allow Workload Identity Impersonation

# Get your NightOps org ID from the dashboard
NIGHTOPS_ORG_ID="your-org-id-from-dashboard"

gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/${POOL_NAME}/attribute.org_id/${NIGHTOPS_ORG_ID}" \
--project=$PROJECT_ID

Step 7: Get Provider Resource Name

# Get the full provider resource name for NightOps
gcloud iam workload-identity-pools providers describe nightops-provider \
--location="global" \
--workload-identity-pool="nightops-pool" \
--project=$PROJECT_ID \
--format="value(name)"

Output format:

projects/123456789/locations/global/workloadIdentityPools/nightops-pool/providers/nightops-provider

Step 8: Configure in NightOps

  1. Go to Providers → Add Provider → GCP
  2. Enter your Project ID
  3. Enter the Workload Identity Provider resource name
  4. Select which Regions to scan
  5. Click Test Connection
  6. Click Save Provider

For environments that don't support Workload Identity Federation:

Create Key

gcloud iam service-accounts keys create nightops-key.json \
--iam-account=nightops-sa@${PROJECT_ID}.iam.gserviceaccount.com

Upload to NightOps

  1. Go to Providers → Add Provider → GCP
  2. Select Service Account Key
  3. Upload the nightops-key.json file
  4. Click Save Provider
warning

Service account keys are less secure than Workload Identity Federation. Keys can be leaked, don't expire automatically, and are harder to audit. Use Workload Identity Federation when possible.


Multi-Region Support

NightOps can manage resources across multiple GCP regions.

When adding the provider, select which regions to scan:

Regions: us-central1, us-east1, europe-west1

Multi-Project Setup

For organizations with multiple GCP projects:

Option A: Separate Providers

Create a service account and workload identity configuration in each project. Add each as a separate provider in NightOps.

Option B: Cross-Project Access

Grant the service account access to multiple projects:

# In the target project
gcloud projects add-iam-policy-binding TARGET_PROJECT_ID \
--member="serviceAccount:nightops-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/compute.instanceAdmin.v1"

Add all project IDs when configuring the provider in NightOps.


Terraform Module

# nightops.tf

variable "project_id" {
type = string
}

variable "nightops_org_id" {
description = "NightOps organization ID from dashboard"
type = string
}

# Enable APIs
resource "google_project_service" "apis" {
for_each = toset([
"compute.googleapis.com",
"sqladmin.googleapis.com",
"container.googleapis.com",
"run.googleapis.com",
"iam.googleapis.com",
"iamcredentials.googleapis.com",
"cloudresourcemanager.googleapis.com"
])

project = var.project_id
service = each.value
}

# Workload Identity Pool
resource "google_iam_workload_identity_pool" "nightops" {
project = var.project_id
workload_identity_pool_id = "nightops-pool"
display_name = "NightOps Pool"
}

# OIDC Provider
resource "google_iam_workload_identity_pool_provider" "nightops" {
project = var.project_id
workload_identity_pool_id = google_iam_workload_identity_pool.nightops.workload_identity_pool_id
workload_identity_pool_provider_id = "nightops-provider"
display_name = "NightOps Provider"

oidc {
issuer_uri = "https://auth.nightops.io"
allowed_audiences = ["nightops"]
}

attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.org_id" = "assertion.org_id"
}
}

# Service Account
resource "google_service_account" "nightops" {
project = var.project_id
account_id = "nightops-sa"
display_name = "NightOps Service Account"
}

# IAM Bindings
resource "google_project_iam_member" "nightops" {
for_each = toset([
"roles/compute.instanceAdmin.v1",
"roles/cloudsql.admin",
"roles/container.clusterAdmin",
"roles/run.admin",
"roles/iam.serviceAccountUser"
])

project = var.project_id
role = each.value
member = "serviceAccount:${google_service_account.nightops.email}"
}

# Allow Workload Identity
resource "google_service_account_iam_member" "nightops_wif" {
service_account_id = google_service_account.nightops.name
role = "roles/iam.workloadIdentityUser"
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.nightops.name}/attribute.org_id/${var.nightops_org_id}"
}

output "workload_identity_provider" {
value = google_iam_workload_identity_pool_provider.nightops.name
}

Troubleshooting

"Permission denied" on Test Connection

  1. Verify all required APIs are enabled
  2. Check the service account has the required roles
  3. Verify Workload Identity binding is correct
# Check service account roles
gcloud projects get-iam-policy $PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.members:nightops-sa@" \
--format="table(bindings.role)"

"Invalid provider" error

  1. Verify the provider resource name is complete
  2. Check the OIDC issuer URI is correct
  3. Ensure allowed audiences include "nightops"
# Verify provider configuration
gcloud iam workload-identity-pools providers describe nightops-provider \
--location="global" \
--workload-identity-pool="nightops-pool" \
--project=$PROJECT_ID

Cloud SQL instances not discovered

Cloud SQL Admin API must be enabled:

gcloud services enable sqladmin.googleapis.com --project=$PROJECT_ID

Security Best Practices

  1. Use Workload Identity Federation — No keys to rotate or leak
  2. Least Privilege — Only grant required roles
  3. Audit Logging — Enable Cloud Audit Logs for the service account
  4. Conditional IAM — Restrict by resource labels if needed

Label-Based Access Control

Limit NightOps to only manage labeled resources using IAM Conditions:

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SA_EMAIL}" \
--role="roles/compute.instanceAdmin.v1" \
--condition='expression=resource.matchLabels("nightops-managed", "true"),title=nightops-only'

Next Steps