backporting sudo’s #includedir

sudo version 1.7.2 (possibly earlier) adds the ability to fragment the sudoers file into smaller chunks via an #includedir directive. This is a boon for our use of puppet, as it affords us the ability to configure sudo in multiple modules at the same time, rather than centralizing all of our privilege escalation information in one module.

class s_gpfs
{
    [...]

    file
    { '/etc/sudoers.d/nrpe-mmfs':
      content => "nrpe ALL = NOPASSWD: /usr/lpp/mmfs/bin/mmgetstate\n",
      owner   => 'root',
      group   => 'root',
      mode    => '0440',
    }

    [...]
}

Here, we allow the nrpe user (part of our automated monitoring infrastructure) to run the gpfs command mmgetstate as root.

Unfortunately, we also have to support systems who’s sudo implementation predates this new feature. (cough SLES 10 cough) In order to provide this functionality forward–compatibly, I wrote a Python script that inlines the contents of files as indicated by an #includedir directive that would otherwise be ignored as a comment in older versions of sudo.

#!/usr/bin/env python


import sys
import re
import glob
import os
import fileinput


include_directive = re.compile(r'^[ \t]*#includedir[ \t]+(.*)$')


def main ():
    for line in fileinput.input():
         match = include_directive.match(line)
        if match:
            directory = match.group(1)
            sys.stdout.write(inlined_content(directory))
        else:
            sys.stdout.write(line)


def inlined_content (directory):
    files = get_files(directory)
    return ''.join(read_all(files))


def get_files (directory):
    return [f for f in glob.glob(os.path.join(directory, '*'))
            if os.path.isfile(f)]


def read_all (files):
    for file_ in files:
        try:
            yield open(file_).read()
        except IOError:
            yield ''


if __name__ == '__main__':
    main()