diff options
-rw-r--r-- | etc/minion-acl.conf | 5 | ||||
-rw-r--r-- | etc/minion.conf | 2 | ||||
-rw-r--r-- | func/commonconfig.py | 2 | ||||
-rw-r--r-- | func/minion/modules/nagios-check.py | 42 | ||||
-rwxr-xr-x | func/minion/server.py | 32 | ||||
-rwxr-xr-x | func/minion/utils.py | 37 |
6 files changed, 108 insertions, 12 deletions
diff --git a/etc/minion-acl.conf b/etc/minion-acl.conf new file mode 100644 index 0000000..1a093a8 --- /dev/null +++ b/etc/minion-acl.conf @@ -0,0 +1,5 @@ +#config file for minion Access control lists +#this specifies which methods a connecting client is allowed to run +# format is: cn-certificate-hash = method1, method2, method3 +# default allows the certmaster key to run all methods + diff --git a/etc/minion.conf b/etc/minion.conf index 9e18eac..dc4c0a1 100644 --- a/etc/minion.conf +++ b/etc/minion.conf @@ -4,4 +4,4 @@ log_level = DEBUG certmaster = certmaster cert_dir = /etc/pki/func - +acl_config = /etc/func/minion-acl.conf diff --git a/func/commonconfig.py b/func/commonconfig.py index cbf031e..e3b1760 100644 --- a/func/commonconfig.py +++ b/func/commonconfig.py @@ -13,3 +13,5 @@ class FuncdConfig(BaseConfig): log_level = Option('INFO') certmaster = Option('certmaster') cert_dir = Option('/etc/pki/func') + acl_config = Option('/etc/func/minion-acl.conf') + diff --git a/func/minion/modules/nagios-check.py b/func/minion/modules/nagios-check.py new file mode 100644 index 0000000..57c1df7 --- /dev/null +++ b/func/minion/modules/nagios-check.py @@ -0,0 +1,42 @@ +# Copyright 2007, Red Hat, Inc +# James Bowes <jbowes@redhat.com> +# Seth Vidal modified command.py to be nagios-check.py +# +# This software may be freely redistributed under the terms of the GNU +# general public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +""" +Abitrary command execution module for func. +""" + +from modules import func_module + +import sub_process + +class Nagios(func_module.FuncModule): + + def __init__(self): + self.methods = { + "run" : self.run + } + func_module.FuncModule.__init__(self) + + def run(self, check_name): + """ + Runs a nagios check returning the return code, stdout, and stderr as a tuple. + """ + nagios_path='/usr/lib/nagios/plugins' + command = '%s/%s' % (nagios_path, check_name) + + cmdref = sub_process.Popen(command.split(),stdout=sub_process.PIPE,stderr=sub_process.PIPE, shell=False) + data = cmdref.communicate() + return (cmdref.returncode, data[0], data[1]) + +methods = Nagios() +register_rpc = methods.register_rpc + + diff --git a/func/minion/server.py b/func/minion/server.py index 253c06a..c900a09 100755 --- a/func/minion/server.py +++ b/func/minion/server.py @@ -20,6 +20,7 @@ import string import sys import traceback import socket +import fnmatch from gettext import textdomain I18N_DOMAIN = "func" @@ -51,7 +52,7 @@ class XmlRpcInterface(object): self.logger = logger.Logger().logger self.audit_logger = logger.AuditLogger() self.__setup_handlers() - + # need a reference so we can log ip's, certs, etc # self.server = server @@ -217,18 +218,27 @@ class FuncSSLXMLRPCServer(AuthedXMLRPCServer.AuthedSSLXMLRPCServer, return peer_cert.get_subject().CN def _check_acl(self, cert, ip, method, params): - cn = cert.get_subject().CN - sub_hash = cert.subject_name_hash() - # FIXME - make this be more useful, obviously :) - # until we figure out the right config - just say - if the cert - # is not the cert of our ca (which is where overlord/func/certmaster - # runs then return False + acls = utils.get_acls_from_config(fn=self.config.acl_config) + # certmaster always gets to run things ca_cn = self._our_ca.get_subject().CN ca_hash = self._our_ca.subject_name_hash() - if cn == ca_cn and sub_hash == ca_hash: - return True - - # clearly other method/param checks here + ca_key = '%s-%s' % (ca_cn, ca_hash) + acls[ca_key] = ['*'] + + cn = cert.get_subject().CN + sub_hash = cert.subject_name_hash() + if acls: + allow_list = [] + hostkey = '%s-%s' % (cn, sub_hash) + # search all the keys, match to 'cn-subhash' + for hostmatch in acls.keys(): + if fnmatch.fnmatch(hostkey, hostmatch): + allow_list.extend(acls[hostmatch]) + # go through the allow_list and make sure this method is in there + for methodmatch in allow_list: + if fnmatch.fnmatch(method, methodmatch): + return True + return False def main(argv): diff --git a/func/minion/utils.py b/func/minion/utils.py index d13808e..447acc8 100755 --- a/func/minion/utils.py +++ b/func/minion/utils.py @@ -157,3 +157,40 @@ def daemonize(pidfile=None): if pidfile is not None: open(pidfile, "w").write(str(pid)) sys.exit(0) + +def get_acls_from_config(fn='/etc/func/minion-acl.conf'): + """ + takes a fn = filename of config file + returns a dict of hostname+hash = [methods, to, run] + + """ + + acls = {} + if not os.path.exists(fn): + print 'acl config file does not exist: %s' % fn + return acls + try: + fo = open(fn, 'r') + except (IOError, OSError), e: + print 'cannot open acl config file: %s' % e + return acls + + for line in fo.readlines(): + if line.startswith('#'): continue + if line.strip() == '': continue + line = line.replace('\n', '') + (host, methods) = line.split('=') + host = host.strip().lower() + methods = methods.strip() + methods = methods.replace(',',' ') + methods = methods.split() + if not acls.has_key(host): + acls[host] = [] + acls[host].extend(methods) + + return acls + + + + + |