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 do_GET(self): """This method services the GET request typically from either the Tenant or the Cloud Verifier. Only tenant and cloudverifier uri's are supported. Both requests require a nonce parameter. The Cloud verifier requires an additional mask paramter. If the uri or parameters are incorrect, a 400 response is returned. """ logger.info('GET invoked from ' + str(self.client_address) + ' with uri:' + self.path) rest_params = common.get_restful_params(self.path) if rest_params is None: common.echo_json_response(self, 405, "Not Implemented: Use /v2/keys/ or /v2/quotes/ interfaces") return if "keys" in rest_params and rest_params['keys']=='verify': if self.server.K is None: logger.info('GET key challenge returning 400 response. bootstrap key not available') common.echo_json_response(self, 400, "Bootstrap key not yet available.") return challenge = rest_params['challenge'] response={} response['hmac'] = crypto.do_hmac(self.server.K, challenge) common.echo_json_response(self, 200, "Success", response) logger.info('GET key challenge returning 200 response.') # If node pubkey requested elif "keys" in rest_params and rest_params["keys"] == "pubkey": response = {} response['pubkey'] = self.server.rsapublickey_exportable common.echo_json_response(self, 200, "Success", response) logger.info('GET pubkey returning 200 response.') return elif "quotes" in rest_params: nonce = rest_params['nonce'] pcrmask = rest_params['mask'] if 'mask' in rest_params else None vpcrmask = rest_params['vmask'] if 'vmask' in rest_params else None # if the query is not messed up if nonce is None: logger.warning('GET quote returning 400 response. nonce not provided as an HTTP parameter in request') common.echo_json_response(self, 400, "nonce not provided as an HTTP parameter in request") return # Sanitization assurance (for tpm_exec.run() tasks below) if not (nonce.isalnum() and (pcrmask is None or pcrmask.isalnum()) and (vpcrmask is None or vpcrmask.isalnum())): logger.warning('GET quote returning 400 response. parameters should be strictly alphanumeric') common.echo_json_response(self, 400, "parameters should be strictly alphanumeric") return # identity quotes are always shallow if not tpm_initialize.is_vtpm() or rest_params["quotes"]=='identity': quote = tpm_quote.create_quote(nonce, self.server.rsapublickey_exportable,pcrmask) imaMask = pcrmask else: quote = tpm_quote.create_deep_quote(nonce, self.server.rsapublickey_exportable, vpcrmask, pcrmask) imaMask = vpcrmask # Allow for a partial quote response (without pubkey) if "partial" in rest_params and (rest_params["partial"] is None or int(rest_params["partial"],0) == 1): response = { 'quote': quote, } else: response = { 'quote': quote, 'pubkey': self.server.rsapublickey_exportable, } # return a measurement list if available if tpm_quote.check_mask(imaMask, common.IMA_PCR): if not os.path.exists(common.IMA_ML): logger.warn("IMA measurement list not available: %s"%(common.IMA_ML)) else: with open(common.IMA_ML,'r') as f: ml = f.read() response['ima_measurement_list']=ml common.echo_json_response(self, 200, "Success", response) logger.info('GET %s quote returning 200 response.'%(rest_params["quotes"])) return else: logger.warning('GET returning 400 response. uri not supported: ' + self.path) common.echo_json_response(self, 400, "uri not supported") return
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) = 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() # try to get some TPM randomness into the system entropy pool tpm_random.init_system_rand() if ekcert is None: if virtual_node: ekcert = 'virtual' elif tpm_initialize.is_emulator(): ekcert = 'emulator' # 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" 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! node_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("Node UUID: %s"%node_uuid) # 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 retval=False if virtual_node: deepquote = tpm_quote.create_deep_quote(hashlib.sha1(key).hexdigest(),node_uuid+aik+ek) retval = registrar_client.doActivateVirtualNode(registrar_ip, registrar_port, node_uuid, deepquote) else: retval = registrar_client.doActivateNode(registrar_ip,registrar_port,node_uuid,key) if not retval: raise Exception("Registration failed on activate") serveraddr = ('', config.getint('general', 'cloudnode_port')) server = CloudNodeHTTPServer(serveraddr,Handler,node_uuid) serverthread = threading.Thread(target=server.serve_forever) logger.info( 'Starting Cloud Node on port %s use <Ctrl-C> to stop'%serveraddr[1]) serverthread.start() # want to listen for revocations? if config.getboolean('cloud_node','listen_notfications'): cert_path = config.get('cloud_node','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 = config.get('cloud_node','revocation_actions') if actionlist.strip() == "": logger.debug("No revocation actions specified") return if actionlist =='default': # load actions from unzipped with open("%s/unzipped/action_list"%secdir,'r') as f: actionlist = f.read() actionlist = actionlist.strip().split(',') uzpath = "%s/unzipped"%secdir if uzpath not in sys.path: sys.path.append(uzpath) else: # load the actions from inside the keylime module actionlist = actionlist.split(',') actionlist = ["revocation_actions.%s"%i for i in actionlist] for action in actionlist: module = importlib.import_module(action) execute = getattr(module,'execute') try: execute(revocation) except Exception as e: logger.warn("Exception during exeuction 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_initialize.flush_keys() server.shutdown() else: try: while True: time.sleep(1) except KeyboardInterrupt: logger.info("TERM Signal received, shutting down...") tpm_initialize.flush_keys() server.shutdown()
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()