OpenKeel: the sovereign French Cloud solution of the inherent group, with a European reach Discover inherent

Reverse-spec · Services

keystone — Summary

Reverse-specification of Keystone — branch stable/2026.2

Branch stable/2026.2 @ e6dc5ae079e6 (30.0.0-5-ge6dc5ae07) — repository https://opendev.org/openstack/keystone — analysed on 2026-10-28

  • Scope: all non-test code (351 files, about 67,000 lines): the Flask API and its middlewares, authentication and tokens, identity (SQL and LDAP), resource, assignment, catalog, credentials, trusts, federation, OAuth1/2, limits, revocation, notifications and cache, the keystone-manage CLI, and the branch history.
  • References are file:line relative to the repository root. [inferred] marks a statement that was not followed to the end in the code.

Files of this specification

FileContent
01-rest-api_stable-2026.2.mdconventions, functional description by area, the 259 operations extracted from the Flask application with handler and policy rule
02-errors_stable-2026.2.mdcentral translation, message masking, statuses and situations, catalogue of 109 exceptions
03-interactions_stable-2026.2.mdHTTP, token format (Fernet payloads, keys), 47 tables, cache and distributed invalidation, CADF notifications, LDAP, xmlsec1
04-scenarios_stable-2026.2.md5 scenarios: authentication and validation, user disabling, OIDC federation, application credential, key rotation
05-async-processing_stable-2026.2.mdno consumer or periodic task; in-process cascade callbacks; keystone-manage commands
06-change-history_stable-2026.2.mdthe 4 commits of the branch (1 security, 1 fix) and the carry-over plan
07-rewrite-pack_stable-2026.2.mdrewrite pack (OpenKeel): contracts in _rewrite/ (routes, OpenAPI, request and response schemas, migrated schema and its differences, policies, configuration), Fernet token format with 227 vectors, mapping engine with 705 cases, client expectations, strategies, conformance

Overview

Keystone is OpenStack's identity and authorisation service:

  • it authenticates users, services and federated identities;
  • it issues tokens that are not stored (Fernet), which the other services have validated by keystonemiddleware;
  • it holds the projects, domains, roles and assignments that the policies of every service use;
  • it publishes the service catalog.

It is a synchronous service:

  • no RPC, and no outbound REST call;
  • its effects outside its database are the CADF notifications it publishes, and the key files shared between nodes.
flowchart LR
  subgraph clients[Clients]
    U[Users / CLI / Horizon]
    S[OpenStack services<br/>keystonemiddleware]
  end
  subgraph ks[keystone-api WSGI — Flask]
    MW[middlewares<br/>CORS, size limit, request-id,<br/>URL normalisation, auth context]
    API[27 API modules<br/>keystone/api/*]
    MGR[managers + drivers<br/>identity, resource, assignment,<br/>catalog, token, revoke…]
  end
  U -->|HTTP /v3| MW --> API --> MGR
  S -->|GET /v3/auth/tokens| MW
  MGR -->|SQL| DB[(47 tables)]
  MGR -->|LDAP, read-only| LDAP[(directory)]
  MGR -->|memcache| C[(oslo.cache)]
  MGR -->|AMQP notify| MQ[(RabbitMQ)]
  MGR -->|reads| K[[fernet-keys / credential-keys]]
  CLI[keystone-manage] -->|db_sync, bootstrap, *_rotate, trust_flush| DB
  CLI --> K

Processes

ProcessEntry pointRole
keystone-apiWSGI keystone.wsgi.api:application (keystone/wsgi/api.py), built by initialize_application (keystone/server/flask/core.py:145-186)the whole REST API (port 5000 by convention [inferred])
keystone-managekeystone.cmd.manage:main (pyproject.toml)migrations, bootstrap, key rotation, purges, federation tools (keystone/cmd/cli.py)
keystone-statuskeystone.cmd.status:mainpre-upgrade checks

External dependencies

SystemProtocolConfigurationUsage
SQL databaseSQL (oslo.db)[database]/connectionall persistent state; tokens excepted
Key filesfile system[fernet_tokens], [credential], [fernet_receipts], [jwt_tokens]token and receipt encryption, credential encryption
Cachememcache, redis…[cache]validated tokens, effective roles, catalog…
RabbitMQAMQP (notifier)[oslo_messaging_notifications], [DEFAULT]/notification_formatCADF audit and resource events
LDAPLDAP v3[ldap], per-domain configurationread-only users and groups
xmlsec1process[saml]SAML assertion signing (Keystone as IdP)

Key figures

259 HTTP operations on 125 paths, 204 default policy rules, 109 exception classes and 689 raise sites, 47 tables, 11 Fernet payload versions, 7 cache regions plus 6 memoised groups, 0 periodic tasks, about 15 types of cascade callbacks.

Points of attention

  1. Token format = an inter-version and inter-node contract: Fernet keys shared by every node; the authentication methods encoded as **bits in the order of [auth]/methods** (changing that order breaks existing tokens); payloads versioned 0 to 10 (see 03 § 2).
  2. Revocation: every validation queries revocation_event unless cached. The table is only purged when a new revocation is written; there is no periodic task.
  3. Synchronous cascades: deleting a domain or a project, or disabling a user, does all its cleanup inside the request (05 § 1).
  4. Cache and invalidation: correct only with a shared cache (memcached); with a per-process cache, invalidations stay local.
  5. 401 vs 404: an invalid token being validated is a 404 TokenNotFound; auth messages are masked unless insecure_debug is set.
  6. Collection methods that answer 400 instead of 405 (DELETE /v3/policies…), because of the shared Flask resources.
  7. Security: the EC2/S3 fix on this branch (bug 2165281) must be carried over to any fork (06).

Blind spots / [inferred]

  • The behaviour of keystonemiddleware (caches, delay_auth_decision) is described from what Keystone expects of it, not read.
  • Federation: the mapping engine (keystone/federation/utils.py, about 1,100 lines) is described by its role, not rule by rule. SAML/ECP and Keystone-to-Keystone were not followed down to the XML.
  • LDAP: the attribute mappings and filters (keystone/identity/backends/ldap/common.py, about 2,000 lines) were not detailed.
  • JWS provider: described from its configuration, its claims not detailed.
  • Policies: the 204 rules are in the extraction (_rewrite/); their effective behaviour by persona (system reader, domain manager…) is not tabulated rule by rule.
  • The inventory found no RPC or periodic task, and reading the code confirms it.

Source: reverse-spec-keystone/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.