In this episode, we will discuss giving automated tasks narrow root privileges via the sudo command using the nopasswd option.
As a sysadmin, you will likely find yourself in a situation, where it would be useful to delegate root level privileges to non-root users. There could be any number of reasons to do this, lets say that you are working closely with a group of developers, and they need access to restart httpd each time a code deployment is pushed out. Initially this will be a manual process but the hope is that it can be automated.
Giving the group root access would be overkill since all they need to do it restart httpd. Luckily this is a well understood requirement and the sudo command was built with this in mind. The sudo command allows a permitted user, or group of users, to execute superuser command as defined by a configuration file. What is so great about sudo, is that you can define very narrow root access with the added bonus that there is built in logging.
With the requirements in mind, lets look at a demo. I have configure an example virtual machine with a deployment account, and this deployment account will be used by our developers to push their code deployments as well as restart httpd via the sudo command.
Right now I am logged in as the deployment account, and I want to show you what it looks like when I try change the state of httpd, as a non-root user. Lets run /etc/init.d/httpd and you will be given a listing of the supported commands. I should point out that I am using CentOS so your output might look different, however the overall theme of this episode will work across distros.
Okay, so you can see we have many commands to choose from. Lets try to check the status by running /etc/init.d/httpd status. So, httpd is off right now. Lets try and turn it on with /etc/init.d/httpd start. As you can see, we were able to execute the init script, but there are a bunch of failures when it tries to change the state. Same goes to stopping the service via /etc/init.d/httpd stop. This is ultimately because we need to be root for this to work.
/etc/init.d/httpd status /etc/init.d/httpd start /etc/init.d/httpd stop
Well, this is a good starting point, since we have our requirements and a problem to fix. Through the magic of video editing I have changed accounts from deployment to root. Before we begin editing files, I should mention that you can always refer to the manual pages for the sudo command and its configuration files. As I pointed out in episode 19, you can use man -k to search the manual pages for a keyword. Lets search for sudo.
man -k sudo
Okay, so we several manual pages that look interesting, specifically the sudo command, visudo, and sudoers. The sudo command can be used to execute commands as the superuser like we talked about earlier, the visudo command is used to edit the sudoers file, the good this about this vs using your favourite editor, is that visudo does syntax checking when you save. Finally, the sudoers manual page talks about the configuration file syntax, which can be useful for finding the correct command syntax.
Okay, so lets use visudo to edit the sudoers file and add entries so that the deployment account can stop, start, and restart httpd. I am just going to paste the lines and then explain what they do.
These first couple lines are not required but I often add them for the sake of figuring out where these requirements came from. So, if there was a helpdesk request or something similar which outlined the requirements, I will put in a couple comments so there is some traceability. This is especially important when you have multiple sysadmins running around.
# helpdesk ticket #1234 # aid software deployment for dev group deployment ALL=(root) NOPASSWD: /etc/init.d/httpd start deployment ALL=(root) NOPASSWD: /etc/init.d/httpd stop deployment ALL=(root) NOPASSWD: /etc/init.d/httpd restart
So, let me just explain what the overall theme is with these commands. The first value here defines the user, or group of users, we want to apply this rule to. In our case, the deployment user will be the one running the commands. The second value defines the machine the command can run on. In my many years as a sysadmin I have never had to use anything other than ALL. I guess this is used if you deploy one master sudo file across a large cluster of machines and need to lock things down based off hostnames. The third value defines the account to be used, in our case, we want to execute the command as root. The fourth value is interesting, in that we are telling sudo not to prompt asking for a password. This is important because if the developer group wishes to automate this via a script they will not want to be prompted for a password. Finally, we provide the command that the deployment user is allowed to execute.
You will notice that I have defined the command arguments as start, stop, and restart. I have done this because if you leave these off, it tells sudo that the user has blanket permissions to run this command with any arguments. For this reason, it is good practice to limit the command line arguments to only the functionality you wish to allow. In our case, we want to lock this down to start, stop, and restart.
Okay, so we lets save the file. And once again, through the magic of video editing I have changed accounts from root to deployment. So, now lets run our commands again, but this time prefixing with sudo.
As you can see, we can now start, stop, and restart httpd without being prompted for a password.
sudo /etc/init.d/httpd start sudo /etc/init.d/httpd stop sudo /etc/init.d/httpd start sudo /etc/init.d/httpd restart
Lets just try running the status command via sudo so that we can compare allowed commands vs undefined ones. You will notice that we are prompted for a password and ultimately denied because the command was never defined in the sudoers configuration file.
sudo /etc/init.d/httpd status
So, we have effectively completed the users request via adding entries to the sudoers file. There are a couple other things I wanted to point out before ending this episode.
Depending on your distro, you might have a directory called /etc/sudoers.d/ where you can package up your custom sudoers line into nice little files. This can be handy if you have a large sudoers file and want to break it apart into smaller manageable chunks.
One final thing before we end. Earlier in the episode, I talked about sudo leaving an audit trail, again it depends on your distro, but my sudo commands are logged to /var/log/secure. Lets quickly take a peak. You can see the allowed commands and also the denied one.