def cmd_revoke(workingdir,name=None,serial=None): cwd = os.getcwd() try: common.ch_dir(workingdir,os.getuid()==0) priv = read_private() if name is not None and serial is not None: raise Exception("You may not specify a cert and a serial at the same time") if name is None and serial is None: raise Exception("You must specify a cert or a serial to revoke") if name is not None: # load up the cert cert = X509.load_cert("%s-cert.crt"%name) serial = cert.get_serial_number() #convert serial to string serial = str(serial) # get the ca key cert and keys as strings with open('cacert.crt','r') as f: cacert = f.read() ca_pk = str(priv[0]['ca']) if serial not in priv[0]['revoked_keys']: priv[0]['revoked_keys'].append(serial) crl = ca_impl.gencrl(priv[0]['revoked_keys'],cacert,ca_pk) write_private(priv) return crl finally: os.chdir(cwd) return crl
def test_010_reg_instance_post(self): """Test registrar's POST /v2/instances/{UUID} Interface""" global keyblob, aik, vtpm, ek # Change CWD for TPM-related operations cwd = os.getcwdu() common.ch_dir(common.WORK_DIR, None) secdir = secure_mount.mount() # Initialize the TPM with AIK (ek, ekcert, aik) = tpm_initialize.init(self_activate=False, config_pw=config.get( 'cloud_node', 'tpm_ownerpassword')) vtpm = tpm_initialize.is_vtpm() # Seed RNG (root only) if common.REQUIRE_ROOT: tpm_random.init_system_rand() # Handle virtualized and emulated TPMs if ekcert is None: if vtpm: ekcert = 'virtual' elif tpm_initialize.is_emulator(): ekcert = 'emulator' # Get back to our original CWD common.ch_dir(cwd, None) data = { 'ek': ek, 'ekcert': ekcert, 'aik': aik, } v_json_message = json.dumps(data) response = tornado_requests.request( "POST", "http://%s:%s/v2/instances/%s" % (tenant_templ.registrar_ip, tenant_templ.registrar_boot_port, tenant_templ.node_uuid), data=v_json_message, context=None) self.assertEqual(response.status_code, 200, "Non-successful Registrar Instance Add return code!") response_body = response.json() # Ensure response is well-formed self.assertIn("results", response_body, "Malformed response body!") self.assertIn("blob", response_body["results"], "Malformed response body!") keyblob = response_body["results"]["blob"] self.assertIsNotNone(keyblob, "Malformed response body!")
def cmd_certpkg(workingdir,name,needfile=True): cwd = os.getcwd() try: common.ch_dir(workingdir,os.getuid()==0) # zip up the crt, private key, and public key with open('cacert.crt','r') as f: cacert = f.read() with open("%s-public.pem"%name,'rb') as f: pub = f.read() with open("%s-cert.crt"%name,'rb') as f: cert = f.read() priv = read_private() private = priv[0][name] with open("%s-private.pem"%name,'rb') as f: prot_priv = f.read() #code to create a pem formatted protected private key using the keystore password # pk = EVP.load_key_string(str(priv[0][name])) # f = BIO.MemoryBuffer() # # globalcb will return the global password provided by the user # pk.save_key_bio(f, 'aes_256_cbc', globalcb) # prot_priv = f.getvalue() # f.close() # no compression to avoid extraction errors in tmpfs sf = cStringIO.StringIO() with zipfile.ZipFile(sf,'w',compression=zipfile.ZIP_STORED) as f: f.writestr('%s-public.pem'%name,pub) f.writestr('%s-cert.crt'%name,cert) f.writestr('%s-private.pem'%name,private) f.writestr('cacert.crt',cacert) pkg = sf.getvalue() # actually output the package to disk with a protected private key with zipfile.ZipFile('%s-pkg.zip'%name,'w',compression=zipfile.ZIP_STORED) as f: f.writestr('%s-public.pem'%name,pub) f.writestr('%s-cert.crt'%name,cert) f.writestr('%s-private.pem'%name,prot_priv) f.writestr('cacert.crt',cacert) logger.info("Creating cert package for %s in %s-pkg.zip"%(name,name)) return pkg finally: os.chdir(cwd)
def cmd_init(workingdir): cwd = os.getcwd() try: common.ch_dir(workingdir, logger) rmfiles("*.pem") rmfiles("*.crt") rmfiles("*.zip") rmfiles("*.der") rmfiles("private.json") cacert, ca_pk, _ = ca_impl.mk_cacert() priv = read_private() # write out keys with open('cacert.crt', 'wb') as f: f.write(cacert.as_pem()) f = BIO.MemoryBuffer() ca_pk.save_key_bio(f, None) priv[0]['ca'] = f.getvalue() f.close() # store the last serial number created. # the CA is always serial # 1 priv[0]['lastserial'] = 1 write_private(priv) ca_pk.get_rsa().save_pub_key('ca-public.pem') # generate an empty crl crl = ca_impl.gencrl([], cacert.as_pem(), str(priv[0]['ca'])) with open('cacrl.der', 'wb') as f: f.write(crl) convert_crl_to_pem("cacrl.der", "cacrl.pem") # Sanity checks... cac = X509.load_cert('cacert.crt') if cac.verify(): logger.info("CA certificate created successfully in %s" % workingdir) else: logger.error("ERROR: Cert does not self validate") finally: os.chdir(cwd)
def cmd_mkcert(workingdir, name): cwd = os.getcwd() try: common.ch_dir(workingdir, logger) priv = read_private() cacert = X509.load_cert('cacert.crt') ca_pk = EVP.load_key_string(str(priv[0]['ca'])) cert, pk = ca_impl.mk_signed_cert(cacert, ca_pk, name, priv[0]['lastserial'] + 1) with open('%s-cert.crt' % name, 'w') as f: f.write(cert.as_pem()) f = BIO.MemoryBuffer() pk.save_key_bio(f, None) priv[0][name] = f.getvalue() f.close() #increment serial number after successful creation priv[0]['lastserial'] += 1 write_private(priv) # write out the private key with password with os.fdopen( os.open("%s-private.pem" % name, os.O_WRONLY | os.O_CREAT, 0600), 'w') as f: biofile = BIO.File(f) pk.save_key_bio(biofile, 'aes_256_cbc', globalcb) biofile.close() pk.get_rsa().save_pub_key('%s-public.pem' % name) cc = X509.load_cert('%s-cert.crt' % name) if cc.verify(cacert.get_pubkey()): logger.info("Created certificate for name %s successfully in %s" % (name, workingdir)) else: logger.error("ERROR: Cert does not validate against CA")
def cmd_regencrl(workingdir): cwd = os.getcwd() try: common.ch_dir(workingdir,logger) priv = read_private() # get the ca key cert and keys as strings with open('cacert.crt','r') as f: cacert = f.read() ca_pk = str(priv[0]['ca']) crl = ca_impl.gencrl(priv[0]['revoked_keys'],cacert,ca_pk) write_private(priv) # write out the CRL to the disk with open('cacrl.der','wb') as f: f.write(crl) convert_crl_to_pem("cacrl.der","cacrl.pem") finally: os.chdir(cwd) return crl
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_certpkg(workingdir,name,insecure=False): cwd = os.getcwd() try: common.ch_dir(workingdir,logger) # zip up the crt, private key, and public key with open('cacert.crt','r') as f: cacert = f.read() with open("%s-public.pem"%name,'rb') as f: pub = f.read() with open("%s-cert.crt"%name,'rb') as f: cert = f.read() with open('cacrl.der','r') as f: crl = f.read() with open('cacrl.pem','r') as f: crlpem = f.read() cert_obj = X509.load_cert_string(cert) serial = cert_obj.get_serial_number() subject = str(cert_obj.get_subject()) priv = read_private() private = priv[0][name] with open("%s-private.pem"%name,'rb') as f: prot_priv = f.read() #code to create a pem formatted protected private key using the keystore password # pk = EVP.load_key_string(str(priv[0][name])) # f = BIO.MemoryBuffer() # # globalcb will return the global password provided by the user # pk.save_key_bio(f, 'aes_256_cbc', globalcb) # prot_priv = f.getvalue() # f.close() # no compression to avoid extraction errors in tmpfs sf = cStringIO.StringIO() with zipfile.ZipFile(sf,'w',compression=zipfile.ZIP_STORED) as f: f.writestr('%s-public.pem'%name,pub) f.writestr('%s-cert.crt'%name,cert) f.writestr('%s-private.pem'%name,private) f.writestr('cacert.crt',cacert) f.writestr('cacrl.der',crl) f.writestr('cacrl.pem',crlpem) pkg = sf.getvalue() if insecure: logger.warn("Unprotected private keys in cert package being written to disk") with open('%s-pkg.zip'%name,'w') as f: f.write(pkg) else: # actually output the package to disk with a protected private key with zipfile.ZipFile('%s-pkg.zip'%name,'w',compression=zipfile.ZIP_STORED) as f: f.writestr('%s-public.pem'%name,pub) f.writestr('%s-cert.crt'%name,cert) f.writestr('%s-private.pem'%name,prot_priv) f.writestr('cacert.crt',cacert) f.writestr('cacrl.der',crl) f.writestr('cacrl.pem',crlpem) logger.info("Creating cert package for %s in %s-pkg.zip"%(name,name)) return pkg,serial,subject finally: os.chdir(cwd)
def main(argv=sys.argv): if os.getuid() != 0 and not common.DEVELOP_IN_ECLIPSE: 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 secure_mount.mount() # change dir to working dir common.ch_dir() #initialize tpm (ek, ekcert, aik) = tpm_initialize.init( self_activate=False, config_pw=config.get('cloud_node', 'tpm_ownerpassword') ) # this tells initialize not to self activate the AIK virtual_node = tpm_initialize.is_vtpm() if common.STUB_TPM: ekcert = common.TEST_EK_CERT if virtual_node and (ekcert is None or common.STUB_TPM): ekcert = 'virtual' # now we need the UUID try: node_uuid = config.get('cloud_node', 'node_uuid') except ConfigParser.NoOptionError: node_uuid = None if node_uuid == 'openstack': node_uuid = openstack.get_openstack_uuid() elif node_uuid == 'hash_ek': node_uuid = hashlib.sha256(ek).hexdigest() elif node_uuid == 'generate' or node_uuid is None: node_uuid = str(uuid.uuid4()) if common.DEVELOP_IN_ECLIPSE: node_uuid = "C432FBB3-D2F1-4A97-9EF7-75BD81C866E9" # use an TLS context with no certificate checking registrar_client.noAuthTLSContext(config) # register it and get back a blob keyblob = registrar_client.doRegisterNode(registrar_ip, registrar_port, node_uuid, ek, ekcert, aik) if keyblob is None: raise Exception("Registration failed") # get the ephemeral registrar key key = tpm_initialize.activate_identity(keyblob) # tell the registrar server we know the key if virtual_node: deepquote = tpm_quote.create_deep_quote( hashlib.sha1(key).hexdigest(), node_uuid + aik + ek) registrar_client.doActivateVirtualNode(registrar_ip, registrar_port, node_uuid, deepquote) else: registrar_client.doActivateNode(registrar_ip, registrar_port, node_uuid, key) serveraddr = ('', config.getint('general', 'cloudnode_port')) server = CloudNodeHTTPServer(serveraddr, Handler, node_uuid) thread = threading.Thread(target=server.serve_forever) threads = [] servers = [] threads.append(thread) servers.append(server) # start the server logger.info('Starting Cloud Node on port %s use <Ctrl-C> to stop' % serveraddr[1]) for thread in threads: thread.start() def signal_handler(signal, frame): do_shutdown(servers) sys.exit(0) # Catch these signals. Note that a SIGKILL cannot be caught, so # killing this process with "kill -9" may result in improper shutdown signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGQUIT, signal_handler) signal.signal(signal.SIGINT, signal_handler) # keep the main thread active, so it can process the signals and gracefully shutdown while True: if not any([thread.isAlive() for thread in threads]): # All threads have stopped break else: # Some threads are still going time.sleep(1) for thread in threads: thread.join()