Connect GCP Project
Connect your GCP project using Workload Identity Federation for secure, keyless authentication.
Prerequisites
- GCP project with billing enabled
OwnerorIAM Adminrole on the projectgcloudCLI installed and configured
Option 1: Workload Identity Federation (Recommended)
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
- Go to Providers → Add Provider → GCP
- Enter your Project ID
- Enter the Workload Identity Provider resource name
- Select which Regions to scan
- Click Test Connection
- Click Save Provider
Option 2: Service Account Key (Not Recommended)
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
- Go to Providers → Add Provider → GCP
- Select Service Account Key
- Upload the
nightops-key.jsonfile - Click Save Provider
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
- Verify all required APIs are enabled
- Check the service account has the required roles
- 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
- Verify the provider resource name is complete
- Check the OIDC issuer URI is correct
- 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
- Use Workload Identity Federation — No keys to rotate or leak
- Least Privilege — Only grant required roles
- Audit Logging — Enable Cloud Audit Logs for the service account
- 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'