Skip to content

Sudo Multi Machine Overhaul

Marius Vollmer edited this page Jan 15, 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:

  • The top row always reflects the current machine.

    [+] [HOST v]  OS-BRAND            (?) [HELP]  [PRIVS] | (A) [USER v]
    
  • The [USER v] menu applies to the current machine. It shows the account on that machine, and the Cockpit version on that machine, etc. There might be issues with "Display Language", "Log Out" and "Authentication" since they always apply to the primary session. What about

     Display Language
     ----------------
     About Cockpit
     Account Settings
     Disconnect from HOST
     ----------------
     Authentication
     Log Out
    

    The three items in the middle are for the current machine, the rest is for the primary session. The "Disconnect from HOST" is the reverse of the [+] button; maybe disconnecting should be moved closer to that button.

  • The [HELP] menu applies to the current machine.

  • The dashboards/applications would also come from the current machine.

  • The [+] button opens a new SSH connection to a secondary machine. It does not add it to machines.d.

     Connect to remote host
    
     Address:         ____________________________
     Login:           ____________________________
    
     [ ] Automatically connect to this machine when I log in.
    

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

    When checking the "Automatically connect" option, the machine will be in that selector immediately after log in, but Cockpit will only connect to it when it is actually selected the first time.

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

    When the log in doesn't succeed upon connecting:

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

    XXX - this is where the user can select a key and provide the passphrase. When doing that, they can also select whether the key should be unlocked when they log in. 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.

  • The [PRIVS] thing shows whether or not the user has superuser powers. It is not shown for root, but for any other user, regardless of whether they can actually gain superuser powers or not. It can drop or gain superuser powers. When gaining privs, a password prompt always appears:

     Credentials for unlocking privileged tasks
    
     Password:     ________________________
    
     [ ] Unlock privileged tasks automatically when I log in / when I connect to this machine
    

    The password can be left blank in case sudo doesn't ask for one, but the dialog always opens so that we can show the "Unlock automatically" option. If sudo doesn't work, there will be a useful error message.

    When that option is selected, Cockpit will try to gain superuser privs on the next connection to this machine, by giving the login password to sudo when needed. The password either comes from the Cockpit login screen or the "Credentials for HOST" dialog.


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 should also be accessible on secondary machines.

  • mvo: We could allow URLs like https://dev.mvo.lan:9090/[email protected] 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