Scenarios — skyline-apiserver — branch stable/2026.2
Branch
stable/2026.2@4af72bfd4577— repository https://opendev.org/openstack/skyline-apiserver — analysed on 2026-10-28
The diagrams follow the recorded order of calls (_rewrite/outbound-calls_stable-2026.2.md). "KS" is the identity endpoint of the catalog; version-discovery GET /v3 calls are omitted unless they matter.
1. Password login
The user types a name and password in the console. Skyline authenticates them, picks a landing project, builds the profile and sets the session cookies. The console then stores the returned Keystone token and loads the profile and the policies (skyline-console:src/stores/root.js:122).
sequenceDiagram
autonumber
actor U as Browser (skyline-console)
participant N as nginx
participant A as skyline-apiserver
participant KS as Keystone
participant NE as Neutron
U->>N: POST /api/openstack/skyline/api/v1/login {username, password, domain?}
N->>A: POST /api/v1/login
A->>KS: POST /v3/auth/tokens (password, unscoped)
alt wrong credentials / expired password
KS-->>A: 401
A-->>U: 401 {"detail": "<Keystone message>"}
else TOTP rule
KS-->>A: 401 + Openstack-Auth-Receipt
A-->>U: 401 {"detail": {"totp_required": true, "receipt": …}}
end
KS-->>A: 201 X-Subject-Token: unscoped
A->>KS: GET /v3/auth/projects (unscoped)
A->>KS: GET /v3/auth/tokens + GET /v3/users/{id} (system session)
Note over A: landing project = default_project_id if enabled, else first project
A->>KS: POST /v3/auth/tokens (token → project)
A->>KS: GET /v3/auth/tokens (validate, system session)
A->>KS: POST /v3/auth/tokens (user session, region list)
A->>NE: GET /v2.0/extensions (system session)
A->>KS: GET /v3/users/{id}/projects, GET /v3/users/{id} (system session)
A-->>U: 200 Profile {keystone_token, endpoints, projects…} + Set-Cookie session, time_expired
U->>N: GET …/profile and GET …/policies (cookie + X-Auth-Token)Diagnostics: a 401 with a connection error text means Keystone (or the system account) is the problem, not the user; Endpoint not found means the region has no identity **or no network** endpoint for interface_type (Neutron is called for every profile, skyline_apiserver/client/openstack/system.py:78; the token was already issued); You are not authorized for any projects or domains. means no role on an enabled project. Run with debug: true to see each outbound request in the log.
2. Login with TOTP
sequenceDiagram
autonumber
actor U as Browser
participant A as skyline-apiserver
participant KS as Keystone
U->>A: POST /api/v1/login {username, password}
A->>KS: POST /v3/auth/tokens (password)
KS-->>A: 401 receipt + required_auth_methods [["password","totp"]]
A-->>U: 401 {"detail": {"totp_required": true, "receipt": R}}
U->>A: POST /api/v1/login/totp {username, passcode, receipt: R}
A->>KS: POST /v3/auth/tokens (totp) + header Openstack-Auth-Receipt: R
alt wrong passcode
KS-->>A: 401
A-->>U: 401 {"detail": "invalid_totp"}
else receipt expired
KS-->>A: 401 receipt expired
A-->>U: 401 {"detail": "receipt_expired"}
end
KS-->>A: 201 unscoped token
Note over A: then steps 4–11 of scenario 1
A-->>U: 200 Profile + cookiesDiagnostics: the console restarts at the password step on receipt_expired (skyline-console:src/pages/auth/containers/Login/index.jsx:347). The warning log lines have unsubstituted %s placeholders: use the request time to correlate.
3. Any authenticated call (middleware)
sequenceDiagram
autonumber
actor U as Browser
participant A as skyline-apiserver middleware
participant DB as Skyline DB
participant KS as Keystone
participant H as Endpoint handler
U->>A: GET /api/v1/… (Cookie session=JWT or X-Auth-Token)
alt neither credential
A-->>U: 401 {"message": "Unauthorized: Token not found"}
end
A->>DB: DELETE FROM revoked_token WHERE expire < now-1
opt cookie path
A->>A: decode JWT (HS256, secret_key)
A->>DB: SELECT count(*) FROM revoked_token WHERE uuid = :uuid
alt revoked
A-->>U: 401 {"message": "Unauthorized: Token revoked"}
end
end
A->>KS: GET /v3/auth/tokens (X-Subject-Token = user token, system session)
alt token invalid / Keystone down / DB error
A-->>U: 401 {"message": "Unauthorized: …"}
end
A->>H: request.state.profile
H-->>A: response
opt less than access_token_renew left
A->>A: Set-Cookie session (new exp), time_expired
end
A-->>U: responseDiagnostics: a burst of 401 on every user at once points to Keystone, the system account (password changed, account disabled) or the database, not to the users. The middleware does not log these 401s.
4. Server list for an administrator (all projects)
sequenceDiagram
autonumber
actor U as Browser (admin)
participant A as skyline-apiserver
participant KS as Keystone
participant NO as Nova
participant GL as Glance
participant CI as Cinder
U->>A: GET /api/v1/extension/servers?all_projects=true&project_name=demo
Note over A: middleware (scenario 3); role check admin or reader, else 403
A->>KS: POST /v3/auth/tokens (user session re-scope)
A->>KS: GET /v3/projects?name=demo (system session)
A->>NO: GET /servers/detail?all_tenants=True&project_id=… (user, 2.79)
alt Nova 400 / 403
NO-->>A: error
A-->>U: 400 / 403 {"detail": …}
end
A->>GL: GET /v2/images?id=in:<≤100 ids> (system session, per batch)
A->>CI: GET /volumes/detail?all_tenants=True&id=[<≤100 ids>] (system session, per batch)
A->>KS: GET /v3/projects (user session, names)
A-->>U: 200 {"servers": [...]} (500 if an ID is not a UUID v4)Diagnostics: a 500 with a client message comes from Glance, Cinder or Keystone (the system account must be allowed to list all volumes and images); a 500 with the plain text Internal Server Error is a response-model failure (non-UUID-v4 ID).
5. Logout
sequenceDiagram
autonumber
actor U as Browser
participant A as skyline-apiserver
participant KS as Keystone
participant DB as Skyline DB
U->>A: POST /api/v1/logout (cookie)
Note over A: middleware validation (scenario 3)
A->>KS: GET /v3/auth/tokens (re-validation from the JWT)
A->>KS: POST /v3/auth/tokens (user session)
A->>KS: DELETE /v3/auth/tokens (X-Subject-Token = user token)
A->>DB: INSERT revoked_token (uuid, exp)
Note over A: any error above is logged at DEBUG and ignored
A-->>U: 200 {"message": "Logout OK"} + delete cookie session
U->>A: GET /api/v1/profile with the old cookie
A-->>U: 401 {"message": "Unauthorized: Token revoked"}Diagnostics: logout always answers 200; if the Keystone token is still valid afterwards, look for a DEBUG line in the log.
6. WebSSO (federated login)
sequenceDiagram
autonumber
actor U as Browser
participant A as skyline-apiserver
participant KS as Keystone
participant IdP as Identity provider
U->>A: GET /api/v1/sso
A-->>U: {"enable_sso": true, "protocols": [{url: KS/auth/OS-FEDERATION/…/websso?origin=…/api/v1/websso}]}
U->>KS: GET …/websso?origin=…
KS->>IdP: redirect (OIDC / SAML)
IdP-->>KS: assertion
KS-->>U: HTML form auto-posting the unscoped token to origin
U->>A: POST /api/v1/websso (form token=…)
A->>KS: POST /v3/auth/tokens (token, unscoped) + GET /v3/auth/projects
Note over A: then as scenario 1 in region sso_region
A-->>U: 302 Location: /base/overview + Set-Cookie session, time_expiredDiagnostics: the origin is built from the request's Host and ssl_enabled; behind a proxy that rewrites Host, Keystone's trusted_dashboard must list exactly that URL. The redirect target /base/overview ignores nginx_prefix.
Source: reverse-spec-skyline-apiserver/04-scenarios_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.