Sovereign by Architecture: Building AI Infrastructure for the EU AI Act
The EU AI Act takes effect August 2026. Compliance starts at the infrastructure layer. Learn why sovereign AI needs OpenStack, Kubernetes, and Atmosphere.
Insights, updates, and stories from our team
The EU AI Act takes effect August 2026. Compliance starts at the infrastructure layer. Learn why sovereign AI needs OpenStack, Kubernetes, and Atmosphere.
Learn how a lightweight keystoneauth1 plugin brings your existing browser-based MFA and SSO to the OpenStack CLI, with no changes to any client tools.
Hyperscaler AI looks fast but hides long-term lock-in and rising costs. See how OpenStack and Kubernetes deliver GPU infrastructure you actually control.
Learn how a lightweight keystoneauth1 plugin brings your existing browser-based MFA and SSO to the OpenStack CLI, with no changes to any client tools.
You run an OpenStack cloud with federated identity. Your users sign in through Horizon with OpenID Connect or SAML, complete their MFA challenge in the browser, and land on a dashboard. The web experience works well.
The command line does not. Keystone's standard auth plugins expect a username and password passed directly. This breaks the moment your identity provider requires a browser redirect or a second-factor prompt. The common workaround is application-specific passwords: static credentials created outside the identity provider's normal auth flow. They bypass MFA entirely. They rarely get rotated. They create the exact kind of long-lived secret federated identity was meant to eliminate.
We built keystoneauth-websso to solve this. The plugin lets any OpenStack CLI tool use the same browser-based WebSSO flow Horizon uses, directly from your terminal.
Keystone's WebSSO flow was built for Horizon. Here is what happens:
mod_auth_openidc.mod_auth_openidc establishes a session.Every step assumes a browser. The identity provider redirect, the MFA challenge, the cookie-based session, the auto-submitted form. None of this maps to a curl-style request/response exchange. A CLI tool driving this flow with raw HTTP calls would need a full browser engine, or at least a JavaScript runtime to render the identity provider's login page. This approach is not practical.
localhost callback serverOur approach is minimal. Instead of replicating a browser, we use the actual browser. The plugin opens your default browser to start the WebSSO flow and spins up a short-lived HTTP server on localhost to receive the token when the flow completes.
The full sequence:
openstack server list, with auth_type set to v3websso.?origin=http://localhost:9990/auth/websso/ as a query parameter. This tells Keystone where to POST the token after authentication succeeds.localhost:9990. This server uses Python's built-in http.server module. No external dependencies. No framework. A 60-second socket timeout prevents the server from hanging if you abandon the flow.webbrowser module.mod_auth_openidc hands control back to Keystone. Keystone renders the callback template containing a form with the unscoped token. Because the origin points to localhost:9990, the form auto-submits to the plugin's waiting HTTP server.token field, stores the value, sends back a minimal HTML page telling you to close the tab, and shuts down.GET /v3/auth/tokens call, then proceeds with the command you originally ran.From your perspective: the terminal pauses, a browser tab opens, you authenticate, the tab says "close this window," and the terminal prints the result.
This works without changes to python-openstackclient or any other OpenStack client. The keystoneauth1 library has a plugin loading system built on stevedore and setuptools entry points. The plugin registers itself under the keystoneauth1.plugin entry point group as v3websso. When you set auth_type: v3websso in your clouds.yaml or pass --os-auth-type v3websso on the command line, keystoneauth1 discovers and loads the plugin automatically. No client-side patches. No vendor forks. No monkey-patching.
The plugin subclasses keystoneauth1's FederationBaseAuth, which handles project/domain scoping, token rescoping, and session management. The plugin only needs to implement one method: get_unscoped_auth_ref. This method contains the browser-and-localhost-server flow described above. Catalog lookups, endpoint discovery, and service clients all work unchanged downstream.
Opening a browser tab every time you run openstack server list would be painful. The plugin caches tokens locally to avoid this.
After a successful authentication, the plugin writes the unscoped token and its metadata to a JSON file in your platform's user cache directory (resolved via platformdirs). The filename is derived from the auth_url and identity_provider, preventing collisions between different clouds or identity providers.
Before starting the browser flow, the plugin checks for a cached token and validates the expiration timestamp. If a valid cached token exists, the plugin uses the token directly and the browser never opens. The cache file is written with 0600 permissions so other users on the system cannot read the token.
The browser flow happens once per token lifetime, typically a few hours depending on your Keystone configuration. Subsequent CLI calls are instant.
The callback server only binds to localhost. No network exposure. The server accepts one request and shuts down immediately.
The socket has a 60-second timeout. If no callback arrives, the server closes and the plugin raises an error instead of blocking your terminal.
The cache file is created with mode 0600, readable only by the owning user. The cache directory follows platform conventions (~/.cache on Linux, ~/Library/Caches on macOS) via platformdirs.
The plugin never sees or stores your identity provider password. Authentication happens entirely in the browser, in the identity provider's domain. The only artifact the plugin captures is the Keystone token, the same token Horizon would receive.
If you have invested in federated identity, this plugin removes the last gap in your SSO story. Your users do not need application passwords. They do not need MFA exceptions for CLI workflows. They authenticate the same way whether they use Horizon or the terminal. The same access policies, session controls, and audit logs apply.
The implementation is roughly 300 lines of Python with two runtime dependencies beyond keystoneauth1: multipart for parsing the POST body, and platformdirs for resolving cache paths. You need one Keystone config change: add http://localhost:9990/auth/websso/ to the trusted_dashboard list in keystone.conf. No changes to any CLI client.
The project is open source under the Apache 2.0 license at github.com/vexxhost/keystoneauth-websso.
Choose from Atmosphere Cloud, Hosted, or On-Premise.
Simplify your cloud operations with our intuitive dashboard.
Run it yourself, tap our expert support, or opt for full remote operations.
Leverage Terraform, Ansible or APIs directly powered by OpenStack & Kubernetes