feat: add single-tenant API key authentication - #123
Conversation
|
Adding a production deployment data point, since this is a design-review vehicle and it may be useful to know how the current "no auth" state actually gets handled in the field. We run AgentENV as the isolation layer under a multi-user internal agent platform — each end user gets one persistent sandbox, and an application-side shim maps users to sandbox IDs. Because there is no authentication today, we follow the README's guidance literally: the API is bound to Three observations that bear on the design: 1. Loopback-only is a real deployment posture, not just a stopgap — please keep it viable. For us the shared key would be defence in depth behind the loopback bind, not the primary boundary. If the implementation ends up requiring a key even for a loopback-only single-node install, that is a small friction on a config that is already safe; an "auth required unless bound to loopback" default, or simply generating the key automatically as you describe, avoids making people opt out of security to keep a working setup. The automatic generation in your Scope section reads like it already handles this well. 2. The derived sandbox-scoped token is the part we would use most. Our shim already knows which user owns which sandbox; AgentENV does not, and deliberately so. A token scoped to a sandbox ID means a compromised component can only reach the sandbox it was issued for, rather than the whole node. That is a meaningful reduction in blast radius for anyone running this multi-tenant on top, and it is the piece a shared key alone does not give you. 3. Key rotation is the operational question we would ask first. With a single shared key persisted at setup time, what does rotation look like for a running node with live sandboxes — is the expectation a restart, or can the key be re-read? If derived sandbox tokens are a function of the shared key, does rotating it invalidate every in-flight sandbox token? For long-lived sandboxes (ours persist across a working session and pause/resume rather than being recreated per command) that distinction matters quite a bit. Worth documenting whichever way it lands. One smaller note: if the key ends up in a config file written by the setup paths, it would be helpful for the docs to state the expected file mode and owner explicitly. It is the kind of thing that is obvious to whoever writes it and non-obvious to whoever inherits the box. Happy to test a branch against a real multi-user deployment if that is useful — we have a node running this pattern daily and can report back on anything that breaks under pause/resume or long-lived sandboxes. |
What
AENV_API_KEYon the AgentENV server and gateway.X-API-Keymatch and sandbox data-plane requests with either that key or an automatically derived, sandbox-scoped access token.Why
AgentENV previously accepted any non-empty supported credential, so an exposed server did not provide a meaningful authentication boundary. Single-tenant deployments need a secure default without adding accounts, a database, or a second user-managed token, and without changing the existing
aenv author E2B SDK workflows.Related issue
N/A. This draft PR is the design and implementation review vehicle.
Scope and non-goals
Included:
Not included:
Design and behavior changes
The server and gateway fail fast when
AENV_API_KEYis missing or empty. All non-health API requests require exactly one matchingX-API-Key; missing, incorrect, duplicate, bearer, admin-token, and team-ID credentials are rejected. Comparisons use constant-time primitives.GET /healthremains public for load balancers and container health checks. A sandbox response carries an HMAC-SHA256 token derived from the shared key and sandbox ID, allowing current E2B SDKs to access that sandbox without a user-providedE2B_ACCESS_TOKEN. The same derivation is implemented by the Rust node and Go gateway.The proxy removes
X-API-Keybefore forwarding traffic into a sandbox and preserves applicationAuthorizationheaders. Rotating the shared key invalidates previously derived sandbox tokens.Installers generate a 256-bit
e2b_-prefixed key once and preserve it across upgrades. Native installs store it in/etc/default/aenv, Docker setup stores it in/etc/aenv/auth.env, and Kubernetes stores it inSecret/agentenv-auth. The gateway and all runtime nodes in a multi-node deployment must use the same value.Compatibility and operations
X-API-Keyauthentication with/healthexplicitly anonymous. Existing routes and request shapes are unchanged; sandbox responses populate existing access-token fields.AENV_API_KEYis required at server and gateway startup. Installation helpers generate it automatically; manual and multi-node deployments must provide the shared value.AENV_API_KEYbefore upgrading. Rollback can leave the unused environment variable or secret in place.The end-user flow remains one key:
aenv authstill stores the server URL and API key, and E2B SDK users set the same value asE2B_API_KEY. Users do not create or copy a separate sandbox token.Validation
make fmtmake clippymake test-unitmake -C services test(required whenservices/changes)maketargetCommands and results:
Skipped checks and reasons:
Risks and reviewer notes
mainand should be rebased before the PR is marked ready.src/api/impls/auth.rs,src/api/proxy.rs, andservices/gateway/internal/server.go.Checklist