summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-09-24 14:34:07 -0400
committerMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-09-24 14:34:07 -0400
commit731190a1b414e3d5b31e6de5c80772d6f532f658 (patch)
treec24dd150598cc5e38cc41a77d0e42323fa4459dc
parent9fa149f6e2a5a0d3233644298a5d50db3f8b6748 (diff)
parent8454fe3216f935746fad17a8c48f4df0e40a0d0d (diff)
downloadthird_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.conf4
-rwxr-xr-xcerts/certmaster.py171
-rwxr-xr-xmodules/func_module.py23
-rwxr-xr-xmodules/test.py3
-rwxr-xr-xserver/module_loader.py3
-rwxr-xr-xserver/server.py11
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: