X-Git-Url: https://pwan.org/git/?a=blobdiff_plain;f=certmaster%2Futils.py;h=76d5b4d579b64ca0d647aa37f6e7481d57f8bfdc;hb=919c9c3a4f5418b55108c1ec903160f0400900df;hp=3dec6a54a283fc699d466da2723100137c297449;hpb=613a485c4798b38a65042e9d78968896c590fdd0;p=certmaster.git diff --git a/certmaster/utils.py b/certmaster/utils.py old mode 100755 new mode 100644 index 3dec6a5..76d5b4d --- a/certmaster/utils.py +++ b/certmaster/utils.py @@ -24,6 +24,7 @@ import certs from config import read_config from commonconfig import MinionConfig import logger +import sub_process # FIXME: module needs better pydoc @@ -31,6 +32,14 @@ import logger # FIXME: can remove this constant? REMOTE_ERROR = "REMOTE_ERROR" +# The standard I/O file descriptors are redirected to /dev/null by default. +if (hasattr(os, "devnull")): + REDIRECT_TO = os.devnull +else: + REDIRECT_TO = "/dev/null" + + + def trace_me(): x = traceback.extract_stack() @@ -43,25 +52,40 @@ def daemonize(pidfile=None): Writes the new PID to the provided file name if not None. """ - print pidfile pid = os.fork() if pid > 0: sys.exit(0) + os.chdir("/") os.setsid() os.umask(0) pid = os.fork() + os.close(0) + os.close(1) + os.close(2) + + # based on http://code.activestate.com/recipes/278731/ + os.open(REDIRECT_TO, os.O_RDWR) # standard input (0) + + os.dup2(0, 1) # standard output (1) + os.dup2(0, 2) # standard error (2) + + + if pid > 0: if pidfile is not None: open(pidfile, "w").write(str(pid)) sys.exit(0) + def nice_exception(etype, evalue, etb): - # FIXME: I believe we can remove this function etype = str(etype) - lefti = etype.index("'") + 1 - righti = etype.rindex("'") - nicetype = etype[lefti:righti] + try: + lefti = etype.index("'") + 1 + righti = etype.rindex("'") + nicetype = etype[lefti:righti] + except: + nicetype = etype nicestack = string.join(traceback.format_list(traceback.extract_tb(etb))) return [ REMOTE_ERROR, nicetype, str(evalue), nicestack ] @@ -83,10 +107,10 @@ def get_hostname(talk_to_certmaster=True): up the hostname for that. """ # FIXME: this code ignores http proxies (which granted, we don't - # support elsewhere either. It also hardcodes the port number - # for the certmaster for now + # support elsewhere either. hostname = None hostname = socket.gethostname() + # print "DEBUG: HOSTNAME TRY1: %s" % hostname try: ip = socket.gethostbyname(hostname) except: @@ -94,37 +118,19 @@ def get_hostname(talk_to_certmaster=True): if ip != "127.0.0.1": return hostname - if talk_to_certmaster: - config_file = '/etc/certmaster/minion.conf' - config = read_config(config_file, MinionConfig) - - server = config.certmaster - port = 51235 - - try: - s = socket.socket() - s.settimeout(5) - s.connect((server, port)) - (intf, port) = s.getsockname() - hostname = socket.gethostbyaddr(intf)[0] - s.close() - except: - s.close() - raise - - return hostname - +# FIXME: move to requestor module and also create a verbose mode +# prints to the screen for usage by /usr/bin/certmaster-request def create_minion_keys(): # FIXME: paths should not be hard coded here, move to settings universally config_file = '/etc/certmaster/minion.conf' config = read_config(config_file, MinionConfig) cert_dir = config.cert_dir - master_uri = 'http://%s:51235/' % config.certmaster - print "DEBUG: acquiring hostname" + master_uri = 'http://%s:%s/' % (config.certmaster, config.certmaster_port) + # print "DEBUG: acquiring hostname" hn = get_hostname() - print "DEBUG: hostname = %s\n" % hn + # print "DEBUG: hostname = %s\n" % hn if hn is None: raise codes.CMException("Could not determine a hostname other than localhost") @@ -136,7 +142,7 @@ def create_minion_keys(): if os.path.exists(cert_file) and os.path.exists(ca_cert_file): - print "DEBUG: err, no cert_file" + # print "DEBUG: err, no cert_file" return keypair = None @@ -151,28 +157,28 @@ def create_minion_keys(): csr = certs.make_csr(keypair, dest=csr_file) except Exception, e: traceback.print_exc() - raise codes.FuncException, "Could not create local keypair or csr for session" + raise codes.CMException, "Could not create local keypair or csr for session" result = False log = logger.Logger().logger while not result: try: - print "DEBUG: submitting CSR to certmaster: %s" % master_uri + # print "DEBUG: submitting CSR to certmaster: %s" % master_uri log.debug("submitting CSR to certmaster %s" % master_uri) result, cert_string, ca_cert_string = submit_csr_to_master(csr_file, master_uri) except socket.gaierror, e: - raise codes.FuncException, "Could not locate certmaster at %s" % master_uri + raise codes.CMException, "Could not locate certmaster at %s" % master_uri # logging here would be nice if not result: - print "DEBUG: no response from certmaster, sleeping 10 seconds" + # print "DEBUG: no response from certmaster, sleeping 10 seconds" log.warning("no response from certmaster %s, sleeping 10 seconds" % master_uri) time.sleep(10) if result: - print "DEBUG: recieved certificate from certmaster" - log.debug("received certificate from certmaster %s, storing" % master_uri) + # print "DEBUG: recieved certificate from certmaster" + log.debug("received certificate from certmaster %s, storing to %s" % (master_uri, cert_file)) cert_fd = os.open(cert_file, os.O_RDWR|os.O_CREAT, 0644) os.write(cert_fd, cert_string) os.close(cert_fd) @@ -181,6 +187,37 @@ def create_minion_keys(): os.write(ca_cert_fd, ca_cert_string) os.close(ca_cert_fd) +def run_triggers(ref, globber): + """ + Runs all the trigger scripts in a given directory. + ref can be a certmaster object, if not None, the name will be passed + to the script. If ref is None, the script will be called with + no argumenets. Globber is a wildcard expression indicating which + triggers to run. Example: "/var/lib/certmaster/triggers/blah/*" + """ + + log = logger.Logger().logger + triggers = glob.glob(globber) + triggers.sort() + for file in triggers: + log.debug("Executing trigger: %s" % file) + try: + if file.find(".rpm") != -1: + # skip .rpmnew files that may have been installed + # in the triggers directory + continue + if ref: + rc = sub_process.call([file, ref], shell=False) + else: + rc = sub_process.call([file], shell=False) + except: + log.warning("Warning: failed to execute trigger: %s" % file) + continue + + if rc != 0: + raise codes.CMException, "certmaster trigger failed: %(file)s returns %(code)d" % { "file" : file, "code" : rc } + + def submit_csr_to_master(csr_file, master_uri): """" gets us our cert back from the certmaster.wait_for_cert() method @@ -192,6 +229,6 @@ def submit_csr_to_master(csr_file, master_uri): csr = fo.read() s = xmlrpclib.ServerProxy(master_uri) - print "DEBUG: waiting for cert" + # print "DEBUG: waiting for cert" return s.wait_for_cert(csr)