Securing the admin API
The admin API is the EdgeControl gRPC control surface for the proxy (admin.grpc_listen). Anything that touches policy, transformation rules, routing, or producers goes through it. This guide covers locking it down with TLS, username/password login, API keys, JWT bearer auth, and mTLS, plus the v1 default-action semantics you should understand before deploying.
Threat model
The admin API can:
- Mutate any policy rule, rate-limit rule, transformation rule, or routing rule.
- Drain or restore producers.
- Change the log level (including
trace, which leaks request bodies).
An attacker with admin API access can bypass every gate the proxy enforces. Treat the admin port the same way you'd treat a root shell on the host.
Defaults to understand
default_action: deny
The v1 default for admin.default_action is deny (fail-closed). This value seeds the policy store that gates proxied SBI traffic, so a fresh install with no policy rules denies every request on the SBI listener. Flip to allow only when you understand the implications — typically a lab or bring-up environment. The live value is mutable without a restart:
Admin listener is off until you set grpc_listen
admin.grpc_listen has no implicit default — empty leaves the admin surface down. The shipped examples set 127.0.0.1:9091 so a loopback install matches the d3x-edgectl -addr default (the SBI listener is separate, on :8090). To expose the admin port off-host, change the listen address and turn on TLS + auth at the same time. examples/edge-full.yaml uses 127.0.0.1:8091 — pass -addr 127.0.0.1:8091 if you follow that file.
allow_insecure
The admin listener requires TLS by default. Setting admin.allow_insecure: true opts into cleartext gRPC — fine for local development on loopback, but exposes bearer tokens and API keys on the wire over any shared network. Production should configure admin.tls and remove this flag.
examples/edge-minimal.yaml and examples/edge-full.yaml set
allow_insecure: true so the shipped example config runs out of the box. Flip it and configure
admin.tls before deploying anywhere outside loopback.allow_anonymous
The proxy refuses to start unless admin.auth is populated or admin.allow_anonymous: true is set. This catches the misconfiguration where someone forgets to configure auth on a publicly-exposed admin port. examples/edge-minimal.yaml satisfies the gate by populating admin.auth.users (see username/password login below); examples/edge-full.yaml ships no credentials and sets allow_anonymous: true so it runs out of the box — turn that off and populate admin.auth for any real deployment.
Username/password login
The default mechanism the shipped configs use: an operator roster under admin.auth.users, each entry pairing a username, a bcrypt password_hash, and an RBAC role (admin, operator, or viewer). The EdgeControl Login RPC exchanges those credentials for a short-lived HMAC JWT. d3x-edgectl has no login subcommand — pass the token with -token, or prefer an API key for the CLI.
The shipped examples/edge-minimal.yaml uses admin / admin. Replace the hash before deploying. Login issues an HMAC JWT signed with jwt_secret carrying the role claim, which EdgeControl then validates on each authenticated RPC.
users list disables the Login RPC; the API-key and bearer-token
paths are unaffected. Issuing login tokens requires admin.auth.jwt_secret to
be set. When login_token_ttl is unset, the TTL is 1 hour.API keys
The simplest gate for d3x-edgectl: a static API key, sent as gRPC metadata (-key / D3X_EDGE_ADMIN_KEY). It always maps to the admin role.
Use the _file: variant in production so the key doesn't appear in your config repo. Set strong random keys (32+ bytes), rotate periodically, and gate file access on a small operator group.
d3x-edgectl picks the key up from the D3X_EDGE_ADMIN_KEY environment variable or the -key flag.
JWT bearer auth
For environments where the admin client is itself authenticated (CI, SSO, an operator portal), accept JWT bearer tokens minted by your issuer. The proxy validates either against an HMAC secret or an asymmetric public key.
The proxy enforces the signature and expiry, then reads the role claim (admin, operator, or viewer) and rejects any unknown role. Map your SSO identities to that claim in the issuer that mints these tokens.
TLS on the admin listener
Configure server-side TLS:
The proxy serves the EdgeControl gRPC API over TLS. ca_file is required only when require_client_cert: true.
mTLS
For the strongest gate, require client certificates. Combined with TLS, mTLS makes the admin listener reachable only from clients that hold a cert signed by your CA.
Pair mTLS with one of the auth modes above so the listener both verifies the client's certificate and resolves an RBAC role for each request.
Pre-prod checklist
admin.default_actionisdenyunless you've consciously chosen otherwise.admin.allow_insecureisfalse.admin.allow_anonymousisfalse.- One of
admin.auth.users,admin.auth.api_key_file, oradmin.auth.jwt_*is configured. - The dev
admin/adminpassword hash has been replaced. admin.tlsis configured.- Admin listen address is reachable only by operators — firewall, ACLs, or service-mesh policy.
Where to go next
- Policy engine — what
default_actiongates. - Admin API overview — address, auth, and how mutations hot-reload.
- Setting up observability — shipping decision logs and metrics to your pipeline.