Skip to content

Sudo Multi Machine Overhaul

Marius Vollmer edited this page Jan 28, 2020 · 23 revisions

Use cases / requirements

As a user using Cockpit for a single machine at a time (with or without a bastion host in the middle) ...

  • I want to log into Cockpit with my personal wheel account and immediately be able to do superuser tasks. [sudo-immediate]

    My personal account is in the "wheel" group (or equivalent) and I can run things like "sudo su" on the command line. Sudo might ask for the password of my personal account, or it might not. Cockpit should remember my password from the login screen and give it to sudo during login.

  • I want to log into Cockpit with my personal wheel account but Cockpit should not be able to do superuser tasks. [sudo-prevent]

    My personal account is in the "wheel" group (or equivalent) and I can run things like "sudo su" on the command line. Sudo might ask for the password of my personal account, or it might not. Cockpit should not remember my password from the login screen and should not give it to sudo. Even if sudo wont ask for a password, Cockpit should not give the session superuser powers.

  • I want to take away from Cockpit the ability to do superuser tasks in a session. [sudo-stop]

    After gaining superuser powers as with "sudo-immediate" or "sudo-start", I want Cockpit to kill the sudo that it has started. From that point on, Cockpit should behave as if I had logged in with "sudo-prevent".

  • I want to give to Cockpit the ability to do superuser tasks in a session. [sudo-start]

    While not having superuser powers as after "sudo-prevent" or "sudo-stop", I want Cockpit to gain these powers.

    My personal account is in the "wheel" group (or equivalent) and I can run things like "sudo su" on the command line. Sudo might ask for the password of my personal account, or it might not. Cockpit should ask me for my password if necessary and only if necessary.

  • I want Cockpit to remember whether the last session had superuser powers for the next session (in the same browser for the same user). [sudo-sticky]

    After logging out, I want Cockpit to either behave like "sudo-immediate" or "sudo-prevent" by default on the next login.

    This should also work if the next login doesn't actually involve a login page where I could change this setting, such as with a automatic Kerberos or OAuth login.

  • I want the login to succeed even if my personal account can't run sudo. [sudo-failure-is-fine]

    If my personal account can't run things like "sudo su", maybe because it is not in the "wheel" group, and I ask for superuser powers during login (or the previous session did have superuser powers), I want the login to still succeed but of course without superuser powers in the session.

As a user using Cockpit for a multiple machines (with or without a bastion host in the middle to get to the primary machine) ...

  • I want to access a secondary machine via SSH from a primary machine. [ssh]

    I can access the secondary machine with "ssh HOST" or "ssh USER@HOST" on the command line and Cockpit should use that ability to start a session on that machine. If a password or passphrase is necessary, Cockpit should ask for it.

  • I want to use a specific account for a secondary session. [ssh-user]

    Cockpit should not assume that the account of the primary session is the correct one for secondary sessions. Using a different one should not give the impression that it's a workaround for a configuration problem.

  • I want to use a specific SSH identity for a secondary session. [ssh-identity]

  • I want to use a specific port for a secondary session. [ssh-port]

    Cockpit should assume that port 22 is the SSH port on the secondary machine, but it should allow the specification of a different one, without confusing people who don't know anything about ports.

  • I want Cockpit to use my ~/.ssh/config for a secondary session. [ssh-config]

  • I want Cockpit to have my private keys ready for use during the primary session. [ssh-agent]

    If accessing secondary machines requires the unlocking of passphrase protected keys, I only want to specify and unlock each key once, even if it is used multiple times.

  • I want Cockpit to drop one of the keys that it holds ready. [ssh-agent-remove]

  • I want Cockpit to automatically unlock keys with my password on login to the primary session. [ssh-auto-agent]

    If a SSH key is protected by a passphrase that is equal to my password, I might want that key to be unlocked during login and automatically be used afterwards. There should be a way to request that for specific keys.

  • I want to close a session on a secondary machine without completely logging out of Cockpit. [ssh-close]

  • I want Cockpit to remember recently closed secondary sessions for easy reconnecting. [ssh-history]

    When opening a secondary session, I would like to be able to just pick from the most recent 10 sessions or so. This should bring back the host for that session (obviously), but also account, ssh port, and ssh identity, etc.

  • I want Cockpit to remember the secondary sessions from one primary session to the next. [sticky-ssh]

    When logging into a primary session, I want all the secondary sessions from the last time to still be there so that I don't need to set then up explicitly again.

    An actual connection to a secondary machine should only be opened on demand. At that point, Cockpit should ask for necessary passwords and passphrases.

  • I want to manage superuser powers for the secondary sessions just like for the primary one. [ssh-sudo]

    For each session (primary and secondary), I want to control whether or not that session has superuser powers. The current state should be remembered for the next time.

  • I want to clearly see the state of sessions. [session-state]

    I want to see which is my primary session, and which are the secondary sessions. I want to see which account is used in a given session and whether or not it currently has superuser powers.

  • I want to setup public key authentication for SSH. [ssh-setup]

    I want password-less access to secondary machines, but I need help creating and copying SSH keys.


Omitted

  • I want to have arbitrarily nested SSH sessions. [ssh-inception]

    Everything about secondary sessions should hold for "tertiary" sessions that are accessed via SSH from a secondary session. And so on and on ...

  • I want to give to Cockpit the ability to do a single superuser task in a session. [one-shot-sudo]

    If a task requires superuser powers, Cockpit should perform it with sudo and ask me for a password if necessary. The password should not be used for anything else.

  • I don't want to be prompted for a password for a secondary machine if it matches my password for the primary machine. [ssh-auto-password]

    I have my machines setup to all have the same accounts with the same password (NIS/YP/FreeIPA/...). If I access a secondary machine I want Cockpit to try my login password first.


UX

Login screen:

  • No "[ ] Reuse my password" checkbox. Cockpit can remember from the last session for this user whether or not it had superuser powers. The way change that is to drop/gain those powers in the session, and that will optionally stick to the next session. On the very first login, the session will not get superuser powers.

Shell navigation:

  • [ designed elsewhere ]

  • When opening a new SSH connection to a secondary machine:

     Connect to remote host
    
     Address:         ____________________________
     Login:           ____________________________
    

    The "Address" field does autocompletion for recently used addresses and addresses from machines.d. If a auto-completed address is selected, that will also pre-fill the "Login" field the "Credentials for HOST" dialog below. (Note that using a auto-completed address will just provide the defaults for the Credentials dialog, it will not immediately use them on the first connection.)

    After adding a machine, it appears in the [HOST v] selector in the top row and will be selected immediately.

    The SSH port can be added to the address like host:22.

    When the log in doesn't succeed non-interactively upon connecting, Cockpit starts asking for input. (This should be like our existing Troubleshoot dialog but talk less about "failure", and also allow specifying SSH identities.)

     Credentials for HOST
    
     Login:           <login>______________________
     Authentication:  Password                    v
     Password:        _____________________________
    

    The "Login" is repeated here to remind people which password they are supposed to type, and also to give them a chance to correct a mistake. Also, also, new machines can come from typed in URLs and in that case we need to give the user a chance to specify it.

    Instead of "Password" authentication, there is also at least "Key":

     Credentials for HOST
    
     Login:           <login>______________________
     Authentication:  Key                         v
     Key:             id_rsa                      v
     Passphrase:      _____________________________
    
     If the passphrase for this key is the same as your login password,
     the Web Console can automatically unlock it during log in.
    
     [ ] Make it so.
    

    The "Key" dropdown lists all files in ~/.ssh/ that have the right permissions and have a corresponding ".pub" sibling, or whatever is appropriate to list all available SSH keys.

    The choice of key will be remembered for the next connection to this machine, just like the "Login".


Discussion

  • mvo: Because of "sudo-sticky" we might not need a "reuse my password" checkbox on the login page at all. Win!

  • mvo: The browser will remember a whole lot from one session to the next, including the list of secondary sessions and all their params. This replaces /etc/cockpit/machines.d/. The dashboard would still manage machines.d (for backward compat), but the shell would not.

    pitti: machines.d/ is there so that you can easily pre-populate the dashboard through Ansible scripts, or generate the JSON files from your local network data. It also shares multiple machines state between several administrators. It could instead grow the fields that we are missing, such as a non-default identity and whether or not the machine is currently connected?

    pitti: I think [ssh-identity] should be persistent (see ssh-history and sticky-ssh). But I don't yet have a solid opinion where to persist this choice. ~/.ssh/config would be ideal, but I am rather afraid of programmatically changing it -- not just because it's very sensitive and error prone, but also because this could be considered intrusive by users. So machines.d/ JSON would be the logical alternative, and given that it already overrides other settings from ssh config (at least the port), it would not be too bad to add the identity there as well? In many cases the identity would already be part of ~/.ssh/config, and we should certainly use it if it's there (ssh-config).

    mvo: I want to move the shell away from machines.d. I feel that the set of machines you are connected to depends on the task you are doing, and forcing everyone to work with a single list seems limiting. Maybe we could actually omit sticky-ssh altogether. Dashboards like our current one where you carefully maintain a view of your infrastructur are useful and I want to keep it, and in fact we should probably invest a bit to make it more capable than just a single list. But I feel that the shell should be independent of it. I should do some survey of what people are actually doing with the dashboard.

    mvo: The dashboard should certainly feed ssh-history so that connecting to a machine from the shell that is already known is super easy.

  • mvo: Cockpit will no longer use a stored password to log into secondary machines. The way to get prompt-less access is to set up key auth for SSH, maybe using the login password as the passphrase. Cockpit can explain this at length and help with generating the keys and copying them over to the secondary machine.

    pitti: This was meant to be "poor admin's IdM", so if you centrally manage your logins with NIS/YP or such, it would just work. With proper IdM you'd just use kerberos SSO and not deal with passwords in Cockpit in the first place, of course. Setting up SSH keys sounds good to me, but rather complex and of secondary importance to me to clean this all up.

    mvo: I think it's confusing for Cockpit to assume that your shop is setup like this. And if it is not, Cockpit tells you that there is a problem that needs trouble shooting. I want to turn this around and not have Cockpit make this assumption and more closely reflect how SSH works. If you access a secondary machine, of course you need to log in with your password, anything else would be magical and actually disturbing, no? And from there, Cockpit can maybe help you add convience, maybe even by remembering your login password, but only after explicit request. Not because remembering the password would be unsafe per se, but because then the user understands what is going on and is no longer surprised and disturbed.

    pitti: If you remove a host from the dashboard, it just gets marked as invisible in machines JSON. That's a good place to remember previous sessions. Adding a host could offer typeahead search, too.

  • mvo: I would consider removing the user synch feature. I think it's too easy to cause chaos with it.

    pitti: That's part of "poor admin's IdM", but without centrally managed NSS. I agree that this feels over the top and hackish.

  • mvo: Because of the above, Cockpit doesn't need to remember the login password after login is complete. It still needs to give it out to sudo and right now sudo is started only on-demand but maybe making it "one-time-use" would work. It's not super critical to delete the password from cockpit-ws, I think, but it would be cleaner.

    pitti: It's quite important as cockpit-ws multiplexes a lot of sessions, and has a very vulnerable attack surface. So the password should always be transient in cockpit-ws only, basically only live between /cockpit/login and calling the session handler. The authorization conversation should "use up" the password, i. e. delete it afterwards ideally.

  • mvo: Instead of

     cockpit-session -> cockpit-bridge -> sudo cockpit-bridge --privileged
    

    we could have

     cockpit-session -> sudo cockpit-bridge
    

    for superuser sessions? The "superuser" option to channels wouldn't try to start anything on demand.

    pitti: Wouldn't that make sudo-start next to impossible?

    mvo: In order to implement dropping/gaining privileges inside the session, cockpit-bridge would need to re-exec itself in some tricky way. Also, this would probably make it harder to change privilege levels without a full reload of the pages. So...

  • andreasn: "No "[ ] Reuse my password" checkbox. Cockpit will remember from the last session for this user whether or not it had superuser powers." What is the behavior on the very first login ever?

    mvo: No sudo on the first login ever, I'd say. This gives us the opportunity to teach people about how this works on Unix.

  • andreasn: I don't quite understand the shell navigation UX part. Would need some examples I think.

    mvo: Yes, I am totally in the middle of that.

  • pitti: [ssh-auto-agen] is apparently what Cockpit does right now, but it feels rather opportunistic/inconsistent to me. gnome-keyring does that more explicitly: It offers to remember your gpg/ssh passphrases and stores that in its keyring. I most certainly don't want Cockpit to maintain its own keyring. I'm not sure whether we should encourage users to use the same passphrase for account and SSH keys -- is that considered best practice?

    mvo: Interesting, I had just assumed that the agent thing is best practice. We should at least make it explicit so that no key is automatically loaded unless the user has requested it. I have changed the text.

  • pitt: [sudo-one-shot] This is not well-defined. E. g. technically, launching cockpit-bridge is one action, but conceptually it is not. Likewise, setting up a D-Bus signal listener might feel like a continuous thing. It seems better to explicitly get or drop privileges, as above. So big +1 for not doing this.

  • mvo: The text above only talks about sudo, but this is always meant to include pkexec.

  • mvo: Dashboards... I think we abuse the dashboard navigation category for applications. The real dashboard only really makes sense for the primary session, but applications like Fleet Commander or Image Builder should also be accessible on secondary machines.

  • mvo: We could allow URLs like https://dev.mvo.lan:9090/frodo@192.168.100.234 where the user name for the remote machine is specified explicitly.

  • mvo: The stretch use case here is probably using a dashboard/application via ssh as superuser via a bastion host. Secondary machines via bastion hosts don't work right now.

Clone this wiki locally