diff options
author | Seth Vidal <skvidal@fedoraproject.org> | 2007-10-08 14:59:28 -0400 |
---|---|---|
committer | Seth Vidal <skvidal@fedoraproject.org> | 2007-10-08 14:59:28 -0400 |
commit | 9033fe7cc3c6a59bd90c4742a47536699dee612d (patch) | |
tree | 7464fb9f366e121d86947f2f900755d681612e14 | |
parent | ce379bdb3d6ade0a6326d5d7cf9446389cf4d94b (diff) | |
download | func-9033fe7cc3c6a59bd90c4742a47536699dee612d.tar.gz func-9033fe7cc3c6a59bd90c4742a47536699dee612d.tar.xz func-9033fe7cc3c6a59bd90c4742a47536699dee612d.zip |
fine-grained acls per minion
- adds minion-acl.conf
-rw-r--r-- | etc/minion-acl.conf | 5 | ||||
-rw-r--r-- | etc/minion.conf | 2 | ||||
-rw-r--r-- | func/commonconfig.py | 2 | ||||
-rwxr-xr-x | func/minion/server.py | 32 | ||||
-rwxr-xr-x | func/minion/utils.py | 37 |
5 files changed, 66 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/server.py b/func/minion/server.py index 39a78cb..921aa03 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 @@ -213,18 +214,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 + + + + + |