async def get_agent_state(self, agent_id): try: get_agent_state = RequestsClient(verifier_base_url, tls_enabled) response = get_agent_state.get( (f'/agents/{agent_id}'), cert=cert, verify=False ) except Exception as e: logger.error("Status command response: %s:%s Unexpected response from Cloud Verifier.", tenant_templ.cloudverifier_ip, tenant_templ.cloudverifier_port) logger.exception(e) config.echo_json_response( self, 500, "Unexpected response from Cloud Verifier", str(e)) logger.error("Unexpected response from Cloud Verifier: %s", e) return inst_response_body = response.json() if response.status_code != 200 and response.status_code != 404: logger.error("Status command response: %d Unexpected response from Cloud Verifier.", response.status_code) keylime_logging.log_http_response( logger, logging.ERROR, inst_response_body) return None if "results" not in inst_response_body: logger.critical("Error: unexpected http response body from Cloud Verifier: %s", response.status_code) return None # Agent not added to CV (but still registered) if response.status_code == 404: return {"operational_state": states.REGISTERED} return inst_response_body["results"]
def test_014_reg_agent_get(self): """Test registrar's GET /agents/{UUID} Interface""" test_014_reg_agent_get = RequestsClient( tenant_templ.registrar_base_tls_url, tls_enabled=True) response = test_014_reg_agent_get.get( f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}", cert=tenant_templ.cert, verify=False) self.assertEqual(response.status_code, 200, "Non-successful Registrar agent return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") self.assertIn("ek_tpm", json_response["results"], "Malformed response body!") self.assertIn("aik_tpm", json_response["results"], "Malformed response body!") self.assertIn("ekcert", json_response["results"], "Malformed response body!") self.assertIn("mtls_cert", json_response["results"], "Malformed response body!") self.assertIn("ip", json_response["results"], "Malformed response body!") self.assertIn("port", json_response["results"], "Malformed response body!") global aik_tpm global mtls_cert mtls_cert = json_response["results"]["mtls_cert"] aik_tpm = json_response["results"]["aik_tpm"]
def test_020_agent_keys_pubkey_get(self): """Test agent's GET /keys/pubkey Interface""" # We want a real cloud agent to communicate with! launch_cloudagent() test_020_agent_keys_pubkey_get = RequestsClient( tenant_templ.agent_base_url, tls_enabled=True, ignore_hostname=True) response = test_020_agent_keys_pubkey_get.get( f"/v{self.api_version}/keys/pubkey", cert=tenant_templ.agent_cert, verify=False, # TODO: use agent certificate ) self.assertEqual(response.status_code, 200, "Non-successful Agent pubkey return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") self.assertIn("pubkey", json_response["results"], "Malformed response body!") global public_key public_key = json_response["results"]["pubkey"] self.assertNotEqual(public_key, None, "Malformed response body!")
def do_verify(self): """ Perform verify using a random generated challenge """ challenge = TPM_Utilities.random_password(20) numtries = 0 while True: try: cloudagent_base_url = (f'{self.agent_ip}:{self.agent_port}') do_verify = RequestsClient(cloudagent_base_url, tls_enabled=False) response = do_verify.get( (f'/keys/verify?challenge={challenge}'), cert=self.cert, verify=False) except Exception as e: if response.status_code in (503, 504): numtries += 1 maxr = config.getint('tenant', 'max_retries') if numtries >= maxr: logger.error( f"Cannot establish connection to agent on {self.agent_ip} with port {self.agent_port}" ) sys.exit() retry = config.getfloat('tenant', 'retry_interval') logger.info( f"Verifier connection to agent at {self.agent_ip} refused {numtries}/{maxr} times, trying again in {retry} seconds..." ) time.sleep(retry) continue raise e response_body = response.json() if response.status_code == 200: if "results" not in response_body or 'hmac' not in response_body[ 'results']: logger.critical( f"Error: unexpected http response body from Cloud Agent: {response.status_code}" ) break mac = response_body['results']['hmac'] ex_mac = crypto.do_hmac(self.K, challenge) if mac == ex_mac: logger.info("Key derivation successful") else: logger.error("Key derivation failed") else: keylime_logging.log_http_response(logger, logging.ERROR, response_body) retry = config.getfloat('tenant', 'retry_interval') logger.warning( f"Key derivation not yet complete...trying again in {retry} seconds...Ctrl-C to stop" ) time.sleep(retry) continue break
def getData(registrar_ip, registrar_port, agent_id): # make absolutely sure you don't ask for data that contains AIK keys unauthenticated if not tls_enabled: raise Exception( "It is unsafe to use this interface to query AIKs without server-authenticated TLS.") response = None try: client = RequestsClient(f'{registrar_ip}:{registrar_port}', tls_enabled) response = client.get(f'/v{api_version}/agents/{agent_id}', cert=tls_cert_info, verify=False) response_body = response.json() if response.status_code != 200: logger.critical("Error: unexpected http response code from Registrar Server: %s", response.status_code) keylime_logging.log_http_response(logger, logging.CRITICAL, response_body) return None # Check for all values that are consumed by other parts of Keylime if "results" not in response_body: logger.critical("Error: unexpected http response body from Registrar Server: %s", response.status_code) return None if "aik_tpm" not in response_body["results"]: logger.critical("Error: did not receive AIK from Registrar Server.") return None if "regcount" not in response_body["results"]: logger.critical("Error: did not receive regcount from Registrar Server.") return None if "ek_tpm" not in response_body["results"]: logger.critical("Error: did not receive EK from Registrar Server.") return None if "ip" not in response_body["results"]: logger.critical("Error: did not receive IP from Registrar Server.") return None if "port" not in response_body["results"]: logger.critical("Error: did not receive port from Registrar Server.") return None return response_body["results"] except AttributeError as e: if response and response.status_code == 503: logger.critical("Error: the registrar is not available at %s:%s", registrar_ip, registrar_port) else: logger.exception(e) except Exception as e: logger.exception(e) return None
def doRegistrarList(registrar_ip, registrar_port): client = RequestsClient(f'{registrar_ip}:{registrar_port}', tls_enabled) response = client.get(f'/v{api_version}/agents/', cert=tls_cert_info, verify=False) response_body = response.json() if response.status_code != 200: logger.warning("Registrar returned: %s Unexpected response from registrar.", response.status_code) keylime_logging.log_http_response(logger, logging.WARNING, response_body) return None return response_body
def test_040_agent_quotes_integrity_get(self): """Test agent's GET /quotes/integrity Interface""" global public_key self.assertIsNotNone( aik_tpm, "Required value not set. Previous step may have failed?") nonce = tpm_abstract.TPM_Utilities.random_password(20) mask = self.tpm_policy["mask"] partial = "1" if public_key is None: partial = "0" test_040_agent_quotes_integrity_get = RequestsClient( tenant_templ.agent_base_url, tls_enabled=True, ignore_hostname=True) response = test_040_agent_quotes_integrity_get.get( f"/v{self.api_version}/quotes/integrity?nonce={nonce}&mask={mask}&partial={partial}", cert=tenant_templ.agent_cert, verify=False, # TODO: use agent certificate ) self.assertEqual(response.status_code, 200, "Non-successful Agent Integrity Get return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") self.assertIn("quote", json_response["results"], "Malformed response body!") if public_key is None: self.assertIn("pubkey", json_response["results"], "Malformed response body!") public_key = json_response["results"]["pubkey"] self.assertIn("hash_alg", json_response["results"], "Malformed response body!") quote = json_response["results"]["quote"] hash_alg = algorithms.Hash(json_response["results"]["hash_alg"]) agentAttestState = cloud_verifier_common.get_AgentAttestStates( ).get_by_agent_id(tenant_templ.agent_uuid) failure = tpm_instance.check_quote(agentAttestState, nonce, public_key, quote, aik_tpm, self.tpm_policy, hash_alg=hash_alg) self.assertTrue(not failure)
def test_060_cv_version_get(self): """Test CV's GET /version Interface""" cv_client = RequestsClient(tenant_templ.verifier_base_url, tls_enabled) response = cv_client.get("/version", cert=tenant_templ.cert, verify=False) self.assertEqual(response.status_code, 200, "Non-successful CV allowlist Post return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") results = json_response["results"] self.assertEqual(results["current_version"], api_version.current_version()) self.assertEqual(results["supported_versions"], api_version.all_versions())
def getKeys(registrar_ip, registrar_port, agent_id): # make absolutely sure you don't ask for AIKs unauthenticated if not tls_enabled: raise Exception( "It is unsafe to use this interface to query AIKs without server-authenticated TLS." ) response = None try: client = RequestsClient(f'{registrar_ip}:{registrar_port}', tls_enabled) response = client.get(f'/agents/{agent_id}', cert=tls_cert_info, verify=False) response_body = response.json() if response.status_code != 200: logger.critical( "Error: unexpected http response code from Registrar Server: %s" % str(response.status_code)) keylime_logging.log_http_response(logger, logging.CRITICAL, response_body) return None if "results" not in response_body: logger.critical( "Error: unexpected http response body from Registrar Server: %s" % str(response.status_code)) return None if "aik" not in response_body["results"]: logger.critical( "Error: did not receive AIK from Registrar Server: %s" % str(response.status_code)) return None return response_body["results"] except AttributeError as e: if response and response.status_code == 503: logger.critical("Error: the registrar is not available at %s:%s" % (registrar_ip, registrar_port)) else: logger.exception(e) except Exception as e: logger.exception(e) return None
def test_013_reg_agents_get(self): """Test registrar's GET /agents Interface""" test_013_reg_agents_get = RequestsClient(tenant_templ.registrar_base_tls_url, tls_enabled=True) response = test_013_reg_agents_get.get(f"/v{self.api_version}/agents/", cert=tenant_templ.cert, verify=False) self.assertEqual(response.status_code, 200, "Non-successful Registrar agent List return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") self.assertIn("uuids", json_response["results"], "Malformed response body!") # We registered exactly one agent so far self.assertEqual(1, len(json_response["results"]["uuids"]), "Incorrect system state!")
def test_032_cv_agents_get(self): """Test CV's GET /agents Interface""" test_032_cv_agents_get = RequestsClient(tenant_templ.verifier_base_url, tls_enabled) response = test_032_cv_agents_get.get(f"/v{self.api_version}/agents/", cert=tenant_templ.cert, verify=False) self.assertEqual(response.status_code, 200, "Non-successful CV agent List return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") self.assertIn("uuids", json_response["results"], "Malformed response body!") # Be sure our agent is registered self.assertEqual(1, len(json_response["results"]["uuids"]))
def test_040_agent_quotes_integrity_get(self): """Test agent's GET /v2/quotes/integrity Interface""" global public_key, aik self.assertIsNotNone( aik, "Required value not set. Previous step may have failed?") nonce = tpm_abstract.TPM_Utilities.random_password(20) mask = self.tpm_policy["mask"] vmask = self.vtpm_policy["mask"] partial = "1" if public_key is None: partial = "0" test_040_agent_quotes_integrity_get = RequestsClient( tenant_templ.agent_base_url, tls_enabled=False) response = test_040_agent_quotes_integrity_get.get( f'/v{self.api_version}/quotes/integrity?nonce={nonce}&mask={mask}&vmask={vmask}&partial={partial}', cert="", verify=False) self.assertEqual(response.status_code, 200, "Non-successful Agent Integrity Get return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") self.assertIn("quote", json_response["results"], "Malformed response body!") if public_key is None: self.assertIn("pubkey", json_response["results"], "Malformed response body!") public_key = json_response["results"]["pubkey"] self.assertIn("tpm_version", json_response["results"], "Malformed response body!") self.assertIn("hash_alg", json_response["results"], "Malformed response body!") quote = json_response["results"]["quote"] hash_alg = json_response["results"]["hash_alg"] validQuote = tpm.check_quote(tenant_templ.agent_uuid, nonce, public_key, quote, aik, self.tpm_policy, hash_alg=hash_alg) self.assertTrue(validQuote)
def test_022_agent_quotes_identity_get(self): """Test agent's GET /quotes/identity Interface""" self.assertIsNotNone( aik_tpm, "Required value not set. Previous step may have failed?") nonce = tpm_abstract.TPM_Utilities.random_password(20) numretries = config.getint("tenant", "max_retries") while numretries >= 0: test_022_agent_quotes_identity_get = RequestsClient( tenant_templ.agent_base_url, tls_enabled=True, ignore_hostname=True) response = test_022_agent_quotes_identity_get.get( f"/v{self.api_version}/quotes/identity?nonce={nonce}", data=None, cert=tenant_templ.agent_cert, verify=False, # TODO: use agent certificate ) if response.status_code == 200: break numretries -= 1 time.sleep(config.getint("tenant", "retry_interval")) self.assertEqual(response.status_code, 200, "Non-successful Agent identity return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") self.assertIn("quote", json_response["results"], "Malformed response body!") self.assertIn("pubkey", json_response["results"], "Malformed response body!") agentAttestState = cloud_verifier_common.get_AgentAttestStates( ).get_by_agent_id(tenant_templ.agent_uuid) # Check the quote identity failure = tpm_instance.check_quote( agentAttestState, nonce, json_response["results"]["pubkey"], json_response["results"]["quote"], aik_tpm, hash_alg=algorithms.Hash(json_response["results"]["hash_alg"]), ) self.assertTrue(not failure, "Invalid quote!")
def do_cvstatus(self, listing=False): """ Perform opertional state look up for agent Keyword Arguments: listing {bool} -- If True, list all agent statues (default: {False}) """ agent_uuid = "" if not listing: agent_uuid = self.agent_uuid do_cvstatus = RequestsClient(self.verifier_base_url, self.tls_enabled) response = do_cvstatus.get((f'/agents/{agent_uuid}'), cert=self.cert, verify=False) if response.status_code == 503: logger.error( f"Cannot connect to Verifier at {self.verifier_ip} with Port {self.verifier_port}. Connection refused." ) sys.exit() elif response == 504: logger.error( f"Verifier at {self.verifier_ip} with Port {self.verifier_port} timed out." ) sys.exit() if response.status_code == 404: logger.error( f"Agent {agent_uuid} does not exist on the verifier. Please try to add or update agent" ) sys.exit() if response.status_code != 200: logger.error( f"Status command response: {response.status_code}. Unexpected response from Cloud Verifier." ) sys.exit() else: response_json = response.json() if not listing: operational_state = response_json["results"][ "operational_state"] logger.info( f'Agent Status: "{states.state_to_str(operational_state)}"' ) else: agent_array = response_json["results"]["uuids"] logger.info(f'Agents: "{agent_array}"')
def test_026_cv_allowlist_get(self): """Test CV's GET /allowlists/{name} Interface""" cv_client = RequestsClient(tenant_templ.verifier_base_url, tls_enabled) response = cv_client.get( f"/v{self.api_version}/allowlists/test-allowlist", cert=tenant_templ.cert, verify=False ) self.assertEqual(response.status_code, 200, "Non-successful CV allowlist Post return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") results = json_response["results"] self.assertEqual(results["name"], "test-allowlist") self.assertEqual(results["tpm_policy"], json.dumps(self.tpm_policy)) self.assertEqual(results["ima_policy"], json.dumps(self.allowlist))
def do_cvdelete(self): """Delete agent from Verifier """ do_cvdelete = RequestsClient(self.verifier_base_url, self.tls_enabled) response = do_cvdelete.delete( (f'/agents/{self.agent_uuid}'), cert=self.cert, verify=False ) if response.status_code == 503: logger.error( f"Cannot connect to Verifier at {self.verifier_ip} with Port {self.verifier_port}. Connection refused.") sys.exit() elif response.status_code == 504: logger.error( f"Verifier at {self.verifier_ip} with Port {self.verifier_port} timed out.") sys.exit() if response.status_code == 202: deleted = False for _ in range(12): get_cvdelete = RequestsClient( self.verifier_base_url, self.tls_enabled) response = get_cvdelete.get( (f'/agents/{self.agent_uuid}'), cert=self.cert, verify=False ) if response.status_code in (200, 404): deleted = True break time.sleep(.4) if deleted: logger.info( f"CV completed deletion of agent {self.agent_uuid}") else: logger.error( f"Timed out waiting for delete of agent {self.agent_uuid} to complete at CV") sys.exit() elif response.status_code == 200: logger.info(f"Agent {self.agent_uuid} deleted from the CV") else: response_body = response.json() keylime_logging.log_http_response( logger, logging.ERROR, response_body)
def test_033_cv_agent_get(self): """Test CV's GET /agents/{UUID} Interface""" test_033_cv_agent_get = RequestsClient(tenant_templ.verifier_base_url, tls_enabled) response = test_033_cv_agent_get.get( f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}", cert=tenant_templ.cert, verify=False ) self.assertEqual(response.status_code, 200, "Non-successful CV agent return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") # Check a few of the important properties are present self.assertIn("operational_state", json_response["results"], "Malformed response body!") self.assertIn("ip", json_response["results"], "Malformed response body!") self.assertIn("port", json_response["results"], "Malformed response body!")
def get_openstack_uuid( uuid_service_ip='169.254.169.254', uuid_service_resource='/openstack/2012-08-10/meta_data.json'): logger.debug("Getting instance UUID from openstack http://%s%s" % (uuid_service_ip, uuid_service_resource)) try: client = RequestsClient(uuid_service_ip, False) response = client.get(uuid_service_resource) if response.status_code == 200: response_body = response.json() return response_body["uuid"] logger.debug("Forcing using locally generated uuid.") return str(uuid.uuid4()) except Exception as e: logger.debug( "Using locally generated uuid. Error getting UUID from openstack: %s\n" % (e)) return str(uuid.uuid4())
def test_022_agent_quotes_identity_get(self): """Test agent's GET /quotes/identity Interface""" self.assertIsNotNone( aik_tpm, "Required value not set. Previous step may have failed?") nonce = tpm_abstract.TPM_Utilities.random_password(20) numretries = config.getint('tenant', 'max_retries') while numretries >= 0: test_022_agent_quotes_identity_get = RequestsClient( tenant_templ.agent_base_url, tls_enabled=False) response = test_022_agent_quotes_identity_get.get( f'/v{self.api_version}/quotes/identity?nonce={nonce}', data=None, cert="", verify=False) if response.status_code == 200: break numretries -= 1 time.sleep(config.getint('tenant', 'retry_interval')) self.assertEqual(response.status_code, 200, "Non-successful Agent identity return code!") json_response = response.json() # Ensure response is well-formed self.assertIn("results", json_response, "Malformed response body!") self.assertIn("quote", json_response["results"], "Malformed response body!") self.assertIn("pubkey", json_response["results"], "Malformed response body!") # Check the quote identity self.assertTrue( tpm_instance.check_quote( tenant_templ.agent_uuid, nonce, json_response["results"]["pubkey"], json_response["results"]["quote"], aik_tpm, hash_alg=json_response["results"]["hash_alg"]), "Invalid quote!")
async def get(self): """This method handles the GET requests to retrieve status on agents from the WebApp. Currently, only the web app is available for GETing, i.e. /agents. All other GET uri's will return errors. """ rest_params = config.get_restful_params(self.request.uri) if rest_params is None: config.echo_json_response( self, 405, "Not Implemented: Use /agents/ or /logs/ interface") return if "logs" in rest_params and rest_params["logs"] == "tenant": offset = 0 if "pos" in rest_params and rest_params[ "pos"] is not None and rest_params["pos"].isdigit(): offset = int(rest_params["pos"]) # intercept requests for logs with open(keylime_logging.LOGSTREAM, 'r') as f: logValue = f.readlines() config.echo_json_response(self, 200, "Success", {'log': logValue[offset:]}) return if "agents" not in rest_params: # otherwise they must be looking for agent info config.echo_json_response(self, 400, "uri not supported") logger.warning('GET returning 400 response. uri not supported: %s', self.request.path) return agent_id = rest_params["agents"] if agent_id is not None: # Handle request for specific agent data separately agents = await self.get_agent_state(agent_id) agents["id"] = agent_id config.echo_json_response(self, 200, "Success", agents) return # If no agent ID, get list of all agents from Registrar try: get_agents = RequestsClient(registrar_base_tls_url, tls_enabled) response = get_agents.get(('/agents/'), cert=cert, verify=False) except Exception as e: logger.error( "Status command response: %s:%s Unexpected response from Registrar.", tenant_templ.registrar_ip, tenant_templ.registrar_port) logger.exception(e) config.echo_json_response(self, 500, "Unexpected response from Registrar", str(e)) return response_body = response.json() if response.status_code != 200: logger.error( "Status command response: %d Unexpected response from Registrar.", response.status_code) keylime_logging.log_http_response(logger, logging.ERROR, response_body) return None if ("results" not in response_body) or ("uuids" not in response_body["results"]): logger.critical( "Error: unexpected http response body from Registrar: %s", response.status_code) return None agent_list = response_body["results"]["uuids"] # Loop through each agent and ask for status agents = {} for agent in agent_list: agents[agent] = await self.get_agent_state(agent_id) # Pre-create sorted agents list sorted_by_state = {} for state in states.VALID_STATES: sorted_by_state[state] = {} # Build sorted agents list for agent_id in agents: state = agents[agent_id]["operational_state"] sorted_by_state[state][agent_id] = agents[agent_id] print_order = [ states.TENANT_FAILED, states.INVALID_QUOTE, states.FAILED, states.GET_QUOTE, states.GET_QUOTE_RETRY, states.PROVIDE_V, states.PROVIDE_V_RETRY, states.SAVED, states.START, states.TERMINATED, states.REGISTERED ] sorted_agents = [] for state in print_order: for agent_id in sorted_by_state[state]: sorted_agents.append(agent_id) config.echo_json_response(self, 200, "Success", {'uuids': sorted_agents})
async def get(self): """This method handles the GET requests to retrieve status on agents from the WebApp. Currently, only the web app is available for GETing, i.e. /agents. All other GET uri's will return errors. """ rest_params = config.get_restful_params(self.request.uri) if rest_params is None: config.echo_json_response( self, 405, "Not Implemented: Use /agents/ or /logs/ interface") return if "logs" in rest_params and rest_params["logs"] == "tenant": offset = 0 if "pos" in rest_params and rest_params["pos"] is not None and rest_params["pos"].isdigit(): offset = int(rest_params["pos"]) # intercept requests for logs with open(keylime_logging.LOGSTREAM, 'r') as f: logValue = f.readlines() config.echo_json_response(self, 200, "Success", { 'log': logValue[offset:]}) return if "agents" not in rest_params: # otherwise they must be looking for agent info config.echo_json_response(self, 400, "uri not supported") logger.warning('GET returning 400 response. uri not supported: %s', self.request.path) return agent_id = rest_params["agents"] if agent_id is not None: # Handle request for specific agent data separately agents = await self.get_agent_state(agent_id) agents["id"] = agent_id config.echo_json_response(self, 200, "Success", agents) return # If no agent ID, get list of all agents from Registrar try: get_agents = RequestsClient(registrar_base_tls_url, tls_enabled) response = get_agents.get( ('/agents/'), cert=cert, verify=False ) except Exception as e: logger.error("Status command response: %s:%s Unexpected response from Registrar.", tenant_templ.registrar_ip, tenant_templ.registrar_port) logger.exception(e) config.echo_json_response( self, 500, "Unexpected response from Registrar", str(e)) return response_body = response.json() if response.status_code != 200: logger.error("Status command response: %d Unexpected response from Registrar.", response.status_code) keylime_logging.log_http_response( logger, logging.ERROR, response_body) return None if ("results" not in response_body) or ("uuids" not in response_body["results"]): logger.critical("Error: unexpected http response body from Registrar: %s", response.status_code) return None agent_list = response_body["results"]["uuids"] config.echo_json_response(self, 200, "Success", { 'uuids': agent_list})
def do_show_allowlist(self, name): cv_client = RequestsClient(self.verifier_base_url, self.tls_enabled) response = cv_client.get(f'/allowlists/{name}', cert=self.cert, verify=False) print(f"Show allowlist command response: {response.status_code}.") print(response.json())
def do_quote(self): """ Perform TPM quote by GET towards Agent Raises: UserError: Connection handler """ self.nonce = TPM_Utilities.random_password(20) numtries = 0 response = None # Note: We need a specific retry handler (perhaps in common), no point having localised unless we have too. while True: try: params = '/quotes/identity?nonce=%s' % (self.nonce) cloudagent_base_url = f'{self.agent_ip}:{self.agent_port}' do_quote = RequestsClient(cloudagent_base_url, tls_enabled=False) response = do_quote.get( params, cert=self.cert ) response_body = response.json() except Exception as e: if response.status_code in (503, 504): numtries += 1 maxr = config.getint('tenant', 'max_retries') if numtries >= maxr: logger.error("Tenant cannot establish connection to agent on %s with port %s", self.agent_ip, self.agent_port) sys.exit() retry = config.getfloat('tenant', 'retry_interval') logger.info("Tenant connection to agent at %s refused %s/%s times, trying again in %s seconds...", self.agent_ip, numtries, maxr, retry) time.sleep(retry) continue raise e break try: if response is not None and response.status_code != 200: raise UserError( "Status command response: %d Unexpected response from Cloud Agent." % response.status) if "results" not in response_body: raise UserError( "Error: unexpected http response body from Cloud Agent: %s" % str(response.status)) quote = response_body["results"]["quote"] logger.debug("Agent_quote received quote: %s", quote) public_key = response_body["results"]["pubkey"] logger.debug("Agent_quote received public key: %s", public_key) # Ensure hash_alg is in accept_tpm_hash_algs list hash_alg = response_body["results"]["hash_alg"] logger.debug("Agent_quote received hash algorithm: %s", hash_alg) if not algorithms.is_accepted(hash_alg, config.get('tenant', 'accept_tpm_hash_algs').split(',')): raise UserError( "TPM Quote is using an unaccepted hash algorithm: %s" % hash_alg) # Ensure enc_alg is in accept_tpm_encryption_algs list enc_alg = response_body["results"]["enc_alg"] logger.debug("Agent_quote received encryption algorithm: %s", enc_alg) if not algorithms.is_accepted(enc_alg, config.get('tenant', 'accept_tpm_encryption_algs').split(',')): raise UserError( "TPM Quote is using an unaccepted encryption algorithm: %s" % enc_alg) # Ensure sign_alg is in accept_tpm_encryption_algs list sign_alg = response_body["results"]["sign_alg"] logger.debug("Agent_quote received signing algorithm: %s", sign_alg) if not algorithms.is_accepted(sign_alg, config.get('tenant', 'accept_tpm_signing_algs').split(',')): raise UserError( "TPM Quote is using an unaccepted signing algorithm: %s" % sign_alg) if not self.validate_tpm_quote(public_key, quote, hash_alg): raise UserError( "TPM Quote from cloud agent is invalid for nonce: %s" % self.nonce) logger.info("Quote from %s validated", self.agent_ip) # encrypt U with the public key encrypted_U = crypto.rsa_encrypt( crypto.rsa_import_pubkey(public_key), self.U) b64_encrypted_u = base64.b64encode(encrypted_U) logger.debug("b64_encrypted_u: %s", b64_encrypted_u.decode('utf-8')) data = { 'encrypted_key': b64_encrypted_u, 'auth_tag': self.auth_tag } if self.payload is not None: data['payload'] = self.payload u_json_message = json.dumps(data) # post encrypted U back to CloudAgent params = '/keys/ukey' cloudagent_base_url = ( f'{self.agent_ip}:{self.agent_port}' ) post_ukey = RequestsClient(cloudagent_base_url, tls_enabled=False) response = post_ukey.post( params, data=u_json_message ) if response.status_code == 503: logger.error("Cannot connect to Agent at %s with Port %s. Connection refused.", self.agent_ip, self.agent_port) sys.exit() elif response.status_code == 504: logger.error("Verifier at %s with Port %s timed out.", self.verifier_ip, self.verifier_port) sys.exit() if response.status_code != 200: keylime_logging.log_http_response( logger, logging.ERROR, response_body) raise UserError( "Posting of Encrypted U to the Cloud Agent failed with response code %d" % response.status) except Exception as e: self.do_cvstop() raise e