def test_041_node_keys_verify_get(self): """Test node's GET /v2/keys/verify Interface""" self.assertIsNotNone( self.K, "Required value not set. Previous step may have failed?") challenge = tpm_initialize.random_password(20) response = tornado_requests.request( "GET", "http://%s:%s/v2/keys/verify/challenge/%s/" % (tenant_templ.cloudnode_ip, tenant_templ.cloudnode_port, challenge)) self.assertEqual(response.status_code, 200, "Non-successful Node verify return code!") response_body = response.json() # Ensure response is well-formed self.assertIn("results", response_body, "Malformed response body!") self.assertIn("hmac", response_body["results"], "Malformed response body!") # Be sure response is valid mac = response_body['results']['hmac'] ex_mac = crypto.do_hmac(self.K, challenge) self.assertEqual(mac, ex_mac, "Node failed to validate challenge code!")
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 do_verify(self): """initiaite v, instance_id and ip initiate the cloudinit sequence""" challenge = tpm_initialize.random_password(20) numtries = 0 while True: try: response = tornado_requests.request( "GET", "http://%s:%s/v2/keys/verify/challenge/%s/" % (self.cloudnode_ip, self.cloudnode_port, challenge)) except Exception as e: # this is one exception that should return a 'keep going' response if tornado_requests.is_refused(e): numtries += 1 maxr = config.getint('tenant', 'max_retries') if numtries >= maxr: logger.error( "Quitting after max number of retries to connect to %s" % (self.cloudnode_ip)) raise e retry = config.getfloat('tenant', 'retry_interval') logger.info( "Connection to %s refused %d/%d times, trying again in %f seconds..." % (self.cloudnode_ip, numtries, maxr, retry)) time.sleep(retry) continue else: 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( "Error: unexpected http response body from Cloud Node: %s" % str(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: common.log_http_response(logger, logging.ERROR, response_body) retry = config.getfloat('tenant', 'retry_interval') logger.error( "Key derivation not yet complete...trying again in %s seconds...Ctrl-C to stop" % retry) time.sleep(retry) continue break
def prepare_get_quote(instance): """This method encapsulates the action required to invoke a quote request on the Cloud Node. This method is part of the polling loop of the thread launched on Tenant POST. """ instance['nonce'] = tpm_initialize.random_password(20) params = { 'nonce': instance['nonce'], 'mask': instance['tpm_policy']['mask'], 'vmask': instance['vtpm_policy']['mask'], } return params
def do_quote(self): """initiaite v, instance_id and ip initiate the cloudinit sequence""" self.nonce = tpm_initialize.random_password(20) params = { 'nonce': self.nonce, } numtries = 0 while True: try: response = tornado_requests.request( "GET", "http://%s:%s/v1/quotes/tenant" % (self.cloudnode_ip, self.cloudnode_port), params=params) except Exception as e: # this is one exception that should return a 'keep going' response if tornado_requests.is_refused(e): numtries += 1 maxr = config.getint('tenant', 'max_retries') if numtries >= maxr: logger.error( "Quiting after max number of retries to connect to %s" % (self.cloudnode_ip)) raise e retry = config.getfloat('tenant', 'retry_interval') logger.info( "Connection to %s refused %d/%d times, trying again in %f seconds..." % (self.cloudnode_ip, numtries, maxr, retry)) time.sleep(retry) continue else: raise e if response.status_code == 200: response_body = response.json() public_key = response_body["pubkey"] logger.debug("cnquote received public key:" + public_key) quote = response_body["quote"] logger.debug("cnquote received quote:" + quote) if self.validate_tpm_quote(public_key, quote): logger.info("Quote from %s validated" % self.cloudnode_ip) # encrypt U with the public key encrypted_U = crypto.rsa_encrypt( crypto.rsa_import_pubkey(public_key), str(self.U)) b64_encrypted_u = base64.b64encode(encrypted_U) logger.debug("b64_encrypted_u: " + b64_encrypted_u) 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 CloudNode response = tornado_requests.request( "POST", "http://%s:%s/v1/quotes/tenant" % (self.cloudnode_ip, self.cloudnode_port), data=u_json_message) if response.status_code != 200: logger.error( "Posting of Encrypted U to the Cloud Node failed with response code %d" % response.status_code) break else: logger.error( "TPM Quote from cloud node is invalid for nonce: %s" % self.nonce) break else: logger.error( "Status command response: %d Unexpected response from Cloud Node." % response.status_code) break break