Using SaltStack for temporary sudoers access — SaltSudo

Mike R
4 min readNov 6, 2018

SaltSudo

This article shows how easy it is to extend Saltstack and its very rich Python module system to fit into your company’s work requirements.

At my company, we sometimes have an emergency case, for example if one of our production servers runs out of disk space, which in turn stops processes and creates all sorts of havoc.

While we have monitoring in place, emergencies do come up where someone other than the primary sysadmin (on vacation!) has to log in as root and fix certain issues. We also have users that need a temporary root access to a host to configure their application, and would need to get their sudo access revoked once theyre done.

I can always give out sudo access like candy, but thats obviously not a good option. To figure this out, I needed 3 main things,

  1. secure mechanism to authorize users for sudoers login to other boxes
  2. auditing of what user received the authorization
  3. ACL control of what users can give themselves this authorization

Offcourse all this can be done via Bash/Python/etc script, but being a heavy user of Salt, I decided to use Salt’s excellent modular structure + native ACL capability to do this

How the process works

  1. Lets say we have a server called nycweb01, its at 98% disk capacity on /home
  2. I have authorized a manager/head user Mary to be able to SSH into the Salt Master server (as her own non-root accounts) and give root access to company servers to her non-root subordinate, Frank
  3. they do this via the following command
mary@saltmaster: salt nycweb01 sudo.grant frank 'fixing disk space issue'nycweb01:
User 'frank' has been added to Sudoers group, they can now run root-level commands using 'sudo cmd'

SSH as 'frank@nycweb01'

To revoke sudo access, run 'salt nycweb01 sudo.revoke frank'

This module will add Frank to a custom sudoers file on nycweb01:

root@nycweb01> cat /etc/sudoers.d/salt_sudo
frank ALL=(ALL) NOPASSWD:ALL

and also send out a notification email to admins@company email address, for auditing purposes. It will also log all these actions into /var/log/salt/minion log file

example of email:

ALERT 2019-02-26 11:50:
sudo_mary has ran "salt nycweb01 sudo.grant frank" to request sudo access for: Frank Castle

Comment: fixing disk space issue
--------------------------------------------------
User 'frank' has been added to Sudoers group, they can now run root-level commands using 'sudo cmd'

SSH as 'frank@nycweb01'

To revoke sudo access, run 'salt nycweb01 sudo.revoke frank'

* frank has been given sudo access for 2 hours

4. Once Mary runs this command, her coworker Frank (non-admin) can now SSH into nycweb01 and fix the disk space issue

frank@franksMac: ssh frank@nycweb01
frank@nycweb01:
frank@nycweb01: sudo su
root@nycweb01

5. Now that Frank is root on nycweb01, he does his cleanup work, exits the SSH session

6. To close up temp sudo access to the server, Mary runs the ‘sudo.revoke’ command which will remove all users from the /etc/sudoers.d/salt_sudo file from the server, thus disabling temporary sudo access for all users (this does not affect users who have permanent sudo, this entire module is sandboxed and will not touch your other configurations). To automatically revoke access, see the next section

joe@saltmaster: salt nycweb01 sudo.revoke
nycweb01:
all temporary sudo access has been removed.

to revoke only a specific user, run the same command and pass the username

salt nycweb01 sudo.revoke frank

Access Lifetime span

You can also pass a time-based expiration to the access by passing “span=” flag.

salt nycweb01 sudo.grant frank 'fixing disk space' span=4h

This will give Frank 4 hours to fix the issue, until his sudo access expires. This is done via a custom crontab entry that this module adds for the user (it calculates the future expiration time and adds a cron to remove user from custom sudo file (as well as removing the cron itself once it runs)

Span can be passed as either days or hours, ie,

span=5d
span=2h

The Magic that makes this happen

Heres how Sudo module works,

This custom module extend’s Salt module system to pull out certain variables like group.add, group.info, smtp.send_msg, etc

This makes it very easy to use the entire Salt execution module library to do whatever action you want on the target server. This keeps the code simple and clean.

To allow Mary to run any sudo.* command, a simple Salt config update is required,

root@saltmaster> vim /etc/salt/master.d/auth.confpublisher_acl:
mary:
- test.ping
- grains.*
- sudo.*
# then restart salt-master

Code

https://gist.github.com/perfecto25/f7a682cb5dca17bdd9c0bd5aa6394bd1

Simply add this code as sudo.py to your Salt State path (ie, /srv/salt/states/_modules), and refresh your minions with this custom module,

salt \* saltutil.sync_all

You can now run this functionality across your entire infrastructure.

Full documentation for SaltSudo module usage

sudo.status - returns any user that has temporary sudo access to the host
> salt nycweb01 sudo.status
sudo.grant - grants sudo access to user
examples:
> salt nycweb01 sudo.grant jsmith 'fixing disk space'
to add a timelimit pass a 'span=' flag with 'd' for days or 'h' for hours
> salt nycweb01 sudo.grant jsmith 'fixing disk' span=3d
sudo.revoke - revokes temp sudo access for all users configured with temp accessto revoke a specific user only, pass the username to the command
> salt nycweb01 sudo.revoke jsmith

--

--