diff options
author | Michael DeHaan <mdehaan@mdehaan.rdu.redhat.com> | 2007-09-24 14:34:07 -0400 |
---|---|---|
committer | Michael DeHaan <mdehaan@mdehaan.rdu.redhat.com> | 2007-09-24 14:34:07 -0400 |
commit | 731190a1b414e3d5b31e6de5c80772d6f532f658 (patch) | |
tree | c24dd150598cc5e38cc41a77d0e42323fa4459dc | |
parent | 9fa149f6e2a5a0d3233644298a5d50db3f8b6748 (diff) | |
parent | 8454fe3216f935746fad17a8c48f4df0e40a0d0d (diff) | |
download | third_party-func-731190a1b414e3d5b31e6de5c80772d6f532f658.tar.gz third_party-func-731190a1b414e3d5b31e6de5c80772d6f532f658.tar.xz third_party-func-731190a1b414e3d5b31e6de5c80772d6f532f658.zip |
Merge branch 'master' of ssh://git.fedoraproject.org/git/hosted/func
-rw-r--r-- | certs/certmaster.conf | 4 | ||||
-rwxr-xr-x | certs/certmaster.py | 171 | ||||
-rwxr-xr-x | modules/func_module.py | 23 | ||||
-rwxr-xr-x | modules/test.py | 3 | ||||
-rwxr-xr-x | server/module_loader.py | 3 | ||||
-rwxr-xr-x | server/server.py | 11 |
6 files changed, 212 insertions, 3 deletions
diff --git a/certs/certmaster.conf b/certs/certmaster.conf new file mode 100644 index 0000000..6e424d1 --- /dev/null +++ b/certs/certmaster.conf @@ -0,0 +1,4 @@ +listen_addr = localhost +listen_port = 51235 +cadir = /etc/pki/func/ca +autosign = yes diff --git a/certs/certmaster.py b/certs/certmaster.py new file mode 100755 index 0000000..2fbfb57 --- /dev/null +++ b/certs/certmaster.py @@ -0,0 +1,171 @@ +#!/usr/bin/python + +""" +cert master listener + +Copyright 2007, Red Hat, Inc +see AUTHORS + +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. +""" + +# standard modules +import SimpleXMLRPCServer +import string +import socket +import sys +import os +import os.path +import traceback +from OpenSSL import crypto +import sha + +#from func.server import codes +import func +import func.certs + + +class SimpleConfigFile(object): + """simple config file object: + reads in key=value pairs from a file and stores each as an attribute""" + + def __init__(self, filename): + self.fn = filename + fo = open(filename, 'r') + for line in fo.readlines(): + if line.startswith('#'): continue + if line.strip() == '': continue + (key, val) = line.split('=') + key = key.strip().lower() + val = val.strip() + setattr(self, key, val) + fo.close() + + +class CertMaster(object): + def __init__(self, conf_file): + self.cfg = SimpleConfigFile(conf_file) + self.listen_addr = 'localhost' + self.listen_port = '51235' + self.cadir = '/etc/pki/func/ca' + self.certroot = '/etc/pki/func/ca/certs' + self.csrroot = '/etc/pki/func/ca/csrs' + self.autosign = True + for attr in ['listen_addr', 'listen_port', 'cadir', 'certroot', + 'csrroot']: + if hasattr(self.cfg, attr): + setattr(self, attr, getattr(self.cfg, attr)) + if hasattr(self.cfg, 'autosign'): + if getattr(self.cfg, 'autosign').lower() in ['yes', 'true', 1, 'on']: + self.autosign = True + elif getattr(self.cfg, 'autosign').lower() in ['no', 'false', 0, 'off']: + self.autosign = False + # open up the cakey and cacert so we have them available + ca_key_file = '%s/funcmaster.key' % self.cadir + ca_cert_file = '%s/funcmaster.crt' % self.cadir + self.cakey = func.certs.retrieve_key_from_file(ca_key_file) + self.cacert = func.certs.retrieve_cert_from_file(ca_cert_file) + + for dirpath in [self.cadir, self.certroot, self.csrroot]: + if not os.path.exists(dirpath): + os.makedirs(dirpath) + + # setup handlers + self.handlers = { + 'wait_for_cert': self.wait_for_cert, + } + + def _dispatch(self, method, params): + if method == 'trait_names' or method == '_getAttributeNames': + return self.handlers.keys() + + if method in self.handlers.keys(): + return self.handlers[method](*params) + else: + pass + #raise codes.InvalidMethodException + + + def wait_for_cert(self, csrbuf): + """ + takes csr as a string + returns True, caller_cert, ca_cert + returns False, '', '' + """ + + try: + csrreq = crypto.load_certificate_request(crypto.FILETYPE_PEM, csrbuf) + except crypto.Error, e: + #XXX need to raise a fault here and document it - but false is just as good + return False, '', '' + + requesting_host = csrreq.get_subject().CN + certfile = '%s/%s.pem' % (self.certroot, requesting_host) + csrfile = '%s/%s.csr' % (self.csrroot, requesting_host) + + # check for old csr on disk + # if we have it - compare the two - if they are not the same - raise a fault + if os.path.exists(csrfile): + oldfo = open(csrfile) + oldcsrbuf = oldfo.read() + oldsha = sha.new() + oldsha.update(oldcsrbuf) + olddig = oldsha.hexdigest() + newsha = sha.new() + newsha.update(csrbuf) + newdig = newsha.hexdigest() + if not newdig == olddig: + # XXX raise a proper fault + return False, '', '' + + # look for a cert: + # if we have it, then return True, etc, etc + if os.path.exists(certfile): + slavecert = crypto.load_certificate(crypto.FILETYPE_PEM, certfile) + + cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert) + cacert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cacert) + return True, cert_buf, cacert_buf + + # if we don't have a cert then: + # if we're autosign then sign it, write out the cert and return True, etc, etc + # else write out the csr + + if self.autosign: + slavecert = func.certs.create_slave_certificate(csrreq, + self.cakey, self.cacert, self.cadir) + + destfo = open(certfile, 'w') + destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert)) + destfo.close() + del destfo + cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert) + cacert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cacert) + return True, cert_buf, cacert_buf + + else: + # write the csr out to a file to be dealt with by the admin + destfo = open(csrfile, 'w') + destfo.write(crypto.dump_certificate_request(crypto.FILETYPE_PEM, csrreq)) + destfo.close() + del destfo + return False, '', '' + + return False, '', '' + + + + + +cm = CertMaster('/etc/func/certmaster.conf') +server = SimpleXMLRPCServer.SimpleXMLRPCServer((cm.cfg.listen_addr, int(cm.cfg.listen_port))) +server.logRequests = 0 +server.register_instance(cm) +server.serve_forever() + + diff --git a/modules/func_module.py b/modules/func_module.py index 4bb06d2..7019bc5 100755 --- a/modules/func_module.py +++ b/modules/func_module.py @@ -24,20 +24,41 @@ import traceback class FuncModule(object): + version = "0.0.0" + api_version = "0.0.0" + description = "No Description provided" + def __init__(self): config_obj = config_data.Config() config_result = config_obj.get() self.config = config_result self.__init_log() + self.__base_methods = { + # __'s so we don't clobber useful names + "module_version" : self.__module_version, + "module_api_version" : self.__module_api_version, + "module_description" : self.__module_description, + } def __init_log(self): log = logger.Logger() self.logger = log.logger def register_rpc(self, handlers, module_name): + # add the internal methods, note that this means they + # can get clobbbered by subclass versions + for meth in self.__base_methods: + handlers["%s.%s" % (module_name, meth)] = self.__base_methods[meth] for meth in self.methods: handlers["%s.%s" % (module_name,meth)] = self.methods[meth] - + def __module_version(self): + return self.version + + def __module_api_version(self): + return self.api_version + + def __module_description(self): + return self.description diff --git a/modules/test.py b/modules/test.py index 31f1e94..ea22007 100755 --- a/modules/test.py +++ b/modules/test.py @@ -4,6 +4,9 @@ from codes import * from modules import func_module class Test(func_module.FuncModule): + version = "11.11.11" + api_version = "0.0.1" + description = "Just a very simple example module" def __init__(self): self.methods = { "add": self.add diff --git a/server/module_loader.py b/server/module_loader.py index 2b20429..a2a00c5 100755 --- a/server/module_loader.py +++ b/server/module_loader.py @@ -75,9 +75,8 @@ def load_modules(blacklist=None): continue mods[mod_imp_name] = blip except ImportError, e: - # shouldn't this be fatal? + # A module that raises an ImportError is (for now) simply not loaded. print e - raise return mods diff --git a/server/server.py b/server/server.py index 4e320e9..bfdf5a9 100755 --- a/server/server.py +++ b/server/server.py @@ -62,6 +62,17 @@ class XmlRpcInterface(object): self.logger.warning("module %s not loaded, missing register_rpc method" % self.modules[x]) + # internal methods that we do instead of spreading internal goo + # all over the modules. For now, at lest -akl + + self.handlers["system.listMethods"] = self.list_methods + + + def list_methods(self): + return self.handlers.keys() + + + def get_dispatch_method(self, method): if method in self.handlers: |