Learn 9router - Secrets & Integration Security
Episode 11 of 23

Learn 9router - Secrets & Integration Security

Securing AI gateway credentials: storing API keys, provider credentials, and service tokens centrally, secure integration with external toolchains, as well as rotation and least-privilege access strategies.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 10 you made routing changes safely rollbackable. But there's one class of secrets that must never enter version control at all: credentials. One leaked API key in a commit means the entire gateway can be abused — and the LLM bill flows to the attacker.

Episode 11 closes the foundational security side: secrets and integration security. We'll cover why provider credentials must not be placed raw in config, how to store API keys and service tokens centrally, referencing secrets from config without writing them, secure integration with external toolchains, and rotation and least-privilege access strategies.

Why Credentials Are More Than Just Env Vars

Many people stop at "store it in an environment variable". That's a good start, but not the end. Env vars hardcoded in a Dockerfile or compose file are still plaintext that can leak through images, logs, or container snapshots. Credentials deserve their own class of treatment: encrypted at rest, rotated regularly, and granted minimal access rights.

There are three kinds of secrets a gateway often holds: LLM provider API keys (OpenAI, Anthropic, Azure), service tokens for authenticating to external toolchains, and encryption keys for internal data. All three have different lifecycles and risks — treat each as an independent secret, not one secret block.

Warning

The first rule: secrets never enter the repo, the image, or the logs. If a single secret leaks, the entire chain of integrations using it is at risk — not just one provider.

Storing Secrets Centrally

9router doesn't store credentials in config files; it reads them from a secret manager. The simplest option to start is a cloud secret manager (AWS Secrets Manager, GCP Secret Manager, or HashiCorp Vault), then reference them by ID, not value. This separates "what the config is" from "what the secret is".

Mapping a secret manager to providers
secrets:
  backend: vault
  address: https://vault.internal:8200
  providers:
    openai: vault:kv/9router/openai#api_key
    anthropic: vault:kv/9router/anthropic#api_key
    azure: vault:kv/9router/azure#api_key
  service_tokens:
    slack: vault:kv/9router/tools/slack#token

The gateway loads secret values from Vault at startup and keeps them only in memory, never on disk or in config. Every access to a secret can be audited by the secret manager, so you know who pulled which key and when. Make sure the gateway's connection to Vault uses its own authentication that's stronger than a static token.

Referencing Secrets in Config

The config stays declarative and clean of secret values. The reference template looks like vault:path#field — you only mention the location, not the content. When deploying to many environments, just change the backend or path, without ever touching the secret values.

Verifying secret resolution
npx @9router/cli secrets check
Secret check results
{
  "providers": { "openai": "resolved", "anthropic": "resolved", "azure": "missing" },
  "service_tokens": { "slack": "resolved" },
  "recent_rotation": { "openai": "21 days ago" }
}

The npx @9router/cli secrets check command validates that all references can be resolved without ever printing the values. This closes the classic gap: a config that passes structural validation but fails at runtime because of a wrong secret path. Run this check together with validation in CI, as in episode 10.

Secure Integration with External Toolchains

The 9router gateway often calls external toolchains — databases, CRMs, message brokers — using service tokens. Secure integration means three things: tokens stored centrally, connections encrypted in transit, and token access rights scoped. For mTLS or key-based auth, store the key material in the secret manager too.

Toolchain integration with limited scope
integrations:
  - name: crm
    type: api
    url: https://crm.internal/api
    auth: token
    secret: vault:kv/9router/tools/crm#token
    tls:
      min_version: "1.2"
    allowed_scopes: [crm:read]

Notice allowed_scopes is only crm:read. This token can't write, delete, or access other resources — the damage possible if the token leaks is also limited. Always encrypt connections with TLS and make sure no service token slips through to an LLM provider as request context.

Info

The zero-trust principle also applies in reverse: don't give external toolchains access to your gateway just because the gateway calls them. Every integration uses its own identity that can be revoked.

Rotation Strategy and Least Privilege

Credentials must change periodically because time increases the chance of leakage. Good rotation is automatic and two-phase: the new key is used first before the old key is removed, so there's never a moment of service outage. 9router supports multiple credentials per provider for a smooth transition.

Multiple credentials for smooth rotation
providers:
  openai:
    credentials:
      - id: active
        secret: vault:kv/9router/openai#key_v2
      - id: previous
        secret: vault:kv/9router/openai#key_v1
        status: draining

When key_v1 enters the draining status, the gateway uses key_v2 for new requests and finishes old requests with key_v1 until it's empty, then key_v1 is deleted. This cycle can also be triggered from the CLI: 9router secrets rotate --provider openai swaps the active and previous statuses automatically, so the drain-and-delete flow runs without manual config edits.

Pair that with least privilege: each secret only has the scope its specific function needs — an analytics token can't write models, a staging key can't access prod. Schedule rotation as a recurring routine, say every 90 days, and tie it to the secret manager audit so no key idles without a reminder. Revoke secrets that are no longer used — old, unrotated, undeleted secrets are just waiting to leak.

Conclusion

Secrets and integration security ties together everything you've learned: credentials are pulled out of config and stored centrally, config only holds references, external toolchains are accessed with limited-scope tokens over encrypted connections, and two-phase rotation keeps the service alive while cleaning up old keys. Least privilege is the final filter — every secret may only do what it's actually for.

Key takeaways:

  • Credentials never enter the repo, image, config, or logs — store them in a secret manager.
  • Config only holds references like vault:path#field, never the secret values.
  • A CI secret-resolution check catches broken references before production.
  • External integrations use minimal-scope tokens and TLS connections.
  • Two-phase rotation with the draining status enables key changes without downtime.

Episode 12 opens Phase 4, the broader security: Secure Gateway & Access Control — authenticating incoming requests, authorizing route and tool invocation access, up to transport security and encrypted provider connections. See you there!

Learn 9router - Secrets & Integration Security | Learn 9router