Skip to content

GCP

This guide extends the Quickstart to use a real GCP project instead of the mock provider. By the end you will have submitted, approved, and executed against a live GCP IAM binding — and verified that GCP enforces the TTL natively at the cloud layer, with no dependency on the jitsudo expiry sweeper.

  • A working jitsudo local environment (from the Quickstart)
  • A GCP project you control (a sandbox or personal project is fine)
  • The gcloud CLI installed and authenticated
  • roles/iam.securityAdmin or roles/owner on the project
Terminal window
gcloud services enable iam.googleapis.com \
cloudresourcemanager.googleapis.com \
--project YOUR_PROJECT_ID

Step 2: Create a Service Account for jitsudod

Section titled “Step 2: Create a Service Account for jitsudod”

jitsudod needs a GCP service account identity to call the IAM API on behalf of your deployment. In production this would use Workload Identity Federation; for local development, a service account key is simplest.

Terminal window
# Create the service account
gcloud iam service-accounts create jitsudo-control-plane \
--display-name "jitsudo control plane" \
--project YOUR_PROJECT_ID
# Store the full email for later steps
SA_EMAIL="jitsudo-control-plane@YOUR_PROJECT_ID.iam.gserviceaccount.com"

jitsudod needs roles/iam.securityAdmin (or a custom role with resourcemanager.projects.getIamPolicy and resourcemanager.projects.setIamPolicy) to create and delete IAM bindings:

Terminal window
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:${SA_EMAIL}" \
--role="roles/iam.securityAdmin"

For local development, create and download a service account key:

Terminal window
gcloud iam service-accounts keys create ./jitsudo-sa-key.json \
--iam-account="${SA_EMAIL}" \
--project YOUR_PROJECT_ID

Add the GCP provider block to your jitsudod.yaml:

providers:
gcp:
project_id: "YOUR_PROJECT_ID"
max_duration: "2h"

Set the credentials environment variable:

Terminal window
export GOOGLE_APPLICATION_CREDENTIALS="$(pwd)/jitsudo-sa-key.json"

Restart jitsudod with make docker-up (or your equivalent).

Terminal window
cat > gcp-eligibility.rego << 'EOF'
package jitsudo.eligibility
import future.keywords.if
default allow = false
default reason = "not authorized"
allow if {
input.user.groups[_] == "sre"
input.request.provider == "gcp"
input.request.role == "roles/storage.objectViewer"
input.request.duration_seconds <= 3600
}
reason = "allowed" if { allow }
EOF
jitsudo policy apply -f gcp-eligibility.rego \
--type eligibility \
--name gcp-sandbox-eligibility
Terminal window
jitsudo request \
--provider gcp \
--role roles/storage.objectViewer \
--scope YOUR_PROJECT_ID \
--duration 30m \
--reason "Testing real GCP provider - sandbox"

You should see:

✓ Request submitted (ID: req_01...)
⏳ Awaiting approval

In a second terminal:

Terminal window
jitsudo approve req_01...
Terminal window
# List Cloud Storage buckets using the elevated binding
jitsudo exec req_01... -- gcloud storage buckets list \
--project YOUR_PROJECT_ID

The exec command injects GOOGLE_CLOUD_PROJECT and CLOUDSDK_CORE_PROJECT into the subprocess. The IAM binding grants roles/storage.objectViewer to your user identity on the project.

Step 9: Understand GCP’s Native TTL Enforcement

Section titled “Step 9: Understand GCP’s Native TTL Enforcement”

GCP IAM Conditions support time-bound bindings natively. jitsudo uses conditions on the IAM binding to enforce the TTL at the GCP layer — this is fundamentally different from AWS and Azure.

Inspect the binding jitsudo created:

Terminal window
gcloud projects get-iam-policy YOUR_PROJECT_ID \
--format=json \
| jq '.bindings[] | select(.role == "roles/storage.objectViewer")'

You will see something like:

{
"condition": {
"expression": "request.time < timestamp(\"2026-03-20T18:30:00Z\")",
"title": "jitsudo-req_01...-expiry"
},
"members": ["user:you@example.com"],
"role": "roles/storage.objectViewer"
}

GCP will refuse requests using this binding after the timestamp in the condition expression — regardless of whether jitsudod is running. This is a security property that requires no trust in jitsudo’s availability. AWS requires jitsudod to attach a deny policy to revoke; Azure relies entirely on jitsudod’s expiry sweeper. GCP’s native TTL stands on its own.

Terminal window
jitsudo audit --request req_01...

You should see request.created, request.approved, grant.issued. After the TTL expires, grant.expired will appear — GCP has already enforced the expiry independently via the IAM condition.

Terminal window
jitsudo revoke req_01...

This calls setIamPolicy to remove the binding immediately, before the IAM condition would have expired it naturally. Verify revocation:

Terminal window
jitsudo exec req_01... -- gcloud storage buckets list \
--project YOUR_PROJECT_ID
# Should fail: PERMISSION_DENIED
Terminal window
# The IAM binding is removed automatically on revocation or expiry.
# Delete the service account key used for local development:
gcloud iam service-accounts keys delete KEY_ID \
--iam-account="${SA_EMAIL}" \
--project YOUR_PROJECT_ID
# Optionally remove the service account entirely:
gcloud iam service-accounts delete "${SA_EMAIL}" \
--project YOUR_PROJECT_ID
  • See the full GCP Provider guide for production configuration, including Workload Identity Federation, custom roles, and multi-project setups
  • See Security Hardening before deploying to production