Secrets management
Security
Sensitive app configuration, integration credentials, signing keys, and app environment variable values sit in the customer’s Key Vault. The Greenlight control plane stores references and metadata needed to bind them to apps, but never the values themselves.
What’s on disk on the control plane, in a database backup, in an exfiltrated control-plane dump? A reference, not a secret.
Where things live
Section titled “Where things live”| Material | Where it lives | What the control plane knows |
|---|---|---|
| Integration credentials | Key Vault | Reference + which apps are granted |
| App env vars, plain and sensitive | Key Vault, injected into app pods through the app’s Kubernetes Secret | Reference + variable name + sensitivity flag |
| Workload identity | Cluster identity service, never persisted | The mapping from workload to app |
| End-user passwords | Customer’s IdP | Nothing |
| Upstream user tokens | In-memory at the broker during a request | Nothing after the request completes |
| Audit log records | Control plane database | The structured event (not request bodies) |
Plain env vars can be revealed through the dashboard or MCP when the caller is authorized, but the value still comes from Key Vault. Sensitive env vars are write-only after creation: admins can see the name and metadata, not the value.
How a credential reaches an app
Section titled “How a credential reaches an app”Every integration credential is registered by IT and stored in Key Vault. How it reaches a granted app is a deliberate choice IT makes when registering the integration, and it changes the exposure profile:
- Proxied — the app holds only a short-lived workload key and calls
GREENLIGHT_PROXY_URL. The broker resolves the grant, swaps in the real credential server-side, and forwards the request. The upstream secret never reaches the app. Every call is audited and rotation takes effect on the very next request. - Injected — at deploy time Greenlight injects the bound credential into the app’s Kubernetes Secret under an environment variable name IT chose, and the app calls the upstream directly. This is the only option for wire-protocol sources a proxy can’t carry, such as a database connection string. Here the raw upstream credential does live in the app’s environment — the deliberate tradeoff for sources the broker can’t front. There’s no per-call broker audit, and rotation takes effect only at the app’s next deploy.
Both modes keep the credential out of the control-plane database and out of git. The difference is whether the secret reaches the running app process: proxied keeps it server-side; injected places it in the pod’s environment, the same mechanism that delivers a managed DATABASE_URL.
What admins can see
Section titled “What admins can see”Greenlight admins can see that a secret exists. They can see which app it is bound to, which integration uses it, when it was last rotated. They cannot see the value through the dashboard, the API, or any MCP tool.
The only path to a secret value is to read it through the Key Vault directly using the cloud provider’s own access controls. An audit event is written for every Greenlight-mediated secret reference change; reads of the Key Vault are audited by the cloud provider’s native logging.
Secrets and local development
Section titled “Secrets and local development”When a developer’s coding agent works on an app locally, no secret value ever passes through the agent or its MCP session — that would put credentials in agent transcripts and inference logs. Local development is built so that nothing on the laptop is a long-lived, replayable secret:
- The agent pairs a bundled
greenlightCLI once over its session. To run the app,greenlight run --app <id> -- <command>resolves the app’s configuration server-side and injects values straight into the running process — there is no.env.localfile and nothing written to disk. (A personal, no-app run —greenlight runwithout--app, against the developer’s own granted integrations — uses the same handling: a short-lived, user-scoped token, nothing on disk.) - For proxied integrations the laptop never holds the upstream secret. The CLI mints a short-lived, principal-scoped token and the process calls the same broker URL the deployed app uses; the broker swaps in the credential exactly as it does in production.
- For injected credentials, a granted developer’s process receives the raw value — granting an injected credential is disclosing it. Because a value handed to a developer’s machine can’t be time-bounded or remotely revoked, the dashboard says so at the two moments that decide it — choosing injected delivery at registration, and approving a grant — and recommends a dedicated least-privilege upstream account. Every raw delivery is audited under the developer’s name.
- To investigate real data without delivering a credential, the agent uses data-inspection tools that run inside the control plane and return only results — never the credential. They cover the app’s own database, its blob storage, and a single request through a granted proxied integration. Blob access uses a short-lived signed URL.
Sensitive env-var values are excluded from local delivery entirely. The CLI’s own credential rotates and is revocable — deactivating the developer immediately kills it and any token minted from it. A lost laptop costs at most one revocable session, never an upstream secret.
Rotation
Section titled “Rotation”Integration credentials are rotated through the dashboard: paste the new value, click rotate, and it lands in Key Vault under a new version.
How fast running apps see the new value depends on how the credential reaches them:
- Proxied — the broker pulls whichever version is current on the very next call. There’s no overlap window where both are valid, and no app restart.
- Injected — the value is baked into each app’s environment at deploy time, so apps already running keep the old value until their next deploy. The replace-secret dialog warns IT and lists the affected apps.
Either way there is no app-side change required during rotation. Every rotation writes an audit event recording the integration, credential slug, and delivery mode — never the secret value.
Workload identity rotates automatically on a cadence the cluster controls. App pods see this as transparent; they reauthenticate to the broker on each call.
When IT deletes a credential or a whole integration, the underlying Key Vault secret is destroyed and the credential is excluded from every path that could resolve it. Apps still holding a grant against it stop being served rather than reaching a stale value.
No plaintext at rest, no exceptions
Section titled “No plaintext at rest, no exceptions”The platform does not have a “but for this one integration we needed plaintext on disk” exception. Every secret routes through Key Vault. If a future provider integration can’t be done that way, it doesn’t ship until it can.