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

Reverse-spec · Services

skyline-apiserver — Scenarios

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 + cookies

Diagnostics: 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: response

Diagnostics: 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_expired

Diagnostics: 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.