-
Notifications
You must be signed in to change notification settings - Fork 1.2k
doc: Login process #22560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
doc: Login process #22560
Conversation
| 9. When PAM succeeds, _cockpit-session_ executes the bridge, and connects its stdio pipes to it, then _cockpit-ws_ starts the websocket on it | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you consider this useful, I'm happy to create diagrams for the other two as well. If not and the text variant is enough, I'm also happy to clean this up -- that just cost me 5 mins of clauding and cleaning up, as opposed to the 1.5 hours of researching and writing the text 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah diagrams are super helpful. With any potential X-Conversation stuff, are the threads still open? If possible we should show this in the diagram too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few questions after a glance through
We have default-bastion.conf that shows this:
[Basic]
Command = /container/cockpit-auth-ssh-key
It seems this would be in cockpit-ws step. Does that also mean python3 -m cockpit.beiboot is executed within cockpit-ws?
Is it possible to create and return a challenge from cockpit-ws? Something like this?
sequenceDiagram
user->>+cockpit-ws: POST with Authorization: passkey <empty>
cockpit-ws->>+user: login-options + generated challenge
user->>+cockpit-ws: POST with Authorization: passkey <signature>
How does interactive processes work? Given the text and chart it does seem like the process remains open (I'm guessing for the default 30s timeout) I assume we detect the output from the process and simply return X-Conversation and await response?
| 9. When PAM succeeds, _cockpit-session_ executes the bridge, and connects its stdio pipes to it, then _cockpit-ws_ starts the websocket on it | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah diagrams are super helpful. With any potential X-Conversation stuff, are the threads still open? If possible we should show this in the diagram too
817b880 to
2168c9d
Compare
That's correct, it's a direct child. I added a section "Login process: SSH to remote machine" now. It's 'orribly complicated, and may have some wrong details -- I'd really like @allisonkarlitskaya to proofread that.
I might be missing something, but I'm pretty sure it's "no". cockpit-ws does not know much about specific auth protocols. It just knows how to communicate with session starters like
Yes, that's my understanding. Session programs can send authorize/conversation messages, and ws is the mediator to send them back and forth to the UI.
Which threads? Conversations happens as an ongoing protocol between login.js, cockpit-ws and a running session process, I think that's what you mean. Only the host key (and possibly initial password?) steps are different and rather stupid, as ws keeps spawning new I'm sorry, I am really hazy beyond this point. |
|
Thanks that clears it up a bit
Yeah, the running session process is what I meant. Particularly cause I wasn't sure how to return a challenge to the browser and then also verify said challenge when user sends the signed message that includes the challenge. |
|
@Venefilyn Right, that should work with X-Conversation messages. |
|
@martinpitt, I think the last two steps in the diagram about "start bridge, connect stdio" and "start websocket" are confusing/wrongish and not necessary to explain the login process. The show starts when cockpit-ws returns the actual HTML for the URL that the user is requesting. So we could end the diagram with that.
I think the diagram should end there. The websocket stuff happens a bit later:
|
|
@martinpitt, as discussed on chat, let's remove cockpit-tls from the diagram (and description) entirely. |
That happens indirectly, actually:
So we should end the diagram with the 200 response to the GET request of login.js. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See individual comments.
| ```mermaid | ||
| sequenceDiagram | ||
| participant User | ||
| participant cockpit-tls | ||
| participant cockpit-ws | ||
| participant cockpit-session | ||
| participant PAM | ||
| User->>cockpit-tls: https://server:9090 | ||
| cockpit-tls->>cockpit-ws: Connect via systemd socket | ||
| cockpit-ws->>User: 401 + Login page | ||
| User->>cockpit-ws: POST with Authorization: Basic | ||
| cockpit-ws->>cockpit-session: Spawn | ||
| cockpit-session->>cockpit-ws: authorize command with * challenge | ||
| cockpit-ws->>cockpit-session: user/password | ||
| cockpit-session->>PAM: pam_authenticate() | ||
| PAM-->>cockpit-session: Success or conversation | ||
| opt 2FA/password change | ||
| cockpit-session->>cockpit-ws: X-Conversation challenge | ||
| cockpit-ws->>User: Display prompt | ||
| User->>cockpit-ws: Response | ||
| cockpit-ws->>cockpit-session: Forward response | ||
| cockpit-session->>PAM: Continue conversation | ||
| end | ||
| PAM->>cockpit-session: Success | ||
| cockpit-session->>PAM: open_session() | ||
| cockpit-session->>cockpit-ws: Execute bridge, connect stdio | ||
| cockpit-ws->>User: Start websocket | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this be accurate? Added bars to indicate processes/requests being opened and closed
sequenceDiagram
participant User
participant cockpit-tls
participant cockpit-ws
participant cockpit-session
participant PAM
User->>cockpit-tls: https://server:9090
activate User
cockpit-tls->>cockpit-ws: Connect via systemd socket
cockpit-ws->>User: 401 + Login page
deactivate User
User->>cockpit-ws: POST with Authorization: Basic
activate User
cockpit-ws->>cockpit-session: Spawn
cockpit-session->>cockpit-ws: authorize command with * challenge
cockpit-ws->>cockpit-session: user/password
activate cockpit-ws
activate cockpit-session
cockpit-session->>PAM: pam_authenticate()
activate PAM
PAM-->>cockpit-session: Success or conversation
opt 2FA/password change
cockpit-session->>cockpit-ws: X-Conversation challenge
cockpit-ws->>User: Display prompt
deactivate User
User->>cockpit-ws: Response
activate User
cockpit-ws->>cockpit-session: Forward response
cockpit-session->>PAM: Continue conversation
end
PAM->>cockpit-session: Success
deactivate PAM
cockpit-session->>PAM: open_session()
cockpit-session->>cockpit-ws: Execute bridge, connect stdio
deactivate cockpit-session
cockpit-ws->>User: Start websocket
deactivate cockpit-ws
deactivate User
| ```mermaid | |
| sequenceDiagram | |
| participant User | |
| participant cockpit-tls | |
| participant cockpit-ws | |
| participant cockpit-session | |
| participant PAM | |
| User->>cockpit-tls: https://server:9090 | |
| cockpit-tls->>cockpit-ws: Connect via systemd socket | |
| cockpit-ws->>User: 401 + Login page | |
| User->>cockpit-ws: POST with Authorization: Basic | |
| cockpit-ws->>cockpit-session: Spawn | |
| cockpit-session->>cockpit-ws: authorize command with * challenge | |
| cockpit-ws->>cockpit-session: user/password | |
| cockpit-session->>PAM: pam_authenticate() | |
| PAM-->>cockpit-session: Success or conversation | |
| opt 2FA/password change | |
| cockpit-session->>cockpit-ws: X-Conversation challenge | |
| cockpit-ws->>User: Display prompt | |
| User->>cockpit-ws: Response | |
| cockpit-ws->>cockpit-session: Forward response | |
| cockpit-session->>PAM: Continue conversation | |
| end | |
| PAM->>cockpit-session: Success | |
| cockpit-session->>PAM: open_session() | |
| cockpit-session->>cockpit-ws: Execute bridge, connect stdio | |
| cockpit-ws->>User: Start websocket | |
| ``` | |
| ```mermaid | |
| sequenceDiagram | |
| participant User | |
| participant cockpit-tls | |
| participant cockpit-ws | |
| participant cockpit-session | |
| participant PAM | |
| User->>cockpit-tls: https://server:9090 | |
| activate User | |
| cockpit-tls->>cockpit-ws: Connect via systemd socket | |
| cockpit-ws->>User: 401 + Login page | |
| deactivate User | |
| User->>cockpit-ws: POST with Authorization: Basic | |
| activate User | |
| cockpit-ws->>cockpit-session: Spawn | |
| cockpit-session->>cockpit-ws: authorize command with * challenge | |
| cockpit-ws->>cockpit-session: user/password | |
| activate cockpit-ws | |
| activate cockpit-session | |
| cockpit-session->>PAM: pam_authenticate() | |
| activate PAM | |
| PAM-->>cockpit-session: Success or conversation | |
| opt 2FA/password change | |
| cockpit-session->>cockpit-ws: X-Conversation challenge | |
| cockpit-ws->>User: Display prompt | |
| deactivate User | |
| User->>cockpit-ws: Response | |
| activate User | |
| cockpit-ws->>cockpit-session: Forward response | |
| cockpit-session->>PAM: Continue conversation | |
| end | |
| PAM->>cockpit-session: Success | |
| deactivate PAM | |
| cockpit-session->>PAM: open_session() | |
| cockpit-session->>cockpit-ws: Execute bridge, connect stdio | |
| deactivate cockpit-session | |
| cockpit-ws->>User: Start websocket | |
| deactivate cockpit-ws | |
| deactivate User | |
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so this adds activation bars, thanks! I adapted that to the current version, and also did a small fix: PAM gets reactivated in open_session.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I had a look at this again, and now found it much more confusing than before. E.g. cockpit-ws and c-session are certainly active at the beginning as well, and generally any participant who does a step in the protocol is "active". I reverted this for now. Can you please explain a bit more what these bars mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some suggestions
| 7. _cockpit-session_ starts a _PAM_ session for the user, and sets the initial credential to the received password | ||
| 8. If _PAM_ sends more messages, like e.g. 2FA prompts or changing expired passwords: | ||
| * _cockpit-session_ sends corresponding `X-Conversation` authorize messages (see above) to _cockpit-ws_ | ||
| * _cockpit-ws_ forwards them to the Login page, which displays the text, and sends the user response as the authorize reply |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is vague. How does the login page send the response? How does -ws track multiple outstanding requests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't actually know. But also, that isn't really important for how the authentication works? Describing every aspect of cockpit is too much, at least for this PR.
doc/authentication.md
Outdated
|
|
||
| 1. _User_ connects to cockpit URL, which lands at _cockpit-tls_ | ||
| 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. | ||
| 3. _cockpit-ws_ responds with "401 Authentication failed" and includes `WWW-Authenticate: Negotiate` header (if Kerberos is available) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does -ws find out about krb being available? I think we also missed the part where the login page gets sent vs. the above sequence for passwords, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs research, I have no idea how this works.
| 1. _User_ connects to cockpit URL with a client certificate, which lands at _cockpit-tls_ | ||
| 2. _cockpit-tls_ calculates the SHA256(certificate) as the user fingerprint | ||
| 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. | ||
| 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still do that? I thought we changed over to using a random nonce here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See client_certificate_accept() for how this works now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/tls/README.md says so, it might be outdated as well.
| 6. _cockpit-ws_ detects the client certificate metadata and uses `tls-cert <fingerprint>` as the authorization type | ||
| 7. _cockpit-ws_ looks at `cockpit.conf` whether it has a customized session command for `tls-cert`. If not, defaults to `cockpit-session` and runs it in the same way as above. | ||
| 8. _cockpit-session_ receives the `tls-cert <fingerprint>` authorization and reads the certificate from `/run/cockpit/tls/clients/<fingerprint>` | ||
| 9. _cockpit-session_ validates that the certificate file exists and matches the expected _cockpit-ws_ cgroup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be worth explaining in more detail since it changed fairly substantially recently. Specifically: how do we know the cgroup of the -ws instance?
doc/authentication.md
Outdated
| Login process: SSH to remote machine | ||
| ------------------------------------ | ||
|
|
||
| 1. _User_ connects to a URL like `https://server:9090/=hostname`) or sets the "Connect to:" field in the Login page to `hostname`. See User/Password steps 2 to 4 for the precise _cockpit-tls_ / _cockpit-ws_ connection process |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs discussion about the mechanism that allows for the 'Connect To' field to appear and be considered during auth.
2168c9d to
b540568
Compare
|
Thanks for the reviews! Next push addresses @mvollmer 's review, and some parts of @allisonkarlitskaya 's. |
e9ae558 to
b540568
Compare
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)
b540568 to
6f63f0f
Compare
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)
This was prompted by my trying to explain the login process to @Venefilyn . This is my complete brain dump, plus validating the steps through code reading and running cockpit. @Venefilyn can you please check and complain about steps that are unclear and need more detail? @mvollmer and @allisonkarlitskaya I'd really appreciate your reviews, I think the three of us together ought to know all the details. Time to pen them down!
Rendered: https://github.com/martinpitt/cockpit/blob/login-process/doc/authentication.md#login-process-userpassword