def cmd_listen(workingdir, cert_path): #just load up the password for later read_private() serveraddr = ('', common.CRL_PORT) server = ThreadedCRLServer(serveraddr, CRLHandler) if os.path.exists('%s/cacrl.der' % workingdir): with open('%s/cacrl.der' % workingdir, 'r') as f: server.setcrl(f.read()) t = threading.Thread(target=server.serve_forever) logger.info("Hosting CRL on %s:%d" % (socket.getfqdn(), common.CRL_PORT)) t.start() def revoke_callback(revocation): serial = revocation.get("metadata", {}).get("cert_serial", None) if revocation.get('type', None) != 'revocation' or serial is None: logger.error("Unsupported revocation message: %s" % revocation) return logger.info("Revoking certificate: %s" % serial) server.setcrl(cmd_revoke(workingdir, None, serial)) try: while True: try: revocation_notifier.await_notifications( revoke_callback, revocation_cert_path=cert_path) except Exception as e: logger.exception(e) logger.warn( "No connection to revocation server, retrying in 10s...") time.sleep(10) except KeyboardInterrupt: logger.info("TERM Signal received, shutting down...") server.shutdown()
def main(argv=sys.argv): if os.getuid()!=0 and common.REQUIRE_ROOT: logger.critical("This process must be run as root.") return # get params for initialization registrar_ip = config.get('general', 'registrar_ip') registrar_port = config.get('general', 'registrar_port') # initialize the tmpfs partition to store keys if it isn't already available secdir = secure_mount.mount() # change dir to working dir common.ch_dir(common.WORK_DIR,logger) #initialize tpm (ek,ekcert,aik,ek_tpm,aik_name) = tpm.tpm_init(self_activate=False,config_pw=config.get('cloud_agent','tpm_ownerpassword')) # this tells initialize not to self activate the AIK virtual_agent = tpm.is_vtpm() # try to get some TPM randomness into the system entropy pool tpm.init_system_rand() if ekcert is None: if virtual_agent: ekcert = 'virtual' elif tpm.is_emulator(): ekcert = 'emulator' # now we need the UUID try: agent_uuid = config.get('cloud_agent','agent_uuid') except ConfigParser.NoOptionError: agent_uuid = None if agent_uuid == 'openstack': agent_uuid = openstack.get_openstack_uuid() elif agent_uuid == 'hash_ek': agent_uuid = hashlib.sha256(ek).hexdigest() elif agent_uuid == 'generate' or agent_uuid is None: agent_uuid = str(uuid.uuid4()) if common.DEVELOP_IN_ECLIPSE: agent_uuid = "C432FBB3-D2F1-4A97-9EF7-75BD81C866E9" if common.STUB_VTPM and common.TPM_CANNED_VALUES is not None: # Use canned values for stubbing jsonIn = common.TPM_CANNED_VALUES if "add_vtpm_to_group" in jsonIn: # The value we're looking for has been canned! agent_uuid = jsonIn['add_vtpm_to_group']['retout'] else: # Our command hasn't been canned! raise Exception("Command %s not found in canned JSON!"%("add_vtpm_to_group")) logger.info("Agent UUID: %s"%agent_uuid) # register it and get back a blob keyblob = registrar_client.doRegisterAgent(registrar_ip,registrar_port,agent_uuid,tpm_version,ek,ekcert,aik,ek_tpm,aik_name) if keyblob is None: raise Exception("Registration failed") # get the ephemeral registrar key key = tpm.activate_identity(keyblob) # tell the registrar server we know the key retval=False if virtual_agent: deepquote = tpm.create_deep_quote(hashlib.sha1(key).hexdigest(),agent_uuid+aik+ek) retval = registrar_client.doActivateVirtualAgent(registrar_ip, registrar_port, agent_uuid, deepquote) else: retval = registrar_client.doActivateAgent(registrar_ip,registrar_port,agent_uuid,key) if not retval: raise Exception("Registration failed on activate") serveraddr = ('', config.getint('general', 'cloudagent_port')) server = CloudAgentHTTPServer(serveraddr,Handler,agent_uuid) serverthread = threading.Thread(target=server.serve_forever) logger.info( 'Starting Cloud Agent on port %s use <Ctrl-C> to stop'%serveraddr[1]) serverthread.start() # want to listen for revocations? if config.getboolean('cloud_agent','listen_notfications'): cert_path = config.get('cloud_agent','revocation_cert') if cert_path == "default": cert_path = '%s/unzipped/RevocationNotifier-cert.crt'%(secdir) elif cert_path[0]!='/': # if it is a relative, convert to absolute in work_dir cert_path = os.path.abspath('%s/%s'%(common.WORK_DIR,cert_path)) def perform_actions(revocation): actionlist = [] # load the actions from inside the keylime module actionlisttxt = config.get('cloud_agent','revocation_actions') if actionlisttxt.strip() != "": actionlist = actionlisttxt.split(',') actionlist = ["revocation_actions.%s"%i for i in actionlist] # load actions from unzipped if os.path.exists("%s/unzipped/action_list"%secdir): with open("%s/unzipped/action_list"%secdir,'r') as f: actionlisttxt = f.read() if actionlisttxt.strip()!="": localactions = actionlisttxt.strip().split(',') for action in localactions: if not action.startswith('local_action_'): logger.warning("invalid local action: %s. must start with local_action_"%action) else: actionlist.append(action) uzpath = "%s/unzipped"%secdir if uzpath not in sys.path: sys.path.append(uzpath) for action in actionlist: logger.debug("executing revocation action %s"%action) try: module = importlib.import_module(action) execute = getattr(module,'execute') execute(revocation) except Exception as e: logger.warn("Exception during execution of revocation action %s: %s"%(action,e)) try: while True: try: revocation_notifier.await_notifications(perform_actions,revocation_cert_path=cert_path) except Exception as e: logger.exception(e) logger.warn("No connection to revocation server, retrying in 10s...") time.sleep(10) except KeyboardInterrupt: logger.info("TERM Signal received, shutting down...") tpm.flush_keys() server.shutdown() else: try: while True: time.sleep(1) except KeyboardInterrupt: logger.info("TERM Signal received, shutting down...") tpm.flush_keys() server.shutdown()
def cmd_listen(workingdir,cert_path): #just load up the password for later read_private() serveraddr = ('', common.CRL_PORT) server = ThreadedCRLServer(serveraddr,CRLHandler) if os.path.exists('%s/cacrl.der'%workingdir): logger.info("Loading existing crl: %s/cacrl.der"%workingdir) with open('%s/cacrl.der'%workingdir,'r') as f: server.setcrl(f.read()) t = threading.Thread(target=server.serve_forever) logger.info("Hosting CRL on %s:%d"%(socket.getfqdn(),common.CRL_PORT)) t.start() def check_expiration(): logger.info("checking CRL for expiration every hour") while True: try: if os.path.exists('%s/cacrl.der'%workingdir): retout = cmd_exec.run("openssl crl -inform der -in %s/cacrl.der -text -noout"%workingdir,lock=False)['retout'] for line in retout: line = line.strip() if line.startswith("Next Update:"): expire = datetime.datetime.strptime(line[13:],"%b %d %H:%M:%S %Y %Z") # check expiration within 6 hours in1hour = datetime.datetime.utcnow()+datetime.timedelta(hours=6) if expire<=in1hour: logger.info("Certificate to expire soon %s, re-issuing"%expire) cmd_regencrl(workingdir) # check a little less than every hour time.sleep(3540) except KeyboardInterrupt: logger.info("TERM Signal received, shutting down...") #server.shutdown() break t2 = threading.Thread(target=check_expiration) t2.setDaemon(True) t2.start() def revoke_callback(revocation): serial = revocation.get("metadata",{}).get("cert_serial",None) if revocation.get('type',None) != 'revocation' or serial is None: logger.error("Unsupported revocation message: %s"%revocation) return logger.info("Revoking certificate: %s"%serial) server.setcrl(cmd_revoke(workingdir, None, serial)) try: while True: try: revocation_notifier.await_notifications(revoke_callback,revocation_cert_path=cert_path) except Exception as e: logger.exception(e) logger.warn("No connection to revocation server, retrying in 10s...") time.sleep(10) except KeyboardInterrupt: logger.info("TERM Signal received, shutting down...") server.shutdown() sys.exit()