def test_022_agent_quotes_identity_get(self): """Test agent's GET /v2/quotes/identity Interface""" global aik self.assertIsNotNone(aik, "Required value not set. Previous step may have failed?") nonce = TPM_Utilities.random_password(20) numretries = config.getint('tenant','max_retries') while numretries >= 0: response = tornado_requests.request( "GET", "http://%s:%s/v%s/quotes/identity?nonce=%s"%(tenant_templ.cloudagent_ip,tenant_templ.cloudagent_port,self.api_version,nonce) ) if response.status_code == 200: break numretries-=1 time.sleep(config.getint('tenant','max_retries')) self.assertEqual(response.status_code, 200, "Non-successful Agent 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.check_quote(nonce,response_body["results"]["pubkey"],response_body["results"]["quote"],aik), "Invalid quote!")
def do_verify(self): """initiaite v, agent_id and ip initiate the cloudinit sequence""" challenge = TPM_Utilities.random_password(20) numtries = 0 while True: try: response = tornado_requests.request( "GET", "http://%s:%s/keys/verify?challenge=%s" % (self.cloudagent_ip, self.cloudagent_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: raise UserError( "Quitting after max number of retries to connect to %s" % (self.cloudagent_ip)) retry = config.getfloat('tenant', 'retry_interval') logger.info( "Connection to %s refused %d/%d times, trying again in %f seconds..." % (self.cloudagent_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 Agent: %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: raise UserError("Key derivation failed") else: common.log_http_response(logger, logging.ERROR, response_body) retry = config.getfloat('tenant', 'retry_interval') raise UserError( "Key derivation not yet complete...trying again in %s seconds...Ctrl-C to stop" % retry) time.sleep(retry) continue break
def prepare_get_quote(agent): """This method encapsulates the action required to invoke a quote request on the Cloud Agent. This method is part of the polling loop of the thread launched on Tenant POST. """ agent['nonce'] = TPM_Utilities.random_password(20) params = { 'nonce': agent['nonce'], 'mask': agent['tpm_policy']['mask'], 'vmask': agent['vtpm_policy']['mask'], } return params
def test_041_agent_keys_verify_get(self): """Test agent's GET /v2/keys/verify Interface""" self.assertIsNotNone(self.K, "Required value not set. Previous step may have failed?") challenge = TPM_Utilities.random_password(20) response = tornado_requests.request( "GET", "http://%s:%s/v%s/keys/verify?challenge=%s"%(tenant_templ.cloudagent_ip,tenant_templ.cloudagent_port,self.api_version,challenge) ) self.assertEqual(response.status_code, 200, "Non-successful Agent 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, "Agent failed to validate challenge code!")
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_Utilities.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/v%s/quotes/integrity?nonce=%s&mask=%s&vmask=%s&partial=%s"%(tenant_templ.cloudagent_ip,tenant_templ.cloudagent_port,self.api_version,nonce,mask,vmask,partial) ) self.assertEqual(response.status_code, 200, "Non-successful Agent 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"] self.assertIn("tpm_version", response_body["results"], "Malformed response body!") self.assertIn("hash_alg", response_body["results"], "Malformed response body!") quote = response_body["results"]["quote"] tpm_version = response_body["results"]["tpm_version"] hash_alg = response_body["results"]["hash_alg"] validQuote = tpm.check_quote(nonce, public_key, quote, aik, self.tpm_policy, hash_alg=hash_alg) self.assertTrue(validQuote)
def do_quote(self): """initiaite v, agent_id and ip initiate the cloudinit sequence""" self.nonce = TPM_Utilities.random_password(20) numtries = 0 response = None while True: # Get quote try: response = tornado_requests.request( "GET", "http://%s:%s/quotes/identity?nonce=%s" % (self.cloudagent_ip, self.cloudagent_port, self.nonce)) 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: raise UserError( "Quitting after max number of retries to connect to %s" % (self.cloudagent_ip)) retry = config.getfloat('tenant', 'retry_interval') logger.info( "Connection to %s refused %d/%d times, trying again in %f seconds..." % (self.cloudagent_ip, numtries, maxr, retry)) time.sleep(retry) continue else: 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_code) response_body = response.json() if "results" not in response_body: raise UserError( "Error: unexpected http response body from Cloud Agent: %s" % str(response.status_code)) quote = response_body["results"]["quote"] logger.debug("agent_quote received quote:" + quote) public_key = response_body["results"]["pubkey"] logger.debug("agent_quote received public key:" + public_key) # Get tpm_version, hash_alg tpm_version = response_body["results"]["tpm_version"] logger.debug("agent_quote received tpm version:" + str(tpm_version)) # Ensure hash_alg is in accept_tpm_hash_algs list hash_alg = response_body["results"]["hash_alg"] logger.debug("agent_quote received hash algorithm:" + hash_alg) if not Hash_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:" + enc_alg) if not Encrypt_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:" + sign_alg) if not Sign_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, tpm_version, hash_alg): raise UserError( "TPM Quote from cloud agent is invalid for nonce: %s" % self.nonce) logger.info("Quote from %s validated" % self.cloudagent_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 CloudAgent response = tornado_requests.request( "POST", "http://%s:%s/keys/ukey" % (self.cloudagent_ip, self.cloudagent_port), data=u_json_message) if response.status_code != 200: common.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_code) except Exception as e: self.do_cvstop() raise e