-
Notifications
You must be signed in to change notification settings - Fork 0
Security and Safety
For a high-level overview of what's safe by default with no configuration, see Safety & Cost Safeguards. This page covers technical implementation details: HITL flow, PII scrubbing, rate limits, and IAM roles.
Aura Tracker GCP is designed on the principle that the LLM proposes, you approve. No mutation reaches GCP without an explicit human confirmation step.
Two tools can change GCP state:
| Tool | What it changes |
|---|---|
gcp_gke_scale_deployment |
GKE node pool size |
gcp_cloudrun_update_traffic |
Cloud Run traffic split percentages |
Both are protected by a two-step confirmation flow enforced at the server level — the LLM cannot bypass it.
Step 1 — Preview
─────────────────────────────────────────────────
LLM calls tool with dry_run=true
↓
Server previews the change (no GCP API call made)
Returns: plan_id, human-readable description, expires_in=10min
↓
LLM presents the preview to YOU
↓
★ YOU decide: approve or reject ★
Step 2 — Execute (only after your explicit approval)
─────────────────────────────────────────────────
LLM calls tool with confirm_plan_id=<plan_id>
↓
Server validates the plan (not expired, not already used)
Atomically consumes the plan (single-use)
Executes the mutation against GCP
Logs confirmation at WARN level with full audit context
Diagram suggestion: A UML sequence diagram with four actors: User, LLM, Aura Tracker GCP Server, GCP APIs. Show Step 1 ending at the User with a decision diamond, and Step 2 only proceeding if the user says "yes". Highlight the 10-minute TTL expiry window.
Key safety properties:
- Plans expire after 10 minutes. A stale
plan_idis rejected with an actionable error message. - Each
plan_idis single-use — atomically consumed on confirmation, preventing replay attacks. - Both dry-run and confirmation are logged. Log entries include project, resource, previous state, and requested change.
-
SAFETY_ENABLED=falsedisables the confirmation gate. Use only in development environments — the server logs a WARNING on startup when this flag is set.
The anonymization engine runs as middleware on every tool result, applied before the LLM sees the output. It is off by default.
ANONYMIZE_ENABLED=true GCP_PROJECT_ID=my-project ./aura-tracker-gcpANONYMIZE_ENABLED=true \
ANONYMIZE_CONFIG_PATH=/path/to/anonymize.yaml \
GCP_PROJECT_ID=my-project ./aura-tracker-gcp| Pattern name | What it matches |
|---|---|
internal_ip |
Private IPv4 ranges: 10.x, 172.16-31.x, 192.168.x
|
public_ip |
Any valid IPv4 address |
email |
Standard email format |
service_account |
GCP service accounts (*@*.iam.gserviceaccount.com) |
gcp_api_key |
GCP API keys (39-char AIza… prefix) |
Custom patterns can be appended via the patterns: list in your YAML config.
The same raw value always maps to the same token within a single tool call (e.g., the first matching email becomes [EMAIL_1], the second [EMAIL_2]). This lets the LLM reason about correlations (same service account appears in two places) without ever seeing the actual value.
Set audit_only: true in the YAML config to see exactly which patterns would fire and on which JSON paths — without masking anything. Use this to tune your patterns safely before enabling real scrubbing.
# anonymize.yaml
audit_only: true
patterns:
- name: internal_project_id
regex: "proj-[a-z0-9]{8}"Every GCP API call is throttled at the server boundary, not the tool level. The LLM cannot generate more API traffic than these limits allow.
| Limit | Value |
|---|---|
| Rate limit | 10 requests/second |
| Burst capacity | 20 requests |
| Per-call timeout | 30 seconds |
| Fan-out budget | 30 seconds shared across parallel goroutines (e.g., gcp_gke_get_cluster_bottlenecks) |
These protect your GCP quota and prevent runaway costs from a looping agent.
Aura Tracker GCP needs read permissions for almost all tools. Only the two mutation tools need write access.
roles/container.viewer # GKE clusters, node pools
roles/run.viewer # Cloud Run services, jobs
roles/pubsub.viewer # Pub/Sub topics, subscriptions
roles/logging.viewer # Cloud Logging
roles/monitoring.viewer # Cloud Monitoring, Cloud Trace
roles/iam.securityReviewer # IAM bindings, policy reads
roles/storage.objectViewer # Cloud Storage buckets and objects
roles/cloudsql.viewer # Cloud SQL instances
roles/secretmanager.viewer # Secret Manager metadata only
roles/cloudtasks.viewer # Cloud Tasks queues
roles/cloudscheduler.viewer # Cloud Scheduler jobs
roles/workflows.viewer # Cloud Workflows
roles/eventarc.viewer # Eventarc triggers
roles/vpcaccess.viewer # Serverless VPC Access connectors
roles/compute.networkViewer # VPCs, subnets, load balancers
roles/artifactregistry.reader # Artifact Registry repos and images
roles/cloudbuild.builds.viewer # Cloud Build triggers
roles/container.nodePoolAdmin # gcp_gke_scale_deployment
roles/run.admin # gcp_cloudrun_update_traffic
Before relying on the server, run:
"Test my IAM permissions for project my-project"
This calls gcp_iam_test_permissions, which returns a per-permission allowed: true/false result for every relevant GCP API the server needs.
Best practice: Create a dedicated service account with only the roles listed above. Never run this server with roles/owner or roles/editor.
| Never | Why |
|---|---|
| Reads Secret Manager values | Only secret metadata (name, labels, create time) is fetched |
| Stores data externally | Results flow directly from GCP to your LLM; nothing is persisted outside your environment |
Executes mutations without a confirmed plan_id
|
The SafetyDecorator in internal/safety/decorator.go enforces this at the port boundary |
| Initializes unused GCP clients | Only clients needed for your enabled --modules set are instantiated, minimizing the OAuth token scope |
| Contacts any endpoint outside GCP APIs | The server makes no outbound calls except to GCP service endpoints |