Ejemplo n.º 1
0
    async def get_agent_state(self, agent_id):
        try:
            get_agent_state = RequestsClient(verifier_base_url, tls_enabled)
            response = get_agent_state.get(
                (f'/agents/{agent_id}'),
                cert=cert,
                verify=False
            )

        except Exception as e:
            logger.error("Status command response: %s:%s Unexpected response from Cloud Verifier.",
                tenant_templ.cloudverifier_ip, tenant_templ.cloudverifier_port)
            logger.exception(e)
            config.echo_json_response(
                self, 500, "Unexpected response from Cloud Verifier", str(e))
            logger.error("Unexpected response from Cloud Verifier: %s", e)
            return

        inst_response_body = response.json()

        if response.status_code != 200 and response.status_code != 404:
            logger.error("Status command response: %d Unexpected response from Cloud Verifier.", response.status_code)
            keylime_logging.log_http_response(
                logger, logging.ERROR, inst_response_body)
            return None

        if "results" not in inst_response_body:
            logger.critical("Error: unexpected http response body from Cloud Verifier: %s", response.status_code)
            return None

        # Agent not added to CV (but still registered)
        if response.status_code == 404:
            return {"operational_state": states.REGISTERED}

        return inst_response_body["results"]
Ejemplo n.º 2
0
    def test_014_reg_agent_get(self):
        """Test registrar's GET /agents/{UUID} Interface"""
        test_014_reg_agent_get = RequestsClient(
            tenant_templ.registrar_base_tls_url, tls_enabled=True)
        response = test_014_reg_agent_get.get(
            f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}",
            cert=tenant_templ.cert,
            verify=False)

        self.assertEqual(response.status_code, 200,
                         "Non-successful Registrar agent return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("ek_tpm", json_response["results"],
                      "Malformed response body!")
        self.assertIn("aik_tpm", json_response["results"],
                      "Malformed response body!")
        self.assertIn("ekcert", json_response["results"],
                      "Malformed response body!")
        self.assertIn("mtls_cert", json_response["results"],
                      "Malformed response body!")
        self.assertIn("ip", json_response["results"],
                      "Malformed response body!")
        self.assertIn("port", json_response["results"],
                      "Malformed response body!")

        global aik_tpm
        global mtls_cert
        mtls_cert = json_response["results"]["mtls_cert"]
        aik_tpm = json_response["results"]["aik_tpm"]
Ejemplo n.º 3
0
    def test_020_agent_keys_pubkey_get(self):
        """Test agent's GET /keys/pubkey Interface"""

        # We want a real cloud agent to communicate with!
        launch_cloudagent()
        test_020_agent_keys_pubkey_get = RequestsClient(
            tenant_templ.agent_base_url,
            tls_enabled=True,
            ignore_hostname=True)
        response = test_020_agent_keys_pubkey_get.get(
            f"/v{self.api_version}/keys/pubkey",
            cert=tenant_templ.agent_cert,
            verify=False,  # TODO: use agent certificate
        )

        self.assertEqual(response.status_code, 200,
                         "Non-successful Agent pubkey return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("pubkey", json_response["results"],
                      "Malformed response body!")

        global public_key
        public_key = json_response["results"]["pubkey"]
        self.assertNotEqual(public_key, None, "Malformed response body!")
Ejemplo n.º 4
0
    def do_verify(self):
        """ Perform verify using a random generated challenge
        """
        challenge = TPM_Utilities.random_password(20)
        numtries = 0
        while True:
            try:
                cloudagent_base_url = (f'{self.agent_ip}:{self.agent_port}')
                do_verify = RequestsClient(cloudagent_base_url,
                                           tls_enabled=False)
                response = do_verify.get(
                    (f'/keys/verify?challenge={challenge}'),
                    cert=self.cert,
                    verify=False)
            except Exception as e:
                if response.status_code in (503, 504):
                    numtries += 1
                    maxr = config.getint('tenant', 'max_retries')
                    if numtries >= maxr:
                        logger.error(
                            f"Cannot establish connection to agent on {self.agent_ip} with port {self.agent_port}"
                        )
                        sys.exit()
                    retry = config.getfloat('tenant', 'retry_interval')
                    logger.info(
                        f"Verifier connection to agent at {self.agent_ip} refused {numtries}/{maxr} times, trying again in {retry} seconds..."
                    )
                    time.sleep(retry)
                    continue

                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(
                        f"Error: unexpected http response body from Cloud Agent: {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:
                keylime_logging.log_http_response(logger, logging.ERROR,
                                                  response_body)
                retry = config.getfloat('tenant', 'retry_interval')
                logger.warning(
                    f"Key derivation not yet complete...trying again in {retry} seconds...Ctrl-C to stop"
                )
                time.sleep(retry)
                continue
            break
Ejemplo n.º 5
0
def getData(registrar_ip, registrar_port, agent_id):
    # make absolutely sure you don't ask for data that contains AIK keys unauthenticated
    if not tls_enabled:
        raise Exception(
            "It is unsafe to use this interface to query AIKs without server-authenticated TLS.")

    response = None
    try:
        client = RequestsClient(f'{registrar_ip}:{registrar_port}', tls_enabled)
        response = client.get(f'/v{api_version}/agents/{agent_id}', cert=tls_cert_info, verify=False)
        response_body = response.json()

        if response.status_code != 200:
            logger.critical("Error: unexpected http response code from Registrar Server: %s", response.status_code)
            keylime_logging.log_http_response(logger, logging.CRITICAL, response_body)
            return None

        # Check for all values that are consumed by other parts of Keylime
        if "results" not in response_body:
            logger.critical("Error: unexpected http response body from Registrar Server: %s", response.status_code)
            return None

        if "aik_tpm" not in response_body["results"]:
            logger.critical("Error: did not receive AIK from Registrar Server.")
            return None

        if "regcount" not in response_body["results"]:
            logger.critical("Error: did not receive regcount from Registrar Server.")
            return None

        if "ek_tpm" not in response_body["results"]:
            logger.critical("Error: did not receive EK from Registrar Server.")
            return None

        if "ip" not in response_body["results"]:
            logger.critical("Error: did not receive IP from Registrar Server.")
            return None

        if "port" not in response_body["results"]:
            logger.critical("Error: did not receive port from Registrar Server.")
            return None

        return response_body["results"]

    except AttributeError as e:
        if response and response.status_code == 503:
            logger.critical("Error: the registrar is not available at %s:%s", registrar_ip, registrar_port)
        else:
            logger.exception(e)

    except Exception as e:
        logger.exception(e)

    return None
Ejemplo n.º 6
0
def doRegistrarList(registrar_ip, registrar_port):
    client = RequestsClient(f'{registrar_ip}:{registrar_port}', tls_enabled)
    response = client.get(f'/v{api_version}/agents/', cert=tls_cert_info, verify=False)
    response_body = response.json()

    if response.status_code != 200:
        logger.warning("Registrar returned: %s Unexpected response from registrar.", response.status_code)
        keylime_logging.log_http_response(logger, logging.WARNING, response_body)
        return None

    return response_body
Ejemplo n.º 7
0
    def test_040_agent_quotes_integrity_get(self):
        """Test agent's GET /quotes/integrity Interface"""
        global public_key

        self.assertIsNotNone(
            aik_tpm, "Required value not set.  Previous step may have failed?")

        nonce = tpm_abstract.TPM_Utilities.random_password(20)
        mask = self.tpm_policy["mask"]
        partial = "1"
        if public_key is None:
            partial = "0"

        test_040_agent_quotes_integrity_get = RequestsClient(
            tenant_templ.agent_base_url,
            tls_enabled=True,
            ignore_hostname=True)
        response = test_040_agent_quotes_integrity_get.get(
            f"/v{self.api_version}/quotes/integrity?nonce={nonce}&mask={mask}&partial={partial}",
            cert=tenant_templ.agent_cert,
            verify=False,  # TODO: use agent certificate
        )

        self.assertEqual(response.status_code, 200,
                         "Non-successful Agent Integrity Get return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("quote", json_response["results"],
                      "Malformed response body!")
        if public_key is None:
            self.assertIn("pubkey", json_response["results"],
                          "Malformed response body!")
            public_key = json_response["results"]["pubkey"]
        self.assertIn("hash_alg", json_response["results"],
                      "Malformed response body!")

        quote = json_response["results"]["quote"]
        hash_alg = algorithms.Hash(json_response["results"]["hash_alg"])

        agentAttestState = cloud_verifier_common.get_AgentAttestStates(
        ).get_by_agent_id(tenant_templ.agent_uuid)

        failure = tpm_instance.check_quote(agentAttestState,
                                           nonce,
                                           public_key,
                                           quote,
                                           aik_tpm,
                                           self.tpm_policy,
                                           hash_alg=hash_alg)
        self.assertTrue(not failure)
Ejemplo n.º 8
0
    def test_060_cv_version_get(self):
        """Test CV's GET /version Interface"""
        cv_client = RequestsClient(tenant_templ.verifier_base_url, tls_enabled)
        response = cv_client.get("/version", cert=tenant_templ.cert, verify=False)

        self.assertEqual(response.status_code, 200, "Non-successful CV allowlist Post return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        results = json_response["results"]
        self.assertEqual(results["current_version"], api_version.current_version())
        self.assertEqual(results["supported_versions"], api_version.all_versions())
Ejemplo n.º 9
0
def getKeys(registrar_ip, registrar_port, agent_id):

    # make absolutely sure you don't ask for AIKs unauthenticated
    if not tls_enabled:
        raise Exception(
            "It is unsafe to use this interface to query AIKs without server-authenticated TLS."
        )

    response = None
    try:
        client = RequestsClient(f'{registrar_ip}:{registrar_port}',
                                tls_enabled)
        response = client.get(f'/agents/{agent_id}',
                              cert=tls_cert_info,
                              verify=False)
        response_body = response.json()

        if response.status_code != 200:
            logger.critical(
                "Error: unexpected http response code from Registrar Server: %s"
                % str(response.status_code))
            keylime_logging.log_http_response(logger, logging.CRITICAL,
                                              response_body)
            return None

        if "results" not in response_body:
            logger.critical(
                "Error: unexpected http response body from Registrar Server: %s"
                % str(response.status_code))
            return None

        if "aik" not in response_body["results"]:
            logger.critical(
                "Error: did not receive AIK from Registrar Server: %s" %
                str(response.status_code))
            return None

        return response_body["results"]

    except AttributeError as e:
        if response and response.status_code == 503:
            logger.critical("Error: the registrar is not available at %s:%s" %
                            (registrar_ip, registrar_port))
        else:
            logger.exception(e)

    except Exception as e:
        logger.exception(e)

    return None
Ejemplo n.º 10
0
    def test_013_reg_agents_get(self):
        """Test registrar's GET /agents Interface"""
        test_013_reg_agents_get = RequestsClient(tenant_templ.registrar_base_tls_url, tls_enabled=True)
        response = test_013_reg_agents_get.get(f"/v{self.api_version}/agents/", cert=tenant_templ.cert, verify=False)

        self.assertEqual(response.status_code, 200, "Non-successful Registrar agent List return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("uuids", json_response["results"], "Malformed response body!")

        # We registered exactly one agent so far
        self.assertEqual(1, len(json_response["results"]["uuids"]), "Incorrect system state!")
Ejemplo n.º 11
0
    def test_032_cv_agents_get(self):
        """Test CV's GET /agents Interface"""
        test_032_cv_agents_get = RequestsClient(tenant_templ.verifier_base_url, tls_enabled)
        response = test_032_cv_agents_get.get(f"/v{self.api_version}/agents/", cert=tenant_templ.cert, verify=False)

        self.assertEqual(response.status_code, 200, "Non-successful CV agent List return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("uuids", json_response["results"], "Malformed response body!")

        # Be sure our agent is registered
        self.assertEqual(1, len(json_response["results"]["uuids"]))
Ejemplo n.º 12
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_abstract.TPM_Utilities.random_password(20)
        mask = self.tpm_policy["mask"]
        vmask = self.vtpm_policy["mask"]
        partial = "1"
        if public_key is None:
            partial = "0"

        test_040_agent_quotes_integrity_get = RequestsClient(
            tenant_templ.agent_base_url, tls_enabled=False)
        response = test_040_agent_quotes_integrity_get.get(
            f'/v{self.api_version}/quotes/integrity?nonce={nonce}&mask={mask}&vmask={vmask}&partial={partial}',
            cert="",
            verify=False)

        self.assertEqual(response.status_code, 200,
                         "Non-successful Agent Integrity Get return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("quote", json_response["results"],
                      "Malformed response body!")
        if public_key is None:
            self.assertIn("pubkey", json_response["results"],
                          "Malformed response body!")
            public_key = json_response["results"]["pubkey"]
        self.assertIn("tpm_version", json_response["results"],
                      "Malformed response body!")
        self.assertIn("hash_alg", json_response["results"],
                      "Malformed response body!")

        quote = json_response["results"]["quote"]
        hash_alg = json_response["results"]["hash_alg"]

        validQuote = tpm.check_quote(tenant_templ.agent_uuid,
                                     nonce,
                                     public_key,
                                     quote,
                                     aik,
                                     self.tpm_policy,
                                     hash_alg=hash_alg)
        self.assertTrue(validQuote)
Ejemplo n.º 13
0
    def test_022_agent_quotes_identity_get(self):
        """Test agent's GET /quotes/identity Interface"""
        self.assertIsNotNone(
            aik_tpm, "Required value not set.  Previous step may have failed?")

        nonce = tpm_abstract.TPM_Utilities.random_password(20)

        numretries = config.getint("tenant", "max_retries")
        while numretries >= 0:
            test_022_agent_quotes_identity_get = RequestsClient(
                tenant_templ.agent_base_url,
                tls_enabled=True,
                ignore_hostname=True)
            response = test_022_agent_quotes_identity_get.get(
                f"/v{self.api_version}/quotes/identity?nonce={nonce}",
                data=None,
                cert=tenant_templ.agent_cert,
                verify=False,  # TODO: use agent certificate
            )

            if response.status_code == 200:
                break
            numretries -= 1
            time.sleep(config.getint("tenant", "retry_interval"))
        self.assertEqual(response.status_code, 200,
                         "Non-successful Agent identity return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("quote", json_response["results"],
                      "Malformed response body!")
        self.assertIn("pubkey", json_response["results"],
                      "Malformed response body!")

        agentAttestState = cloud_verifier_common.get_AgentAttestStates(
        ).get_by_agent_id(tenant_templ.agent_uuid)

        # Check the quote identity
        failure = tpm_instance.check_quote(
            agentAttestState,
            nonce,
            json_response["results"]["pubkey"],
            json_response["results"]["quote"],
            aik_tpm,
            hash_alg=algorithms.Hash(json_response["results"]["hash_alg"]),
        )
        self.assertTrue(not failure, "Invalid quote!")
Ejemplo n.º 14
0
    def do_cvstatus(self, listing=False):
        """ Perform opertional state look up for agent

        Keyword Arguments:
            listing {bool} -- If True, list all agent statues (default: {False})
        """
        agent_uuid = ""
        if not listing:
            agent_uuid = self.agent_uuid

        do_cvstatus = RequestsClient(self.verifier_base_url, self.tls_enabled)
        response = do_cvstatus.get((f'/agents/{agent_uuid}'),
                                   cert=self.cert,
                                   verify=False)

        if response.status_code == 503:
            logger.error(
                f"Cannot connect to Verifier at {self.verifier_ip} with Port {self.verifier_port}. Connection refused."
            )
            sys.exit()
        elif response == 504:
            logger.error(
                f"Verifier at {self.verifier_ip} with Port {self.verifier_port} timed out."
            )
            sys.exit()

        if response.status_code == 404:
            logger.error(
                f"Agent {agent_uuid} does not exist on the verifier. Please try to add or update agent"
            )
            sys.exit()

        if response.status_code != 200:
            logger.error(
                f"Status command response: {response.status_code}. Unexpected response from Cloud Verifier."
            )
            sys.exit()
        else:
            response_json = response.json()
            if not listing:
                operational_state = response_json["results"][
                    "operational_state"]
                logger.info(
                    f'Agent Status: "{states.state_to_str(operational_state)}"'
                )
            else:
                agent_array = response_json["results"]["uuids"]
                logger.info(f'Agents: "{agent_array}"')
Ejemplo n.º 15
0
    def test_026_cv_allowlist_get(self):
        """Test CV's GET /allowlists/{name} Interface"""
        cv_client = RequestsClient(tenant_templ.verifier_base_url, tls_enabled)
        response = cv_client.get(
            f"/v{self.api_version}/allowlists/test-allowlist", cert=tenant_templ.cert, verify=False
        )

        self.assertEqual(response.status_code, 200, "Non-successful CV allowlist Post return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        results = json_response["results"]
        self.assertEqual(results["name"], "test-allowlist")
        self.assertEqual(results["tpm_policy"], json.dumps(self.tpm_policy))
        self.assertEqual(results["ima_policy"], json.dumps(self.allowlist))
Ejemplo n.º 16
0
    def do_cvdelete(self):
        """Delete agent from Verifier
        """
        do_cvdelete = RequestsClient(self.verifier_base_url, self.tls_enabled)
        response = do_cvdelete.delete(
            (f'/agents/{self.agent_uuid}'),
            cert=self.cert,
            verify=False
        )

        if response.status_code == 503:
            logger.error(
                f"Cannot connect to Verifier at {self.verifier_ip} with Port {self.verifier_port}. Connection refused.")
            sys.exit()
        elif response.status_code == 504:
            logger.error(
                f"Verifier at {self.verifier_ip} with Port {self.verifier_port} timed out.")
            sys.exit()

        if response.status_code == 202:
            deleted = False
            for _ in range(12):
                get_cvdelete = RequestsClient(
                    self.verifier_base_url, self.tls_enabled)
                response = get_cvdelete.get(
                    (f'/agents/{self.agent_uuid}'),
                    cert=self.cert,
                    verify=False
                )

                if response.status_code in (200, 404):
                    deleted = True
                    break
                time.sleep(.4)
            if deleted:
                logger.info(
                    f"CV completed deletion of agent {self.agent_uuid}")
            else:
                logger.error(
                    f"Timed out waiting for delete of agent {self.agent_uuid} to complete at CV")
                sys.exit()
        elif response.status_code == 200:
            logger.info(f"Agent {self.agent_uuid} deleted from the CV")
        else:
            response_body = response.json()
            keylime_logging.log_http_response(
                logger, logging.ERROR, response_body)
Ejemplo n.º 17
0
    def test_033_cv_agent_get(self):
        """Test CV's GET /agents/{UUID} Interface"""
        test_033_cv_agent_get = RequestsClient(tenant_templ.verifier_base_url, tls_enabled)
        response = test_033_cv_agent_get.get(
            f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}", cert=tenant_templ.cert, verify=False
        )

        self.assertEqual(response.status_code, 200, "Non-successful CV agent return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")

        # Check a few of the important properties are present
        self.assertIn("operational_state", json_response["results"], "Malformed response body!")
        self.assertIn("ip", json_response["results"], "Malformed response body!")
        self.assertIn("port", json_response["results"], "Malformed response body!")
Ejemplo n.º 18
0
def get_openstack_uuid(
        uuid_service_ip='169.254.169.254',
        uuid_service_resource='/openstack/2012-08-10/meta_data.json'):

    logger.debug("Getting instance UUID from openstack http://%s%s" %
                 (uuid_service_ip, uuid_service_resource))
    try:
        client = RequestsClient(uuid_service_ip, False)
        response = client.get(uuid_service_resource)
        if response.status_code == 200:
            response_body = response.json()
            return response_body["uuid"]
        logger.debug("Forcing using locally generated uuid.")
        return str(uuid.uuid4())
    except Exception as e:
        logger.debug(
            "Using locally generated uuid.  Error getting UUID from openstack: %s\n"
            % (e))
        return str(uuid.uuid4())
Ejemplo n.º 19
0
    def test_022_agent_quotes_identity_get(self):
        """Test agent's GET /quotes/identity Interface"""
        self.assertIsNotNone(
            aik_tpm, "Required value not set.  Previous step may have failed?")

        nonce = tpm_abstract.TPM_Utilities.random_password(20)

        numretries = config.getint('tenant', 'max_retries')
        while numretries >= 0:
            test_022_agent_quotes_identity_get = RequestsClient(
                tenant_templ.agent_base_url, tls_enabled=False)
            response = test_022_agent_quotes_identity_get.get(
                f'/v{self.api_version}/quotes/identity?nonce={nonce}',
                data=None,
                cert="",
                verify=False)

            if response.status_code == 200:
                break
            numretries -= 1
            time.sleep(config.getint('tenant', 'retry_interval'))
        self.assertEqual(response.status_code, 200,
                         "Non-successful Agent identity return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("quote", json_response["results"],
                      "Malformed response body!")
        self.assertIn("pubkey", json_response["results"],
                      "Malformed response body!")

        # Check the quote identity
        self.assertTrue(
            tpm_instance.check_quote(
                tenant_templ.agent_uuid,
                nonce,
                json_response["results"]["pubkey"],
                json_response["results"]["quote"],
                aik_tpm,
                hash_alg=json_response["results"]["hash_alg"]),
            "Invalid quote!")
Ejemplo n.º 20
0
    async def get(self):
        """This method handles the GET requests to retrieve status on agents from the WebApp.

        Currently, only the web app is available for GETing, i.e. /agents. All other GET uri's
        will return errors.
        """

        rest_params = config.get_restful_params(self.request.uri)
        if rest_params is None:
            config.echo_json_response(
                self, 405, "Not Implemented: Use /agents/ or /logs/ interface")
            return

        if "logs" in rest_params and rest_params["logs"] == "tenant":
            offset = 0
            if "pos" in rest_params and rest_params[
                    "pos"] is not None and rest_params["pos"].isdigit():
                offset = int(rest_params["pos"])
            # intercept requests for logs
            with open(keylime_logging.LOGSTREAM, 'r') as f:
                logValue = f.readlines()
                config.echo_json_response(self, 200, "Success",
                                          {'log': logValue[offset:]})
            return
        if "agents" not in rest_params:
            # otherwise they must be looking for agent info
            config.echo_json_response(self, 400, "uri not supported")
            logger.warning('GET returning 400 response. uri not supported: %s',
                           self.request.path)
            return

        agent_id = rest_params["agents"]
        if agent_id is not None:
            # Handle request for specific agent data separately
            agents = await self.get_agent_state(agent_id)
            agents["id"] = agent_id

            config.echo_json_response(self, 200, "Success", agents)
            return

        # If no agent ID, get list of all agents from Registrar
        try:
            get_agents = RequestsClient(registrar_base_tls_url, tls_enabled)
            response = get_agents.get(('/agents/'), cert=cert, verify=False)

        except Exception as e:
            logger.error(
                "Status command response: %s:%s Unexpected response from Registrar.",
                tenant_templ.registrar_ip, tenant_templ.registrar_port)
            logger.exception(e)
            config.echo_json_response(self, 500,
                                      "Unexpected response from Registrar",
                                      str(e))
            return

        response_body = response.json()

        if response.status_code != 200:
            logger.error(
                "Status command response: %d Unexpected response from Registrar.",
                response.status_code)
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response_body)
            return None

        if ("results"
                not in response_body) or ("uuids"
                                          not in response_body["results"]):
            logger.critical(
                "Error: unexpected http response body from Registrar: %s",
                response.status_code)
            return None

        agent_list = response_body["results"]["uuids"]

        # Loop through each agent and ask for status
        agents = {}
        for agent in agent_list:
            agents[agent] = await self.get_agent_state(agent_id)

        # Pre-create sorted agents list
        sorted_by_state = {}
        for state in states.VALID_STATES:
            sorted_by_state[state] = {}

        # Build sorted agents list
        for agent_id in agents:
            state = agents[agent_id]["operational_state"]
            sorted_by_state[state][agent_id] = agents[agent_id]

        print_order = [
            states.TENANT_FAILED, states.INVALID_QUOTE, states.FAILED,
            states.GET_QUOTE, states.GET_QUOTE_RETRY, states.PROVIDE_V,
            states.PROVIDE_V_RETRY, states.SAVED, states.START,
            states.TERMINATED, states.REGISTERED
        ]
        sorted_agents = []
        for state in print_order:
            for agent_id in sorted_by_state[state]:
                sorted_agents.append(agent_id)

        config.echo_json_response(self, 200, "Success",
                                  {'uuids': sorted_agents})
Ejemplo n.º 21
0
    async def get(self):
        """This method handles the GET requests to retrieve status on agents from the WebApp.

        Currently, only the web app is available for GETing, i.e. /agents. All other GET uri's
        will return errors.
        """

        rest_params = config.get_restful_params(self.request.uri)
        if rest_params is None:
            config.echo_json_response(
                self, 405, "Not Implemented: Use /agents/ or /logs/ interface")
            return

        if "logs" in rest_params and rest_params["logs"] == "tenant":
            offset = 0
            if "pos" in rest_params and rest_params["pos"] is not None and rest_params["pos"].isdigit():
                offset = int(rest_params["pos"])
            # intercept requests for logs
            with open(keylime_logging.LOGSTREAM, 'r') as f:
                logValue = f.readlines()
                config.echo_json_response(self, 200, "Success", {
                                          'log': logValue[offset:]})
            return
        if "agents" not in rest_params:
            # otherwise they must be looking for agent info
            config.echo_json_response(self, 400, "uri not supported")
            logger.warning('GET returning 400 response. uri not supported: %s', self.request.path)
            return

        agent_id = rest_params["agents"]
        if agent_id is not None:
            # Handle request for specific agent data separately
            agents = await self.get_agent_state(agent_id)
            agents["id"] = agent_id

            config.echo_json_response(self, 200, "Success", agents)
            return

        # If no agent ID, get list of all agents from Registrar
        try:
            get_agents = RequestsClient(registrar_base_tls_url, tls_enabled)
            response = get_agents.get(
                ('/agents/'),
                cert=cert,
                verify=False
            )

        except Exception as e:
            logger.error("Status command response: %s:%s Unexpected response from Registrar.",
                tenant_templ.registrar_ip, tenant_templ.registrar_port)
            logger.exception(e)
            config.echo_json_response(
                self, 500, "Unexpected response from Registrar", str(e))
            return

        response_body = response.json()

        if response.status_code != 200:
            logger.error("Status command response: %d Unexpected response from Registrar.", response.status_code)
            keylime_logging.log_http_response(
                logger, logging.ERROR, response_body)
            return None

        if ("results" not in response_body) or ("uuids" not in response_body["results"]):
            logger.critical("Error: unexpected http response body from Registrar: %s", response.status_code)
            return None

        agent_list = response_body["results"]["uuids"]

        config.echo_json_response(self, 200, "Success", {
                                  'uuids': agent_list})
Ejemplo n.º 22
0
 def do_show_allowlist(self, name):
     cv_client = RequestsClient(self.verifier_base_url, self.tls_enabled)
     response = cv_client.get(f'/allowlists/{name}',
                              cert=self.cert, verify=False)
     print(f"Show allowlist command response: {response.status_code}.")
     print(response.json())
Ejemplo n.º 23
0
    def do_quote(self):
        """ Perform TPM quote by GET towards Agent

        Raises:
            UserError: Connection handler
        """
        self.nonce = TPM_Utilities.random_password(20)

        numtries = 0
        response = None
        # Note: We need a specific retry handler (perhaps in common), no point having localised unless we have too.
        while True:
            try:
                params = '/quotes/identity?nonce=%s' % (self.nonce)
                cloudagent_base_url = f'{self.agent_ip}:{self.agent_port}'
                do_quote = RequestsClient(cloudagent_base_url, tls_enabled=False)
                response = do_quote.get(
                    params,
                    cert=self.cert
                )
                response_body = response.json()

            except Exception as e:
                if response.status_code in (503, 504):
                    numtries += 1
                    maxr = config.getint('tenant', 'max_retries')
                    if numtries >= maxr:
                        logger.error("Tenant cannot establish connection to agent on %s with port %s", self.agent_ip, self.agent_port)
                        sys.exit()
                    retry = config.getfloat('tenant', 'retry_interval')
                    logger.info("Tenant connection to agent at %s refused %s/%s times, trying again in %s seconds...",
                        self.agent_ip, numtries, maxr, retry)
                    time.sleep(retry)
                    continue

                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)

            if "results" not in response_body:
                raise UserError(
                    "Error: unexpected http response body from Cloud Agent: %s" % str(response.status))

            quote = response_body["results"]["quote"]
            logger.debug("Agent_quote received quote: %s", quote)

            public_key = response_body["results"]["pubkey"]
            logger.debug("Agent_quote received public key: %s", public_key)

            # Ensure hash_alg is in accept_tpm_hash_algs list
            hash_alg = response_body["results"]["hash_alg"]
            logger.debug("Agent_quote received hash algorithm: %s", hash_alg)
            if not 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: %s", enc_alg)
            if not 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: %s", sign_alg)
            if not 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, hash_alg):
                raise UserError(
                    "TPM Quote from cloud agent is invalid for nonce: %s" % self.nonce)

            logger.info("Quote from %s validated", self.agent_ip)

            # encrypt U with the public key
            encrypted_U = crypto.rsa_encrypt(
                crypto.rsa_import_pubkey(public_key), self.U)

            b64_encrypted_u = base64.b64encode(encrypted_U)
            logger.debug("b64_encrypted_u: %s", b64_encrypted_u.decode('utf-8'))
            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
            params = '/keys/ukey'
            cloudagent_base_url = (
                f'{self.agent_ip}:{self.agent_port}'
            )

            post_ukey = RequestsClient(cloudagent_base_url, tls_enabled=False)
            response = post_ukey.post(
                params,
                data=u_json_message
            )

            if response.status_code == 503:
                logger.error("Cannot connect to Agent at %s with Port %s. Connection refused.", self.agent_ip, self.agent_port)
                sys.exit()
            elif response.status_code == 504:
                logger.error("Verifier at %s with Port %s timed out.", self.verifier_ip, self.verifier_port)
                sys.exit()

            if response.status_code != 200:
                keylime_logging.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)
        except Exception as e:
            self.do_cvstop()
            raise e