End-to-end scenarios — keystone — branch stable/2026.2
Branch
stable/2026.2@e6dc5ae079e6— repository https://opendev.org/openstack/keystone — analysed on 2026-10-28
Statuses refer to errors. The behaviour of keystonemiddleware, in the other services, is marked [inferred]: it lives outside this repository.
1. Authentication, then token validation by a service
sequenceDiagram
autonumber
participant U as Client (openstack CLI)
participant K as keystone-api
participant DB as SQL
participant C as memcached
participant N as nova-api + keystonemiddleware
U->>K: POST /v3/auth/tokens {password, scope project}
K->>DB: SELECT user/local_user/password (+ failure counter)
alt bad password
K->>DB: UPDATE local_user SET failed_auth_count+1
K-->>U: 401 "The request you have made requires authentication."
else account locked / disabled / password expired
K-->>U: 401 AccountLocked / UserDisabled / PasswordExpired
else
K->>DB: roles (effective assignments), catalog
K->>K: Fernet encrypt(msgpack payload v2) with the primary key
K-->>U: 201 X-Subject-Token + token body + catalog
end
U->>N: GET /servers X-Auth-Token
N->>K: GET /v3/auth/tokens X-Auth-Token=<service token> X-Subject-Token=<user token> [inferred: middleware]
K->>C: tokens region (cached validation?)
alt not cached
K->>K: decrypt with the active keys, expiry check
K->>DB: SELECT revocation_event … (check_token)
K->>DB: SELECT user (enabled?)
end
alt revoked / expired / unreadable key
K-->>N: 404 TokenNotFound
N-->>U: 401 [inferred]
else
K-->>N: 200 token (roles, project, catalog)
N->>N: middleware cache (token_cache_time) [inferred]
endDiagnostics:
- 401 for every user after a key rotation: the key repository is not synchronised between nodes. A token encrypted on node A with its new primary key cannot be decrypted on node B (
ValidationError "Could not recognize Fernet token", thenTokenNotFound). - 500 on every authentication:
KeysNotFound, an empty key repository or wrong permissions. - "Authorization failed … from <ip>" in the logs: the
WARNINGemitted by the 401 handler (keystone/server/flask/application.py:137-141).
2. Disabling a user: instant revocation
sequenceDiagram
autonumber
participant A as Administrator
participant K as keystone-api
participant DB as SQL
participant C as memcached
participant MQ as RabbitMQ
participant N as other services
A->>K: PATCH /v3/users/{id} {"enabled": false}
K->>DB: UPDATE user SET enabled=false
K->>K: callbacks "disabled user" (same request)
K->>DB: INSERT revocation_event(user_id, issued_before=now) + purge of expired events
K->>DB: DELETE application_credential … WHERE user_id
K->>C: invalidate tokens and receipts regions (new region identifier)
K->>MQ: identity.user.updated (CADF)
K-->>A: 200
N->>K: validation of an old token of the user [inferred]
K-->>N: 404 TokenNotFound (revocation event matched)Diagnostics: tokens still accepted after disabling the user. There are two possible causes:
- the services' middleware cache (
token_cache_time, 300 s by default on the keystonemiddleware side [inferred]); - a non-shared Keystone cache (
dogpile.cache.memory), where the invalidation stays in the one worker that handled it.
3. Federated login (OIDC through mod_auth_openidc, WebSSO)
sequenceDiagram
autonumber
participant B as Browser (Horizon)
participant H as Apache + mod_auth_openidc
participant K as keystone-api
participant I as External IdP (OIDC)
participant DB as SQL
B->>H: GET /v3/auth/OS-FEDERATION/websso/openid?origin=https://horizon/…
H->>I: OIDC redirect, authentication
I-->>H: code → id_token (validated by the module)
H->>K: same request + OIDC-* attributes in the WSGI environment
K->>DB: identity_provider (by remote_id), federation_protocol, mapping
K->>K: RuleProcessor.process(assertion) → user, groups, projects
alt no rule matches / IdP disabled
K-->>B: 401 / 403
else
K->>DB: shadow user (federated_user, nonlocal_user), expiring_user_group_membership (TTL authorization_ttl)
K->>K: federated unscoped token (payload v4)
K-->>B: 200 HTML page that POSTs the token to "origin" (trusted_dashboard)
end
B->>K: POST /v3/auth/tokens {token, scope project}
K-->>B: 201 federated project-scoped token (v5)Sources: keystone/api/auth.py:360-470, keystone/auth/plugins/mapped.py:41-500, keystone/federation/utils.py:469-1130. The origin must be in [federation]/trusted_dashboard, or the request is refused.
4. Application credential: create, then use
sequenceDiagram
autonumber
participant U as User
participant K as keystone-api
participant DB as SQL
U->>K: POST /v3/users/{me}/application_credentials {name, roles?, expires_at?, access_rules?}
K->>DB: effective roles of the user on the token's project
alt requested role not held
K-->>U: 404 RoleAssignmentNotFound
else quota reached
K-->>U: 403 ApplicationCredentialLimitExceeded
else
K->>DB: INSERT application_credential (secret_hash), application_credential_role, access_rule
K-->>U: 201 {id, secret (shown once only), …}
end
Note over U: later, from a script or a service
U->>K: POST /v3/auth/tokens {methods:[application_credential], id, secret}
K->>DB: application_credential + hash check + expiry + user enabled
K-->>U: 201 token v9 (credential's roles only, expiry ≤ the credential's)5. Rotating the Fernet keys (operation)
sequenceDiagram autonumber participant O as Operator / cron participant M as keystone-manage (node 1) participant FS1 as fernet-keys node 1 participant FS2 as fernet-keys nodes 2..n O->>M: fernet_rotate --keystone-user keystone --keystone-group keystone M->>FS1: create a new staged key 0; rename the old 0 to N+1 (primary) M->>FS1: delete the oldest keys beyond max_active_keys O->>FS2: rsync of the repository (must be fast) Note over FS1,FS2: between rotation and sync, node 1 encrypts with key N+1, which nodes 2..n already know as key 0 (staged): validation keeps working
If the sync comes after a second rotation, the nodes no longer share their keys and validations fail (see scenario 1). The key lifetime should be at least expiration + allow_expired_window × the number of keys [inferred: Keystone documentation].
Source: reverse-spec-keystone/04-scenarios_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.