You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While the existing document describes the protocol, it is hard to see
how all the moving parts communicate together. Describe the steps for
user/password, Kerberos, and client certificate authentication schemes.
Assisted-By: Claude code (initial mermaid diagram and proofreading)
Copy file name to clipboardExpand all lines: doc/authentication.md
+83Lines changed: 83 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -203,3 +203,86 @@ SSH connections:
203
203
204
204
***COCKPIT_SSH_KNOWN_HOSTS_FILE** Path to knownhost files. Defaults to
205
205
`PACKAGE_SYSCONF_DIR/ssh/ssh_known_hosts`
206
+
207
+
Login process: User/Password
208
+
----------------------------
209
+
210
+
1._User_ connects to cockpit URL, which lands at _cockpit-tls_
211
+
2._cockpit-tls_ connects to _cockpit-ws_ via the `cockpit-wsinstance-http@` or `cockpit-wsinstance-https@SHA256_NIL` systemd socket/service. See [cockpit-tls docs](../src/tls/README.md) and [systemd units](../src/systemd/) for details.
212
+
3._cockpit-ws_ responds with "401 Authentication failed" and sends the Login page
213
+
4._User_ fills in username/password and clicks "Log In". The login page sends a new request to _cockpit-ws_ with an `Authorization: Basic base64(user password)` header
214
+
5._cockpit-ws_ looks at `cockpit.conf` whether it has a customized session command for `basic`. If not, defaults to `cockpit-session`. It parses user/password from the header and spawns the session command with the target host as argument.
215
+
6._cockpit-session_ sends an `authorize` command with a `*` challenge (see above) to _cockpit-ws_, which responds with the user/password
216
+
7._cockpit-session_ starts a _PAM_ session for the user, and sets the initial credential to the received password
217
+
8. If _PAM_ sends more messages, like e.g. 2FA prompts or changing expired passwords:
218
+
*_cockpit-session_ sends corresponding `X-Conversation` authorize messages (see above) to _cockpit-ws_
219
+
*_cockpit-ws_ forwards them to the Login page, which displays the text, and sends the user response as the authorize reply
220
+
*_cockpit-ws_ forwards the authorize reply to PAM
221
+
9. When PAM succeeds, _cockpit-session_ executes the bridge, and connects its stdio pipes to it, then _cockpit-ws_ starts the websocket on it
222
+
223
+
```mermaid
224
+
sequenceDiagram
225
+
participant User
226
+
participant cockpit-tls
227
+
participant cockpit-ws
228
+
participant cockpit-session
229
+
participant PAM
230
+
231
+
User->>cockpit-tls: https://server:9090
232
+
cockpit-tls->>cockpit-ws: Connect via systemd socket
233
+
cockpit-ws->>User: 401 + Login page
234
+
User->>cockpit-ws: POST with Authorization: Basic
235
+
cockpit-ws->>cockpit-session: Spawn
236
+
cockpit-session->>cockpit-ws: authorize command with * challenge
1._User_ connects to cockpit URL, which lands at _cockpit-tls_
257
+
2._cockpit-tls_ connects to _cockpit-ws_ via the `cockpit-wsinstance-http@` or `cockpit-wsinstance-https@SHA256_NIL` systemd socket/service. See [cockpit-tls docs](../src/tls/README.md) and [systemd units](../src/systemd/) for details.
258
+
3._cockpit-ws_ responds with "401 Authentication failed" and includes `WWW-Authenticate: Negotiate` header (if Kerberos is available)
259
+
4._Browser_ (if configured for SPNEGO/Kerberos) requests a service ticket from the _KDC_ for the HTTP service principal
260
+
5._Browser_ sends a new request with `Authorization: Negotiate <base64-gssapi-token>` header
261
+
6._cockpit-ws_ looks at `cockpit.conf` whether it has a customized session command for `negotiate`. If not, defaults to `cockpit-session`. It spawns the session command with the target host as argument.
262
+
7._cockpit-session_ calls `gss_accept_sec_context()` with the GSSAPI token to verify the Kerberos ticket
263
+
8. If GSSAPI returns `GSS_S_CONTINUE_NEEDED` (multi-round negotiation):
264
+
*_cockpit-session_ sends an authorize command with a `Negotiate` challenge containing the output token to _cockpit-ws_
265
+
*_cockpit-ws_ responds with "401 Authentication failed" and `WWW-Authenticate: Negotiate <token>` to the _Browser_
266
+
*_Browser_ sends another `Authorization: Negotiate <token>` request
267
+
* This continues until GSSAPI negotiation completes
268
+
9. When GSSAPI succeeds, _cockpit-session_ has the authenticated GSSAPI principal name
269
+
10._cockpit-session_ maps the GSSAPI name to a local username using `gss_localname()` (which applies configured mapping rules), or if that fails, falls back to `gss_display_name()` which returns the principal name as-is (e.g. `[email protected]`)
270
+
11._cockpit-session_ starts _PAM_, skipping the auth stack (as GSSAPI already authenticated), and runs the account, credential, and session stacks
271
+
12._cockpit-session_ stores the delegated Kerberos credentials (if delegation was negotiated) in a credential cache at `/run/user/<uid>/cockpit-session-<pid>.ccache` and sets `KRB5CCNAME` in the PAM environment, so that the bridge can use them for accessing other Kerberos-protected services (like SSH to remote machines)
272
+
13._cockpit-session_ executes the bridge, and connects its stdio pipes to it, then _cockpit-ws_ starts the websocket on it
273
+
274
+
Login process: Client Certificate
275
+
----------------------------------
276
+
277
+
1._User_ connects to cockpit URL with a client certificate, which lands at _cockpit-tls_
278
+
2._cockpit-tls_ calculates the SHA256(certificate) as the user fingerprint
279
+
3._cockpit-tls_ connects to the `cockpit-wsinstance-https@<fingerprint>` systemd socket/service (starting a dedicated _cockpit-ws_ instance for this certificate if needed). See [cockpit-tls docs](../src/tls/README.md) and [systemd units](../src/systemd/) for details.
280
+
4._cockpit-tls_ exports the certificate to `/run/cockpit/tls/clients/<fingerprint>` (kept as long as there is at least one active connection with that certificate)
281
+
5._cockpit-tls_ includes `"client-certificate": "<fingerprint>"` in its mini JSON protocol to _cockpit-ws_
282
+
6._cockpit-ws_ detects the client certificate metadata and uses `tls-cert <fingerprint>` as the authorization type
283
+
7._cockpit-ws_ looks at `cockpit.conf` whether it has a customized session command for `tls-cert`. If not, defaults to `cockpit-session`. It spawns the session command with the target host as argument.
284
+
8._cockpit-session_ receives the `tls-cert <fingerprint>` authorization and reads the certificate from `/run/cockpit/tls/clients/<fingerprint>`
285
+
9._cockpit-session_ validates that the certificate file exists and matches the expected _cockpit-ws_ cgroup
286
+
10._cockpit-session_ calls the _sssd_ D-Bus API (`org.freedesktop.sssd.infopipe.Users.FindByCertificate`) to map the certificate to a username
287
+
11. When successful, _cockpit-session_ sets the username and starts _PAM_, skipping the auth stack (as the certificate itself was the authentication), and runs the account, credential, and session stacks
288
+
12._cockpit-session_ executes the bridge, and connects its stdio pipes to it, then _cockpit-ws_ starts the websocket on it
0 commit comments