Пример #1
0
    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!")
Пример #2
0
    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
Пример #3
0
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
Пример #4
0
    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!")
Пример #5
0
    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)
Пример #6
0
    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