def test_021_node_quotes_identity_get(self): """Test node's GET /v2/quotes/identity Interface""" global aik self.assertIsNotNone( aik, "Required value not set. Previous step may have failed?") nonce = tpm_initialize.random_password(20) numretries = config.getint('tenant', 'max_retries') while numretries >= 0: response = tornado_requests.request( "GET", "http://%s:%s/v2/quotes/identity/nonce/%s/" % (tenant_templ.cloudnode_ip, tenant_templ.cloudnode_port, nonce)) if response.status_code == 200: break numretries -= 1 time.sleep(config.getint('tenant', 'max_retries')) self.assertEqual(response.status_code, 200, "Non-successful Node identity return code!") response_body = response.json() # Ensure response is well-formed self.assertIn("results", response_body, "Malformed response body!") self.assertIn("quote", response_body["results"], "Malformed response body!") self.assertIn("pubkey", response_body["results"], "Malformed response body!") # Check the quote identity self.assertTrue( tpm_quote.check_quote(nonce, response_body["results"]["pubkey"], response_body["results"]["quote"], aik), "Invalid quote!")
def test_040_node_quotes_integrity_get(self): """Test node's GET /v2/quotes/integrity Interface""" global public_key, aik self.assertIsNotNone(aik, "Required value not set. Previous step may have failed?") nonce = tpm_initialize.random_password(20) mask = self.tpm_policy["mask"] vmask = self.vtpm_policy["mask"] partial = "1" if public_key is None: partial = "0" response = tornado_requests.request( "GET", "http://%s:%s/v2/quotes/integrity/nonce/%s/mask/%s/vmask/%s/partial/%s/"%(tenant_templ.cloudnode_ip,tenant_templ.cloudnode_port,nonce,mask,vmask,partial) ) self.assertEqual(response.status_code, 200, "Non-successful Node Integrity Get return code!") response_body = response.json() # Ensure response is well-formed self.assertIn("results", response_body, "Malformed response body!") self.assertIn("quote", response_body["results"], "Malformed response body!") if public_key is None: self.assertIn("pubkey", response_body["results"], "Malformed response body!") public_key = response_body["results"]["pubkey"] quote = response_body["results"]["quote"] validQuote = tpm_quote.check_quote(nonce, public_key, quote, aik, self.tpm_policy) self.assertTrue(validQuote)
def validate_tpm_quote(self, public_key, quote): registrar_client.serverAuthTLSContext(config, 'tenant') aikFromRegistrar = registrar_client.getAIK(self.cloudverifier_ip, self.registrar_port, self.node_uuid) if aikFromRegistrar is not None: return tpm_quote.check_quote(self.nonce, public_key, quote, aikFromRegistrar) else: logger.warning("AIK not found in registrar, quote not validated") return False
def process_quote_response(instance, json_response): """Validates the response from the Cloud node. This method invokes an Registrar Server call to register, and then check the quote. """ received_public_key = None quote = None # in case of failure in response content do not continue try: received_public_key = json_response.get("pubkey", None) quote = json_response["quote"] ima_measurement_list = json_response.get("ima_measurement_list", None) logger.debug("received quote: %s" % quote) logger.debug("for nonce: %s" % instance['nonce']) logger.debug("received public key: %s" % received_public_key) logger.debug("received ima_measurement_list %s" % (ima_measurement_list != None)) except Exception: return None # if no public key provided, then ensure we have cached it if received_public_key is None: if instance.get('public_key', "") == "" or instance.get( 'b64_encrypted_V', "") == "": logger.error( "node did not provide public key and no key or encrypted_v was cached at CV" ) return False instance['provide_V'] = False received_public_key = instance['public_key'] if instance.get('registrar_keys', "") is "": registrar_client.init_client_tls(config, 'cloud_verifier') registrar_keys = registrar_client.getKeys( config.get("general", "registrar_ip"), config.get("general", "registrar_tls_port"), instance['instance_id']) if registrar_keys is None: logger.warning("AIK not found in registrar, quote not validated") return False instance['registrar_keys'] = registrar_keys if tpm_quote.is_deep_quote(quote): validQuote = tpm_quote.check_deep_quote( instance['nonce'], received_public_key, quote, instance['registrar_keys']['aik'], instance['registrar_keys']['provider_keys']['aik'], instance['vtpm_policy'], instance['tpm_policy'], ima_measurement_list, instance['ima_whitelist']) else: validQuote = tpm_quote.check_quote(instance['nonce'], received_public_key, quote, instance['registrar_keys']['aik'], instance['tpm_policy'], ima_measurement_list, instance['ima_whitelist']) if not validQuote: return False # set a flag so that we know that the node was verified once. # we only issue notifications for nodes that were at some point good instance['first_verified'] = True # has public key changed? if so, clear out b64_encrypted_V, it is no longer valid if received_public_key != instance.get('public_key', ""): instance['public_key'] = received_public_key instance['b64_encrypted_V'] = "" instance['provide_V'] = True # ok we're done return validQuote
def validate_tpm_quote(self, public_key, quote): registrar_client.init_client_tls(config, 'tenant') reg_keys = registrar_client.getKeys(self.cloudverifier_ip, self.registrar_port, self.node_uuid) if reg_keys is None: logger.warning("AIK not found in registrar, quote not validated") return False if not tpm_quote.check_quote(self.nonce, public_key, quote, reg_keys['aik']): if reg_keys['regcount'] > 1: logger.error( "WARNING: This UUID had more than one ek-ekcert registered to it! This might indicate that your system is misconfigured or a malicious node is present. Run 'regdelete' for this node and restart it to make this message go away!" ) return False if reg_keys['regcount'] > 1: logger.warn( "WARNING: This UUID had more than one ek-ekcert registered to it! This might indicate that your system is misconfigured. Run 'regdelete' for this node and restart it to make this message go away!" ) if not common.STUB_TPM and ( not config.getboolean('tenant', 'require_ek_cert') and config.get('tenant', 'ek_check_script') == ""): logger.warn( "DANGER: EK cert checking is disabled and no additional checks on EKs have been specified with ek_check_script option. Keylime is not secure!!" ) # check EK cert and make sure it matches EK if not self.check_ek(reg_keys['ek'], reg_keys['ekcert']): return False # if node is virtual, check phyisical EK cert and make sure it matches phyiscal EK if 'provider_keys' in reg_keys: if not self.check_ek(reg_keys['provider_keys']['ek'], reg_keys['provider_keys']['ekcert']): return False # check all EKs with optional script: script = config.get('tenant', 'ek_check_script') if script is not "": if script[0] != '/': script = "%s/%s" % (common.WORK_DIR, script) logger.info("Checking EK with script %s" % script) #now we need to exec the script with the ek and ek cert in vars env = os.environ.copy() env['NODE_UUID'] = self.node_uuid env['EK'] = reg_keys['ek'] if reg_keys['ekcert'] is not None: env['EK_CERT'] = reg_keys['ekcert'] else: env['EK_CERT'] = "" env['PROVKEYS'] = json.dumps(reg_keys.get('provider_keys', {})) proc = subprocess.Popen(script, env=env, shell=True, cwd=common.WORK_DIR, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) retval = proc.wait() if retval != 0: logger.error("External check script failed to validate EK") while True: line = proc.stdout.readline() if line == "": break logger.debug("ek_check output: %s" % line.strip()) return False else: logger.debug( "External check script successfully to validated EK") while True: line = proc.stdout.readline() if line == "": break logger.debug("ek_check output: %s" % line.strip()) return True
def process_quote_response(instance, json_response, config): """Validates the response from the Cloud node. This method invokes an Registrar Server call to register, and then check the quote. """ received_public_key = None quote = None # in case of failure in response content do not continue try: received_public_key = json_response.get("pubkey", None) quote = json_response["quote"] ima_measurement_list = json_response.get("ima_measurement_list", None) logger.debug("received quote: %s" % quote) logger.debug("for nonce: %s" % instance['nonce']) logger.debug("received public key: %s" % received_public_key) logger.debug("received ima_measurement_list %s" % (ima_measurement_list != None)) except Exception: return None # if no public key provided, then ensure we have cached it if received_public_key is None: if instance.get('public_key', "") == "" or instance.get( 'b64_encrypted_V', "") == "": logger.error( "node did not provide public key and no key or encrypted_v was cached at CV" ) return False instance['provide_V'] = False received_public_key = instance['public_key'] if instance.get('aikFromRegistrar', "") is "" or instance.get( 'aikFromRegistrarCacheHits', common.MAX_STALE_REGISTRAR_CACHE ) >= common.MAX_STALE_REGISTRAR_CACHE: # talk to yourself fool registrar_client.serverAuthTLSContext(config, 'cloud_verifier') aikFromRegistrar = registrar_client.getAIK( config.get("general", "registrar_ip"), config.get("general", "registrar_port"), instance['instance_id']) if aikFromRegistrar is None: logger.warning("AIK not found in registrar, quote not validated") return False instance['aikFromRegistrar'] = aikFromRegistrar instance['aikFromRegistrarCacheHits'] = 0 else: aikFromRegistrar = instance['aikFromRegistrar'] instance['aikFromRegistrarCacheHits'] += 1 if not instance['vtpm_policy']: validQuote = tpm_quote.check_quote(instance['nonce'], received_public_key, quote, aikFromRegistrar, instance['tpm_policy'], ima_measurement_list, instance['ima_whitelist']) else: registrar_client.serverAuthTLSContext(config, 'cloud_verifier') dq_aik = registrar_client.getAIK( config.get("general", "provider_registrar_ip"), config.get("general", "provider_registrar_port"), instance['instance_id']) if dq_aik is None: logger.warning( "provider AIK not found in registrar, deep quote not validated" ) return False validQuote = tpm_quote.check_deep_quote( instance['nonce'], received_public_key, quote, aikFromRegistrar, dq_aik, instance['vtpm_policy'], instance['tpm_policy'], ima_measurement_list, instance['ima_whitelist']) if not validQuote: return False # has public key changed? if so, clear out b64_encrypted_V, it is no longer valid if received_public_key != instance.get('public_key', ""): instance['public_key'] = received_public_key instance['b64_encrypted_V'] = "" instance['provide_V'] = True # ok we're done return validQuote