diff options
Diffstat (limited to 'certmaster/minion/server.py')
-rwxr-xr-x | certmaster/minion/server.py | 285 |
1 files changed, 0 insertions, 285 deletions
diff --git a/certmaster/minion/server.py b/certmaster/minion/server.py deleted file mode 100755 index f1b827f..0000000 --- a/certmaster/minion/server.py +++ /dev/null @@ -1,285 +0,0 @@ -""" -func - -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 sys -import traceback -import socket -import fnmatch - -from gettext import textdomain -I18N_DOMAIN = "func" - - -from func.config import read_config -from func.commonconfig import FuncdConfig -from func import logger -from func import certs -import func.jobthing as jobthing -import utils - -# our modules -import AuthedXMLRPCServer -import codes -import module_loader -import func.utils as futils - - - -class XmlRpcInterface(object): - - def __init__(self): - - """ - Constructor. - """ - - config_file = '/etc/func/minion.conf' - self.config = read_config(config_file, FuncdConfig) - 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 - - def __setup_handlers(self): - - """ - Add RPC functions from each class to the global list so they can be called. - """ - - self.handlers = {} - for x in self.modules.keys(): - try: - self.modules[x].register_rpc(self.handlers, x) - self.logger.debug("adding %s" % x) - except AttributeError, e: - 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 - - - # system.listMethods os a quasi stanard xmlrpc method, so - # thats why it has a odd looking name - self.handlers["system.listMethods"] = self.list_methods - self.handlers["system.list_methods"] = self.list_methods - self.handlers["system.list_modules"] = self.list_modules - - def list_modules(self): - modules = self.modules.keys() - modules.sort() - return modules - - def list_methods(self): - methods = self.handlers.keys() - methods.sort() - return methods - - def get_dispatch_method(self, method): - - if method in self.handlers: - return FuncApiMethod(self.logger, method, self.handlers[method]) - - else: - self.logger.info("Unhandled method call for method: %s " % method) - raise codes.InvalidMethodException - - -class FuncApiMethod: - - """ - Used to hold a reference to all of the registered functions. - """ - - def __init__(self, logger, name, method): - - self.logger = logger - self.__method = method - self.__name = name - - def __log_exc(self): - - """ - Log an exception. - """ - - (t, v, tb) = sys.exc_info() - self.logger.info("Exception occured: %s" % t ) - self.logger.info("Exception value: %s" % v) - self.logger.info("Exception Info:\n%s" % string.join(traceback.format_list(traceback.extract_tb(tb)))) - - def __call__(self, *args): - - self.logger.debug("(X) -------------------------------------------") - - try: - rc = self.__method(*args) - except codes.FuncException, e: - self.__log_exc() - (t, v, tb) = sys.exc_info() - rc = futils.nice_exception(t,v,tb) - except: - self.__log_exc() - (t, v, tb) = sys.exc_info() - rc = futils.nice_exception(t,v,tb) - self.logger.debug("Return code for %s: %s" % (self.__name, rc)) - - return rc - - -def serve(): - - """ - Code for starting the XMLRPC service. - """ - server =FuncSSLXMLRPCServer(('', 51234)) - server.logRequests = 0 # don't print stuff to console - server.serve_forever() - - - -class FuncXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, XmlRpcInterface): - - def __init__(self, args): - - self.allow_reuse_address = True - - self.modules = module_loader.load_modules() - SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, args) - XmlRpcInterface.__init__(self) - - -class FuncSSLXMLRPCServer(AuthedXMLRPCServer.AuthedSSLXMLRPCServer, - XmlRpcInterface): - def __init__(self, args): - self.allow_reuse_address = True - self.modules = module_loader.load_modules() - - XmlRpcInterface.__init__(self) - hn = utils.get_hostname() - self.key = "%s/%s.pem" % (self.config.cert_dir, hn) - self.cert = "%s/%s.cert" % (self.config.cert_dir, hn) - self.ca = "%s/ca.cert" % self.config.cert_dir - - self._our_ca = certs.retrieve_cert_from_file(self.ca) - - AuthedXMLRPCServer.AuthedSSLXMLRPCServer.__init__(self, ("", 51234), - self.key, self.cert, - self.ca) - - def _dispatch(self, method, params): - - """ - the SimpleXMLRPCServer class will call _dispatch if it doesn't - find a handler method - """ - # take _this_request and hand it off to check out the acls of the method - # being called vs the requesting host - - if not hasattr(self, '_this_request'): - raise codes.InvalidMethodException - - r,a = self._this_request - peer_cert = r.get_peer_certificate() - ip = a[0] - - - # generally calling conventions are: hardware.info - # async convention is async.hardware.info - # here we parse out the async to decide how to invoke it. - # see the async docs on the Wiki for further info. - async_dispatch = False - if method.startswith("async."): - async_dispatch = True - method = method.replace("async.","",1) - - if not self._check_acl(peer_cert, ip, method, params): - raise codes.AccessToMethodDenied - - # Recognize ipython's tab completion calls - if method == 'trait_names' or method == '_getAttributeNames': - return self.handlers.keys() - - cn = peer_cert.get_subject().CN - sub_hash = peer_cert.subject_name_hash() - self.audit_logger.log_call(ip, cn, sub_hash, method, params) - - try: - if not async_dispatch: - return self.get_dispatch_method(method)(*params) - else: - return jobthing.minion_async_run(self.get_dispatch_method, method, params) - except: - (t, v, tb) = sys.exc_info() - rc = futils.nice_exception(t, v, tb) - return rc - - def auth_cb(self, request, client_address): - peer_cert = request.get_peer_certificate() - return peer_cert.get_subject().CN - - def _check_acl(self, cert, ip, method, params): - acls = utils.get_acls_from_config(acldir=self.config.acl_dir) - - # certmaster always gets to run things - ca_cn = self._our_ca.get_subject().CN - ca_hash = self._our_ca.subject_name_hash() - 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): - - """ - Start things up. - """ - - if "daemon" in sys.argv or "--daemon" in sys.argv: - futils.daemonize("/var/run/funcd.pid") - else: - print "serving...\n" - - try: - utils.create_minion_keys() - serve() - except codes.FuncException, e: - print >> sys.stderr, 'error: %s' % e - sys.exit(1) - - -# ====================================================================================== -if __name__ == "__main__": - textdomain(I18N_DOMAIN) - main(sys.argv) |