When managing servers with Chef, sometimes it’s useful to trigger a run “right now.” One of our use cases was triggering a Chef deployment of an updated application as part of a continuous integration job, prior to running acceptance tests. One of the most common ways to trigger a run is `sudo chef-client`. You may also have stumbled upon the option of sending a USR1 signal to the chef daemon process (`sudo killall -USR1 chef-client`). Depending on your configuration, the `sudo killall -USR1 chef-client` approach may not trigger the run immediately, as it uses the configured “splay” to wait a random number of seconds before running. Both of these approaches require root privileges, which may be problematic in automation scenarios.
So, how do we get the right permissions to trigger a Chef run? For the purposes of this post, I’m going to assume you are on a Unix-like operating system (in my case, Ubuntu Linux), want to trigger the run from a remote server via SSH, and don’t want/need root access for other reasons. There are several options, each with their own drawbacks.
One approach is to connect directly, as the root user. This involves the use of either username/password or public key authentication, both of which require spreading around credentials that have wide access to the server.
Another option is to connect as a user with sudo rights, which means you just need to deal with sudo requiring password entry. A bad way to deal with this is to execute sudo with the “-S” option to accept the password on STDIN, passing in the password via echo or a similar command. The password ends up being stored in multiple locations, and may end up in logs as well. A better approach is to configure sudo to allow chef-client to be run without requiring password entry. In my opinion, this is a reasonable approach. However, you still end up with a user that has more permissions than truly needed (sudo access). This approach also allows the user to perform other non-default Chef operations by specifying additional arguments to chef-client, which may not be desirable. To prevent such misuse, sudo could be configured to allow passwordless execution of a shell script that calls chef-client with the specified arguments, rather than chef-client itself.
The approach I prefer is to use the “setuid” filesystem permission bit to specify that a given executable should be run as another user (in this case, the root user). With this approach, you can allow users without any special privileges (not root, non-sudoers) to trigger standard chef-client runs (chef-client without any options) without having to provide their password again after initial authentication. You still want to keep in mind that chef-client accepts other arguments, so you don’t want to use setuid directly on chef-client. You might consider writing a shell script to control the arguments used, but setuid doesn’t work on shell scripts. The general workaround is to create a tiny binary that does what you want, and use setuid on that.
And thus, chef-kick: the tiny binary that I use with setuid to allow execution of chef-client as root, but with only the `–once` command-line argument. I have it pre-compiled and packaged for Ubuntu, along with a cookbook to facilitate installation. When you want to trigger a Chef run, just call `chef-kick`. This also works nicely when called from `knife ssh`.
– David M. Carr (GitHub)