Puppet + Subversion + SELinux
published
Puppet is “an enterprise systems management platform” that can be used to control the configuration of many servers, in theory substantially reducing the management effort of systems administrators. We use Puppet at work, and I was recently tasked with migrating the Puppet service to a new server. The actual migration was easy enough, thanks to a tip from a Puppet user I know.
While I was working with Puppet, I decided to make a couple of small improvements to the way we use it. The Puppet documentation recommends using version control for the Puppet files, and we’d been doing that but deploying the configuration from Subversion into /etc/puppet was an entirely manual process. I wanted to set up a Subversion post-commit hook so that simply checking new stuff into the repository would automatically get pushed to the live system.
The default location for the Puppet files is /etc/puppet. The Subversion repository we’re using is stored on the same server, so I made a check-out of our files into /etc/puppet:
$ cd /etc/puppet $ sudo svn co file:///usr/local/svn/puppet .
I checked out the Puppet repository onto my local workstation, so I can work on the files there, and then commit them back. That works fine.
So I set up the following post-commit hook for the Puppet repository:
#!/bin/sh # update the local checkout of Puppet manifests export HOME=/tmp REPOS="$1" REV="$2" /usr/bin/svn up /etc/puppet
I access the repository from my workstation over https using Apache’s mod_dav_svn, so the post-commit hook runs as the Apache user. This means the Apache user needs write access to /etc/puppet. That’s an easy chmod. But even after that, the post-commit hook failed with a permission denied problem. So I chown’ed the files to Apache, but still no luck writing there.
The SELinux context on /etc/puppet is system_u:object_r:puppet_etc_t, and SELinux’s audit log confirms that Apache, via httpd_sys_script_t, does not have permission to do the necessary operations inside /etc/puppet.
Through a series of iterations with ausearch -m avc -ts recent | audit2allow -r, I worked up the following SELinux policy module:
module local 1.0;require {
type httpd_sys_script_t;
type puppet_etc_t;
class file { rename setattr unlink write };
class dir remove_name;
}#============= httpd_sys_script_t ==============
allow httpd_sys_script_t puppet_etc_t:file rename;
allow httpd_sys_script_t puppet_etc_t:file setattr;
allow httpd_sys_script_t puppet_etc_t:file unlink;
allow httpd_sys_script_t puppet_etc_t:file write;
allow httpd_sys_script_t puppet_etc_t:dir remove_name;
As root, I built and installed the module using these commands:
# checkmodule -M -m -o local.mod local.te # semodule_package -o local.pp -m local.mod # semodule -i local.pp
Now my post-commit hook works as expected: /etc/puppet is updated whenever I commit something to the repository from my workstation.
My questions are:
- is my policy too permissive?
- what alternatives might exist to this solution?
- are there any subtle gotchas that might cause trouble?
This is my first time writing an SELinux policy, so I wouldn’t mind some feedback on it. I posted this same question to the Central Ohio Linux User Group mailing list, so check there for follow-ups, too.