def post_cfssl(url, data): numtries = 0 maxr = 10 retry = 0.05 while True: try: response = tornado_requests.request("POST", url, params=None, data=data, context=None) break except Exception as e: if tornado_requests.is_refused(e): numtries += 1 if numtries >= maxr: logger.error( "Quiting after max number of retries to connect to cfssl server" ) raise e logger.info( "Connection to cfssl refused %d/%d times, trying again in %f seconds..." % (numtries, maxr, retry)) time.sleep(retry) continue else: raise e return response
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 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
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