README
¶
GCP IAM Emulator
Policy engine for the Local IAM Control Plane — Evaluate permissions before data access, make emulators fail for the same authorization reasons production would.
This is the brain of the Blackwell Local IAM Control Plane. It evaluates IAM policies and tells service emulators (Secret Manager, KMS) whether to allow or deny requests.
Unlike mocks (which allow everything) or observers (which record after the fact), this actively enforces policies before requests reach data planes.
Quick Example
# policy.yaml - Define exactly what your tests need
roles:
roles/custom.ciRunner:
permissions:
- secretmanager.secrets.get
- secretmanager.versions.access
- cloudkms.cryptoKeys.encrypt
groups:
developers:
members:
- user:alice@example.com
- user:bob@example.com
projects:
test-project:
bindings:
- role: roles/viewer
members:
- group:developers
- role: roles/custom.ciRunner
members:
- serviceAccount:ci@test-project.iam.gserviceaccount.com
condition:
expression: 'resource.name.startsWith("projects/test-project/secrets/prod-")'
title: "CI limited to production secrets"
# Start with strict mode (default - catches misconfigurations)
server --config policy.yaml --trace
# HTTP REST API
server --config policy.yaml --http-port 8081
# Hot reload on config changes
server --config policy.yaml --watch
Result: Local IAM decisions matching your policy, offline testing of authorization logic, CI-ready without GCP credentials.
Usage Modes
Standalone - Run independently as a policy engine:
server --config policy.yaml
# Single IAM server, use for custom emulators
Unified Ecosystem - Use with gcp-emulator for unified multi-service testing in a single process:
go install github.com/blackwell-systems/gcp-emulator/cmd/gcp-emulator@latest
gcp-emulator --policy policy.yaml --iam-mode strict
# IAM + Secret Manager + KMS + Eventarc
# Single process, single port, single policy file
Choose standalone for custom integrations, gcp-emulator for the complete GCP emulator stack.
How to Provide Principals
The emulator needs to know who is making each request. Provide identity via metadata/headers:
gRPC Metadata (Go SDK Example)
import "google.golang.org/grpc/metadata"
// Inject principal identity
md := metadata.Pairs("x-emulator-principal", "serviceAccount:ci@project.iam.gserviceaccount.com")
ctx = metadata.NewOutgoingContext(context.Background(), md)
// Now use ctx for API calls - emulator sees the principal
client.GetSecretVersion(ctx, &secretmanagerpb.GetSecretVersionRequest{...})
HTTP Header (REST API / curl)
curl -X POST http://localhost:8081/v1/projects/test/secrets/api-key:testIamPermissions \
-H "X-Emulator-Principal: serviceAccount:ci@project.iam.gserviceaccount.com" \
-H "Content-Type: application/json" \
-d '{"permissions": ["secretmanager.secrets.get"]}'
Supported Principal Formats
- Service accounts:
serviceAccount:name@project.iam.gserviceaccount.com - Users:
user:alice@example.com - Groups:
group:eng-team@example.com(define groups in policy.yaml) - All authenticated:
allAuthenticatedUsers - Public:
allUsers
Integration with Emulators
When using with Secret Manager / KMS emulators, the data plane emulators automatically forward the principal to the IAM control plane:
// Your test code sets principal once
ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs(
"x-emulator-principal", "serviceAccount:ci@test.iam.gserviceaccount.com",
))
// Secret Manager emulator forwards principal to IAM emulator automatically
client.AccessSecretVersion(ctx, &secretmanagerpb.AccessSecretVersionRequest{...})
// ↓ Internally: IAM checks if ci@test.iam can secretmanager.versions.access
No additional configuration needed - the emulator ecosystem handles principal propagation.
Architecture — Control Plane Position
┌─────────────────────────────────────────┐
│ Your Application Code │
│ (GCP client libraries) │
└────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ DATA PLANES │
│ • Secret Manager Emulator │
│ • KMS Emulator │
│ • (Future: Tasks, Pub/Sub, Storage) │
│ │
│ Each checks IAM before data access │
└────────────────┬────────────────────────┘
│
│ CheckPermission(principal, resource, permission)
▼
┌─────────────────────────────────────────┐
│ CONTROL PLANE (THIS REPO) │◄── You are here
│ IAM Emulator — Policy Engine │
│ │
│ Evaluates: │
│ • Role bindings │
│ • Group memberships │
│ • Conditional policies (CEL) │
│ • Resource-level policy evaluation │
│ │
│ Returns: Allow / Deny │
└─────────────────────────────────────────┘
This is the enforcement boundary. Requests are authorized here before data access.
| Approach | Example | When | Behavior |
|---|---|---|---|
| Mock | Standard emulators | Never | Always allows |
| Observer | Post-execution analysis | After | Records what you used |
| Control Plane | Blackwell IAM | Before | Denies unauthorized |
Deterministic Consistency (The CI/CD Killer Feature)
The Problem with Real GCP IAM:
GCP IAM is eventually consistent. When you create or update a policy binding:
- Changes can take 1-60 seconds to propagate globally
- Your tests become flaky (sometimes pass, sometimes fail)
- CI/CD pipelines have random failures you can't reproduce
The Blackwell Difference:
This emulator is strongly consistent. Policy changes are:
- Instant (0ms propagation delay)
- Deterministic (same input = same output, every time)
- Repeatable (run the test 1000 times, get the same result)
| Dimension | Real GCP IAM | Blackwell IAM Emulator |
|---|---|---|
| Consistency Model | Eventually consistent | Strongly consistent |
| Propagation Delay | 1-60 seconds | 0ms (immediate) |
| Test Flakiness | High (timing-dependent) | Zero (deterministic) |
| CI/CD Reliability | Unpredictable | Fully repeatable |
| Network Dependency | Required | None |
| Cost per Test Run | API charges | Free (local) |
"Eventual consistency is the enemy of CI/CD. This emulator gives you instant, deterministic IAM testing—no more flaky tests, no more waiting for propagation, no more Friday night debugging."
What This Is (and Isn't)
GCP IAM Emulator is a deterministic, local policy engine for testing cloud authorization logic.
Scope note: This emulator is a deterministic IAMPolicy engine for CI testing. It does not attempt full Google Cloud IAM parity (org/folder hierarchy, deny policies, full CEL).
It is not a full reimplementation of Google Cloud IAM, and it does not attempt perfect fidelity.
Instead, it provides:
- Deterministic permission evaluation - Test "who can access what" locally (within your policy.yaml-defined permission universe)
- Strict, offline policy modeling - No GCP credentials or network required
- Composable auth layer - Foundation for local GCP emulator ecosystems
Users define their own permission universe. The emulator enforces it.
Goal: Catch authorization bugs in CI (missing permissions, wrong roles, misconfigured principals).
Non-goal: Mirror every edge case of Google IAM. If your test passes locally but fails in real GCP, refine your custom role definitions.
The built-in roles are intentionally small. The emulator is infinite via custom roles.
Why This IAM Emulator Uses Curated Permissions (On Purpose)
This IAM emulator is deliberately scoped for authorization testing, not comprehensive IAM replication. We model a small set of built-in roles (primitives + Secret Manager + KMS) plus unlimited custom role definitions to catch the bugs that actually break production: missing permissions, wrong role assignments, and misconfigured principals. This curated-first approach catches 95% of real-world authorization bugs while maintaining hermetic execution (no GCP credentials required), deterministic behavior (0ms propagation delay vs 1-60s in real GCP), and zero maintenance burden from tracking GCP's evolving role catalog. If you need to test additional GCP services or permissions, define them explicitly in policy.yaml as custom roles — this explicit approach is simpler, more reliable, and avoids the catalog staleness problem that plagues comprehensive IAM emulation. We optimize for authorization failures that matter, not theoretical IAM completeness.
Features
- Complete IAMPolicy API surface - SetIamPolicy, GetIamPolicy, TestIamPermissions (gRPC + REST)
- Deterministic Permission Evaluation - Explicit role→permission definitions (built-in bootstrap roles + YAML-defined custom roles)
- Conditional Bindings - CEL expression support for resource-based access control
- Groups Support - Define reusable groups with nested membership (1 level)
- Policy Schema v3 - Full support for etag, version, auditConfigs, conditions
- Enhanced Trace Mode - JSON output, verbose logging, duration metrics
- Custom Roles - Define any GCP permission in YAML (extensible, not hardcoded)
- Small Built-in Core - Primitive roles + Secret Manager + KMS (bootstrap only)
- No GCP Credentials - Works entirely offline without authentication
- Fast & Lightweight - In-memory storage, starts in milliseconds
- Thread-Safe - Concurrent access with proper synchronization
- Integrates with Emulators - Works with gcp-secret-manager-emulator, gcp-kms-emulator
Supported Operations
IAM Policy Management
SetIamPolicy- Set IAM policy on any resourceGetIamPolicy- Retrieve IAM policy for a resourceTestIamPermissions- Check which permissions are granted
Built-in Roles (Bootstrap Set)
The emulator includes a small built-in set for immediate use. For production tests, define custom roles in YAML.
Primitive roles:
roles/owner- Full access to all resourcesroles/editor- Read/write access (no IAM management, no delete)roles/viewer- Read-only access
Secret Manager roles:
roles/secretmanager.admin- Full secret managementroles/secretmanager.secretAccessor- Read secret values onlyroles/secretmanager.secretVersionManager- Manage versions
KMS roles:
roles/cloudkms.admin- Full KMS managementroles/cloudkms.cryptoKeyEncrypterDecrypter- Encrypt/decrypt onlyroles/cloudkms.viewer- Read-only KMS access
Total: 10 built-in roles, 26 permissions
Need more services? Define custom roles in YAML - see Custom Roles section below.
Quick Start
Install
go install github.com/blackwell-systems/gcp-iam-emulator/cmd/server@latest
Run Server
Basic:
# Start on default port 8080
server
# Custom port
server --port 9090
With policy config (recommended for CI):
# Load policies from YAML
server --config policy.yaml
# Enable trace mode for debugging
server --config policy.yaml --trace
# Enable HTTP REST API
server --config policy.yaml --http-port 8081
# Enable verbose trace with JSON output
server --config policy.yaml --explain --trace-output trace.json
# Hot reload policies on file changes
server --config policy.yaml --watch
Docker:
# Run with mounted config
docker run -p 8080:8080 -v $(pwd)/policy.yaml:/policy.yaml \
ghcr.io/blackwell-systems/gcp-iam-emulator:latest --config /policy.yaml
# Run with trace mode
docker run -p 8080:8080 \
ghcr.io/blackwell-systems/gcp-iam-emulator:latest --trace
Example Policy Config
Create policy.yaml:
# Define custom roles for your test environment
roles:
roles/custom.dataReader:
permissions:
- bigquery.datasets.get
- bigquery.tables.list
projects:
test-project:
bindings:
- role: roles/owner
members:
- user:admin@example.com
- role: roles/custom.dataReader
members:
- user:analyst@example.com
- role: roles/secretmanager.secretAccessor
members:
- serviceAccount:ci@test-project.iam.gserviceaccount.com
resources:
secrets/db-password:
bindings:
- role: roles/secretmanager.secretAccessor
members:
- serviceAccount:app@test-project.iam.gserviceaccount.com
Note: The emulator includes built-in roles for primitives + Secret Manager + KMS. For other GCP services, define custom roles as shown above.
Use with GCP SDK
Go client with principal injection:
package main
import (
"context"
iampb "google.golang.org/genproto/googleapis/iam/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
)
func main() {
ctx := context.Background()
conn, _ := grpc.NewClient(
"localhost:8080",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
defer conn.Close()
client := iampb.NewIAMPolicyClient(conn)
// Inject principal identity via metadata
md := metadata.Pairs("x-emulator-principal", "serviceAccount:ci@test-project.iam.gserviceaccount.com")
ctx = metadata.NewOutgoingContext(ctx, md)
// Test permissions (checks if this principal has access)
resp, _ := client.TestIamPermissions(ctx, &iampb.TestIamPermissionsRequest{
Resource: "projects/test-project/secrets/db-password",
Permissions: []string{
"secretmanager.versions.access",
"secretmanager.secrets.delete",
},
})
// resp.Permissions = ["secretmanager.versions.access"]
// (delete denied - secretAccessor role doesn't include it)
}
Setting policies dynamically (no config file):
// Set policy via API
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"serviceAccount:ci@my-project.iam.gserviceaccount.com",
},
},
},
}
client.SetIamPolicy(ctx, &iampb.SetIamPolicyRequest{
Resource: "projects/my-project/secrets/my-secret",
Policy: policy,
})
Use Cases
- CI/CD Pipelines - Drop-in IAM for hermetic testing without GCP credentials
- Policy Development - Iterate on IAM policies locally with instant feedback
- Security Testing - Validate "who can access what" before production
- Permission Debugging - Trace mode explains why access was granted/denied
- Integration Testing - Real permission evaluation with Secret Manager + KMS emulators
- Cost Reduction - Avoid GCP API charges during development
CI/CD Integration
GitHub Actions
name: Integration Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
iam-emulator:
image: ghcr.io/blackwell-systems/gcp-iam-emulator:latest
ports:
- 8080:8080
options: --mount type=bind,source=${{ github.workspace }}/policy.yaml,target=/policy.yaml
args: --config /policy.yaml --trace
steps:
- uses: actions/checkout@v4
- name: Run integration tests
env:
IAM_EMULATOR_HOST: localhost:8080
run: |
go test ./...
Docker Compose
Full GCP emulator stack:
# docker-compose.yml
services:
iam:
image: ghcr.io/blackwell-systems/gcp-iam-emulator:latest
ports:
- "8080:8080"
volumes:
- ./policy.yaml:/policy.yaml
command: --config /policy.yaml --trace
secret-manager:
image: ghcr.io/blackwell-systems/gcp-secret-manager-emulator:latest
environment:
IAM_EMULATOR_HOST: iam:8080
ports:
- "9090:9090"
depends_on:
- iam
kms:
image: ghcr.io/blackwell-systems/gcp-kms-emulator:latest
environment:
IAM_EMULATOR_HOST: iam:8080
ports:
- "9091:9090"
depends_on:
- iam
Run:
docker-compose up
# Your tests connect to localhost:8080 (IAM), localhost:9090 (Secret Manager), localhost:9091 (KMS)
Trace Mode
Enable trace mode to debug authorization decisions:
server --config policy.yaml --trace
Example output:
2026/01/26 10:30:15 GCP IAM Emulator v0.2.0
2026/01/26 10:30:15 Loading policy config from policy.yaml
2026/01/26 10:30:15 Loaded 3 policies from config
2026/01/26 10:30:15 Trace mode: ENABLED (authz decisions will be logged)
2026/01/26 10:30:15 Server ready - listening on :8080
level=INFO msg="authz decision" decision=ALLOW principal=serviceAccount:ci@test.iam.gserviceaccount.com resource=projects/test/secrets/api-key permission=secretmanager.versions.access reason="matched binding: role=roles/secretmanager.secretAccessor member=serviceAccount:ci@test.iam.gserviceaccount.com"
level=INFO msg="authz decision" decision=DENY principal=user:dev@example.com resource=projects/test/secrets/db-password permission=secretmanager.secrets.delete reason="no matching binding found for principal"
Use trace mode to:
- Understand why access was denied
- Debug policy inheritance
- Verify principal matching
- Audit authz decisions in local testing
Enhanced trace mode (v0.3.0+):
# Verbose logging with --explain
server --config policy.yaml --explain
# JSON output to file
server --config policy.yaml --trace-output trace.json
JSON trace format:
{
"time":"2026-01-26T10:30:15Z",
"level":"INFO",
"msg":"permission_check",
"resource":"projects/test/secrets/api-key",
"principal":"serviceAccount:ci@test.iam.gserviceaccount.com",
"allowed_permissions":["secretmanager.versions.access"],
"duration_ms":2,
"timestamp":"2026-01-26T10:30:15Z"
}
Authorization Tracing
Structured logging of IAM decisions for debugging, auditing, and testing.
Enable Tracing
# Emit structured traces to file
IAM_TRACE_OUTPUT=./authz-trace.jsonl ./server --config policy.yaml
# Or to stdout for debugging
IAM_TRACE_OUTPUT=stdout ./server --config policy.yaml
Use Cases
Debug Permission Denials:
# See exactly why access was denied
cat authz-trace.jsonl | jq 'select(.decision.outcome=="DENY")'
# Output shows principal, resource, permission, and reason
Audit Test Coverage:
# List all permissions your tests actually exercised
cat authz-trace.jsonl | jq -r '.action.permission' | sort -u
# See which principals were tested
cat authz-trace.jsonl | jq -r '.actor.principal' | sort -u
Validate Policy Changes:
# Before policy change
IAM_TRACE_OUTPUT=./before.jsonl go test ./...
# After policy change
IAM_TRACE_OUTPUT=./after.jsonl go test ./...
# Compare outcomes (detect regressions)
diff <(jq -r '.decision.outcome' before.jsonl | sort) \
<(jq -r '.decision.outcome' after.jsonl | sort)
CI/CD Compliance:
# Prove CI only accessed allowed resources
cat ci-audit.jsonl | \
jq -r 'select(.decision.outcome=="ALLOW") | .target.resource' | \
grep -v "projects/prod/" && echo "❌ Unauthorized access" || echo "✅ Compliant"
Trace Event Schema
Each trace event is a single JSON line with:
- Actor:
actor.principal(who) - Target:
target.resource(what) - Action:
action.permission(which permission) - Decision:
decision.outcome(ALLOW or DENY) - Reason:
decision.reason(why) - Timing:
decision.latency_ms(performance)
Example event:
{"schema_version":"1.0","event_type":"authz_check","timestamp":"2026-01-28T10:15:23.483Z","actor":{"principal":"user:alice@example.com"},"target":{"resource":"projects/test/secrets/db-password"},"action":{"permission":"secretmanager.secrets.get"},"decision":{"outcome":"ALLOW","reason":"binding_match","latency_ms":3}}
See gcp-emulator-auth/pkg/trace for complete schema definition.
v0.3.0 Features
Conditional Bindings
Use CEL expressions to restrict access based on resource properties:
projects:
test-project:
bindings:
# CI can only access production secrets
- role: roles/secretmanager.secretAccessor
members:
- serviceAccount:ci@test-project.iam.gserviceaccount.com
condition:
expression: 'resource.name.startsWith("projects/test-project/secrets/prod-")'
title: "Production secrets only"
description: "CI service account restricted to production secrets"
# Time-based access
- role: roles/cloudkms.cryptoKeyEncrypterDecrypter
members:
- serviceAccount:temp-access@test-project.iam.gserviceaccount.com
condition:
expression: 'request.time < timestamp("2026-12-31T23:59:59Z")'
title: "Temporary access"
Supported CEL expressions:
resource.name.startsWith("prefix")- Match resource name prefixresource.type == "SECRET"- Match resource type (SECRET, CRYPTO_KEY, KEY_RING)request.time < timestamp("2026-12-31T00:00:00Z")- Time-based access
Groups Support
Define reusable groups to reduce duplication:
groups:
developers:
members:
- user:alice@example.com
- user:bob@example.com
- serviceAccount:dev-bot@test-project.iam.gserviceaccount.com
operators:
members:
- user:ops@example.com
- group:oncall # Nested groups (1 level supported)
oncall:
members:
- user:charlie@example.com
- user:diana@example.com
projects:
test-project:
bindings:
- role: roles/viewer
members:
- group:developers # Reference group
REST API
HTTP REST gateway for all IAM operations:
# Start with REST API
server --config policy.yaml --http-port 8081
Example requests:
# Set IAM policy
curl -X POST http://localhost:8081/v1/projects/test-project:setIamPolicy \
-H "Content-Type: application/json" \
-d '{
"policy": {
"bindings": [{
"role": "roles/viewer",
"members": ["user:dev@example.com"]
}]
}
}'
# Get IAM policy
curl http://localhost:8081/v1/projects/test-project:getIamPolicy
# Test permissions
curl -X POST http://localhost:8081/v1/projects/test-project/secrets/api-key:testIamPermissions \
-H "Content-Type: application/json" \
-H "X-Emulator-Principal: serviceAccount:ci@test.iam.gserviceaccount.com" \
-d '{
"permissions": [
"secretmanager.versions.access",
"secretmanager.secrets.delete"
]
}'
Response:
{
"permissions": ["secretmanager.versions.access"]
}
Policy Schema v3
Full support for IAM Policy v3 features:
- etag - Optimistic concurrency control (SHA256-based)
- version - Policy format version (1=basic, 3=with conditions)
- auditConfigs - Audit logging configuration
- bindings[].condition - Conditional role bindings
projects:
test-project:
auditConfigs:
- service: secretmanager.googleapis.com
auditLogConfigs:
- logType: ADMIN_READ
- logType: DATA_READ
- logType: DATA_WRITE
exemptedMembers:
- serviceAccount:logging@test-project.iam.gserviceaccount.com
Custom Roles (v0.4.0)
Define your own role-to-permission mappings for any GCP service:
roles:
roles/custom.dataReader:
permissions:
- bigquery.datasets.get
- bigquery.tables.list
- bigquery.tables.getData
roles/custom.pubsubPublisher:
permissions:
- pubsub.topics.publish
- pubsub.topics.get
roles/custom.storageAdmin:
permissions:
- storage.buckets.create
- storage.buckets.delete
- storage.objects.create
- storage.objects.delete
projects:
test-project:
bindings:
- role: roles/custom.dataReader
members:
- user:analyst@example.com
Features:
- Extensible - Define permissions for any GCP service
- Override built-in roles - Custom roles take precedence
- Strict mode by default - Unknown roles denied (catches misconfigurations)
- Compat mode available - Wildcard fallback with
--allow-unknown-rolesroles/secretmanager.customRole→ grantssecretmanager.*roles/cloudkms.encryptOnly→ grantscloudkms.*
Why this matters:
- GCP has thousands of permissions - hardcoding doesn't scale
- Each test environment needs different permissions
- Keeps emulator offline, deterministic, and CI-friendly
Modes:
Strict mode (default, recommended):
server --config policy.yaml
- Unknown roles → DENIED
- Custom roles → allowed
- Built-in roles → allowed
- Catches bugs: Tests fail if you use a role you haven't defined
Compat mode (less strict):
server --config policy.yaml --allow-unknown-roles
- Unknown roles → wildcard match (if service prefix matches)
- More permissive, but can hide bugs
- Use when migrating existing tests
Decision order:
- Custom roles (highest priority)
- Built-in roles (primitives + Secret Manager + KMS)
- Wildcard match (only in compat mode)
- Deny (strict mode default)
Architecture
In-memory policy storage with thread-safe concurrent access. Simple permission engine mapping roles to permissions. Resource-level policies (no organization/folder hierarchy in MVP). No token minting (pure policy evaluation only).
Roadmap
Future Considerations:
Role Packs (optional convenience):
- Optional import packs like
packs/pubsub.yaml,packs/bigquery.yaml - Users import only what they need
- Community-maintained, not hardcoded in emulator
- Example:
roles: !include packs/storage.yaml
NOT planned:
- Large built-in permission database (creates maintenance hell)
- Auto-syncing with GCP IAM API (adds network dependency)
- Perfect GCP IAM fidelity (not the goal)
Strategy: Keep the emulator focused and sustainable. Users define what they need via custom roles. The built-in set stays small (primitives + Secret Manager + KMS only).
See ROADMAP.md for full details.
API Parity with GCP IAM
What's Implemented
Methods:
SetIamPolicy- Full implementationGetIamPolicy- Full implementationTestIamPermissions- Full implementation with principal matching
Policy Fields:
bindings[]- Role assignments with membersrole- IAM role stringmembers[]- Principal identifiers
version- Policy format version (1=basic, 3=conditions)etag- Optimistic concurrency control (SHA256-based)auditConfigs[]- Audit logging configurationbindings[].condition- Conditional role bindings (CEL expressions)
Features:
- Principal injection via gRPC metadata
- Resource hierarchy policy inheritance
- Custom roles (extensible to any GCP service)
- Conditional bindings (CEL expressions)
- Groups support (nested, 1 level)
- REST API gateway (HTTP/JSON)
- Enhanced trace mode (JSON output, duration metrics)
- Strict mode (unknown roles denied by default)
Limitations
- No organization/folder hierarchy (project is root)
- No service accounts or token minting
- No audit logging enforcement (auditConfigs accepted but not enforced)
- CEL expressions: basic subset only (startsWith, type equality, time comparisons)
Current scope: Core IAM policy operations for CI/CD testing with emulators
Project Status
Extracted as the strategic "keystone" auth layer to enable complete GCP emulator ecosystem testing.
Disclaimer
This project is not affiliated with, endorsed by, or sponsored by Google LLC or Google Cloud Platform. "Google Cloud", "IAM", and related trademarks are property of Google LLC. This is an independent open-source implementation for testing and development purposes.
Maintained By
Maintained by Dayna Blackwell — founder of Blackwell Systems, building reference infrastructure for cloud-native development.
Trademarks
Blackwell Systems™ and the Blackwell Systems logo are trademarks of Dayna Blackwell. You may use the name "Blackwell Systems" to refer to this project, but you may not use the name or logo in a way that suggests endorsement or official affiliation without prior written permission. See BRAND.md for usage guidelines.
Related Projects
- gcp-emulator - Unified single-process runtime (IAM + Secret Manager + KMS + Eventarc)
- GCP Secret Manager Emulator - IAM-enforced Secret Manager data plane
- GCP KMS Emulator - IAM-enforced KMS data plane
- GCP Eventarc Emulator - IAM-enforced Eventarc data plane
- gcp-emulator-auth - Enforcement proxy library (the guard)
Who's Using This?
If you're using this IAM emulator — in CI, locally, or in a test harness — I'd love to hear how you're using it.
- What authorization bugs did you catch? (missing bindings, wrong role definitions, conditional policy issues)
- How are you defining roles? (mostly built-in, mostly custom YAML, mix of both)
- What's your setup? (standalone policy engine, orchestrated with data plane emulators, custom integration)
- What's still friction? (policy.yaml complexity, trace mode integration, missing GCP role equivalents)
Open an issue, start a discussion, or reach out directly:
This helps shape the roadmap and ensures the project stays aligned with real-world needs.
License
Apache License 2.0 - See LICENSE for details.
Documentation
¶
Overview ¶
Package iam provides the composition entry point for the GCP IAM Emulator.
Register wires the IAM Policy gRPC service onto an existing grpc.Server, enabling use within the unified gcp-emulator or any custom composition layer. For standalone use, see cmd/server.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewGatewayHandler ¶ added in v0.10.0
NewGatewayHandler returns an http.Handler that serves the IAM REST API by proxying to the gRPC server at grpcAddr via grpc-gateway v2.
Types ¶
type Option ¶
type Option func(*options)
Option configures the IAM server at registration time.
func WithAllowUnknownRoles ¶
WithAllowUnknownRoles enables wildcard role matching (compatibility mode).
func WithPolicyFile ¶
WithPolicyFile loads IAM policies, groups, and custom roles from a YAML file.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
server
command
|
|
|
internal
|
|
|
gateway
Package gateway provides HTTP/REST gateway access to the gRPC IAM Policy service using grpc-gateway v2 to transcode HTTP/JSON ↔ gRPC.
|
Package gateway provides HTTP/REST gateway access to the gRPC IAM Policy service using grpc-gateway v2 to transcode HTTP/JSON ↔ gRPC. |
|
gen/google/iam/v1
Package iamv1 is a reverse proxy.
|
Package iamv1 is a reverse proxy. |