Beispiel #1
0
def doRegisterAgent(registrar_ip,registrar_port,agent_id,tpm_version,pub_ek,ekcert,pub_aik,pub_ek_tpm=None,aik_name=None):
    data = {
    'ek': pub_ek,
    'ekcert': ekcert,
    'aik': pub_aik,
    'aik_name': aik_name,
    'ek_tpm': pub_ek_tpm,
    'tpm_version': tpm_version,
    }
    v_json_message = json.dumps(data)
    params = '/agents/%s'% (agent_id)
    response = httpclient_requests.request("POST", "%s"%(registrar_ip), registrar_port, params=params, data=v_json_message, context=None)
    response_body = json.loads(response.read().decode("utf-8"))

    if response.status != 200:
        logger.error("Error: unexpected http response code from Registrar Server: " + str(response.status))
        keylime_logging.log_http_response(logger,logging.ERROR,response_body)
        return None

    logger.info("Agent registration requested for %s"%agent_id)

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

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

    return response_body["results"]["blob"]
Beispiel #2
0
    def do_cvdelete(self):
        params = f'/agents/{self.agent_uuid}'
        response = httpclient_requests.request("DELETE", "%s"%(self.cloudverifier_ip), self.cloudverifier_port, params=params,  context=self.context)

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

        if response.status == 202:
            deleted = False
            for _ in range(12):
                response = httpclient_requests.request("GET", "%s"%(self.cloudverifier_ip), self.cloudverifier_port, params=params, context=self.context)
                if response.status == 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")
                exit()
        elif response.status == 200:
            logger.info(f"Agent {self.agent_uuid} deleted from the CV")
        else:
            response_body = json.loads(response.read().decode())
            keylime_logging.log_http_response(logger,logging.ERROR,response_body)
Beispiel #3
0
    def do_cvreactivate(self):
        """ Reactive Agent
        """
        do_cvreactivate = RequestsClient(
            self.verifier_base_url, self.tls_enabled)
        response = do_cvreactivate.put(
            (f'/agents/{self.agent_uuid}/reactivate'),
            data=b'',
            cert=self.cert,
            verify=False
        )

        if response.status_code == 503:
            logger.error("Cannot connect to Verifier at %s with Port %s. Connection refused.", self.verifier_ip, self.verifier_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()

        response_body = response.json()

        if response.status_code != 200:
            keylime_logging.log_http_response(
                logger, logging.ERROR, response_body)
            logger.error("Update command response: %s Unexpected response from Cloud Verifier.", response.status_code)
        else:
            logger.info("Agent %s re-activated", self.agent_uuid)
Beispiel #4
0
def getKeys(registrar_ip,registrar_port,agent_id):
    global context

    #make absolutely sure you don't ask for AIKs unauthenticated
    if context is None or context.verify_mode != ssl.CERT_REQUIRED:
        raise Exception("It is unsafe to use this interface to query AIKs with out server authenticated TLS")

    try:
        params = '/agents/%s'% (agent_id)
        response = httpclient_requests.request("GET", "%s"%(registrar_ip), registrar_port, params=params, context=context)
        response_body = json.loads(response.read().decode())

        if response.status != 200:
            logger.critical("Error: unexpected http response code from Registrar Server: %s"%str(response.status))
            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))
            return None

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

        return response_body["results"]
    except Exception as e:
        logger.exception(e)

    return None
def doRegisterAgent(registrar_ip,
                    registrar_port,
                    agent_id,
                    tpm_version,
                    pub_ek,
                    ekcert,
                    pub_aik,
                    pub_ek_tpm=None,
                    aik_name=None):
    data = {
        'ek': pub_ek,
        'ekcert': ekcert,
        'aik': pub_aik,
        'aik_name': aik_name,
        'ek_tpm': pub_ek_tpm,
        'tpm_version': tpm_version,
    }
    response = None
    try:
        client = RequestsClient(f'{registrar_ip}:{registrar_port}',
                                tls_enabled)
        response = client.post(f'/agents/{agent_id}',
                               cert=tls_cert_info,
                               data=json.dumps(data),
                               verify=False)
        response_body = response.json()

        if response.status_code != 200:
            logger.error(
                f"Error: unexpected http response code from Registrar Server: {response.status_code}"
            )
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response_body)
            return None

        logger.info(f"Agent registration requested for {agent_id}")

        if "results" not in response_body:
            logger.critical(
                f"Error: unexpected http response body from Registrar Server: {response.status_code}"
            )
            return None

        if "blob" not in response_body["results"]:
            logger.critical(
                f"Error: did not receive blob from Registrar Server: {response.status_code}"
            )
            return None

        return response_body["results"]["blob"]
    except Exception as e:
        if response and response.status_code == 503:
            logger.error(
                f"Agent cannot establish connection to registrar at {registrar_ip}:{registrar_port}"
            )
            sys.exit()
        else:
            logger.exception(e)

    return None
Beispiel #6
0
    def do_cvstop(self):
        """ Stop declared active agent
        """
        params = f'/agents/{self.agent_uuid}/stop'
        do_cvstop = RequestsClient(self.verifier_base_url, self.tls_enabled)
        response = do_cvstop.put(
            params,
            cert=self.cert,
            data=b'',
            verify=False
        )

        if response.status_code == 503:
            logger.error("Cannot connect to Verifier at %s with Port %s. Connection refused.", self.verifier_ip, self.verifier_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()

        response_body = response.json()
        if response.status_code != 200:
            keylime_logging.log_http_response(
                logger, logging.ERROR, response_body)
        else:
            logger.info("Agent %s stopped", self.agent_uuid)
Beispiel #7
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"]
Beispiel #8
0
    def do_cvstop(self):
        # params = '/agents/%s/stop'% (self.agent_uuid)
        params = f'/agents/{self.agent_uuid}/stop'
        response = httpclient_requests.request("PUT",
                                               "%s" % (self.cloudverifier_ip),
                                               self.cloudverifier_port,
                                               params=params,
                                               data=b'',
                                               context=self.context)

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

        response_body = json.loads(response.read().decode())
        if response.status != 200:
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response_body)
        else:
            logger.info(f"Agent {self.agent_uuid} stopped")
Beispiel #9
0
    def do_cvreactivate(self):
        #params = '/agents/%s/reactivate'% (self.agent_uuid)
        params = f'/agents/{self.agent_uuid}/reactivate'
        response = httpclient_requests.request("PUT",
                                               "%s" % (self.cloudverifier_ip),
                                               self.cloudverifier_port,
                                               params=params,
                                               data=b'',
                                               context=self.context)

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

        response_body = json.loads(response.read().decode())
        if response.status != 200:
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response_body)
            raise UserError(
                "Update command response: %d Unexpected response from Cloud Verifier."
                % response.status)
        else:
            logger.info(f"Agent {self.agent_uuid} re-activated")
Beispiel #10
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
Beispiel #11
0
def doRegistrarDelete(registrar_ip,registrar_port, agent_id):
    global context
    params = '/agents/%s'% (agent_id)
    response = httpclient_requests.request("DELETE", "%s"%(registrar_ip), registrar_port, params=params,  context=None)
    response_body = json.loads(response)
    if response.status == 200:
        logger.debug("Registrar deleted.")
    else:
        logger.warn("Status command response: " + str(response.status) + " Unexpected response from registrar.")
        keylime_logging.log_http_response(logger,logging.WARNING,response_body)
Beispiel #12
0
def doRegistrarDelete(registrar_ip, registrar_port, agent_id):
    client = RequestsClient(f'{registrar_ip}:{registrar_port}', tls_enabled)
    response = client.delete(f'/v{api_version}/agents/{agent_id}', cert=tls_cert_info, verify=False)
    response_body = response.json()

    if response.status_code == 200:
        logger.debug("Registrar deleted.")
    else:
        logger.warning("Status command response: %s Unexpected response from registrar.", response.status_code)
        keylime_logging.log_http_response(logger, logging.WARNING, response_body)
Beispiel #13
0
    def do_cv(self):
        """initiaite v, agent_id and ip
        initiate the cloudinit sequence"""
        b64_v = base64.b64encode(self.V).decode('utf-8')
        logger.debug("b64_v:" + b64_v)
        data = {
            'v': b64_v,
            'cloudagent_ip': self.cv_cloudagent_ip,
            'cloudagent_port': self.cloudagent_port,
            'providerverifier_ip': self.providerverifier_ip,
            'providerverifier_port': self.providerverifier_port,
            'need_provider_quote': self.need_provider_quote,
            'tpm_policy': json.dumps(self.tpm_policy),
            'vtpm_policy': json.dumps(self.vtpm_policy),
            'ima_whitelist': json.dumps(self.ima_whitelist),
            'metadata': json.dumps(self.metadata),
            'revocation_key': self.revocation_key,
            'accept_tpm_hash_algs': self.accept_tpm_hash_algs,
            'accept_tpm_encryption_algs': self.accept_tpm_encryption_algs,
            'accept_tpm_signing_algs': self.accept_tpm_signing_algs,
        }
        json_message = json.dumps(data)
        params = f'/agents/{self.agent_uuid}'
        #params = '/agents/%s'% (self.agent_uuid)
        response = httpclient_requests.request("POST",
                                               "%s" % (self.cloudverifier_ip),
                                               self.cloudverifier_port,
                                               params=params,
                                               data=json_message,
                                               context=self.context)

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

        if response.status == 409:
            # this is a conflict, need to update or delete it
            logger.error(
                "Agent %s already existed at CV.  Please use delete or update."
                % self.agent_uuid)
            exit()
        elif response.status != 200:
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response.read().decode()())
            logger.error(
                f"POST command response: {response.status} Unexpected response from Cloud Verifier: {response.read().decode()}"
            )
            exit()
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
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
Beispiel #16
0
    def do_verify(self):
        challenge = TPM_Utilities.random_password(20)
        numtries = 0
        while True:
            try:
                params = f'/keys/verify?challenge={challenge}'
                response = httpclient_requests.request("GET",
                                                       "%s" %
                                                       (self.cloudagent_ip),
                                                       self.cloudagent_port,
                                                       params=params)
            except Exception as e:
                if response == 503 or 504:
                    numtries += 1
                    maxr = config.getint('tenant', 'max_retries')
                    if numtries >= maxr:
                        logger.error(
                            f"Cannot establish connection to agent on {self.cloudagent_ip} with port {self.cloudagent_port}"
                        )
                        exit()
                    retry = config.getfloat('tenant', 'retry_interval')
                    logger.info(
                        f"Verifier connection to agent at {self.cloudagent_ip} refused {numtries}/{maxr} times, trying again in {retry} seconds..."
                    )
                    time.sleep(retry)
                    continue
                else:
                    raise (e)
            response_body = json.loads(response.read().decode())
            if response.status == 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}"
                    )
                    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
def doRegisterAgent(registrar_ip, registrar_port, agent_id, ek_tpm, ekcert,
                    aik_tpm):
    data = {
        'ekcert': ekcert,
        'aik_tpm': aik_tpm,
    }
    if ekcert is None or ekcert == 'emulator':
        data['ek_tpm'] = ek_tpm
    response = None
    try:
        client = RequestsClient(f'{registrar_ip}:{registrar_port}',
                                tls_enabled)
        response = client.post(f'/agents/{agent_id}',
                               cert=tls_cert_info,
                               data=json.dumps(data),
                               verify=False)
        response_body = response.json()

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

        logger.info("Agent registration requested for %s", agent_id)

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

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

        return response_body["results"]["blob"]
    except Exception as e:
        if response and response.status_code == 503:
            logger.error(
                "Agent cannot establish connection to registrar at %s:%s",
                registrar_ip, registrar_port)
            sys.exit()
        else:
            logger.exception(e)

    return None
Beispiel #18
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
Beispiel #19
0
    def do_cv(self):
        """ Initiaite v, agent_id and ip and initiate the cloudinit sequence
        """
        b64_v = base64.b64encode(self.V).decode('utf-8')
        logger.debug("b64_v:" + b64_v)
        data = {
            'v': b64_v,
            'cloudagent_ip': self.cv_cloudagent_ip,
            'cloudagent_port': self.agent_port,
            'tpm_policy': json.dumps(self.tpm_policy),
            'vtpm_policy': json.dumps(self.vtpm_policy),
            'allowlist': json.dumps(self.allowlist),
            'metadata': json.dumps(self.metadata),
            'revocation_key': self.revocation_key,
            'accept_tpm_hash_algs': self.accept_tpm_hash_algs,
            'accept_tpm_encryption_algs': self.accept_tpm_encryption_algs,
            'accept_tpm_signing_algs': self.accept_tpm_signing_algs,
        }
        json_message = json.dumps(data)
        do_cv = RequestsClient(self.verifier_base_url, self.tls_enabled)
        response = do_cv.post((f'/agents/{self.agent_uuid}'),
                              data=json_message,
                              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 == 409:
            # this is a conflict, need to update or delete it
            logger.error(
                f"Agent {self.agent_uuid} already existed at CV.  Please use delete or update."
            )
            sys.exit()
        elif response.status_code != 200:
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response.json())
            logger.error(
                f"POST command response: {response.status} Unexpected response from Cloud Verifier: {response.read()}"
            )
            sys.exit()
Beispiel #20
0
def doActivateAgent(registrar_ip,registrar_port,agent_id,key):
    data = {
    'auth_tag': crypto.do_hmac(key,agent_id),
    }
    v_json_message = json.dumps(data)
    params = '/agents/%s/activate'% (agent_id)
    response = httpclient_requests.request("PUT", "%s"%(registrar_ip), registrar_port, params=params, data=v_json_message,  context=None)
    response_body = json.loads(response.read().decode())
    if response.status == 200:
        logger.info("Registration activated for agent %s."%agent_id)
        return True
    else:
        logger.error("Error: unexpected http response code from Registrar Server: " + str(response.status))
        keylime_logging.log_http_response(logger,logging.ERROR,response_body)
        return False
Beispiel #21
0
def doActivateVirtualAgent(registrar_ip, registrar_port, agent_id, deepquote):
    data = {'deepquote': deepquote}

    client = RequestsClient(f'{registrar_ip}:{registrar_port}', tls_enabled)
    response = client.put(f'/agents/{agent_id}/vactivate', cert=tls_cert_info, data=json.dumps(data), verify=False)
    response_body = response.json()

    if response.status_code == 200:
        logger.info("Registration activated for agent %s." % agent_id)
        return True

    logger.error(
        "Error: unexpected http response code from Registrar Server: " + str(response.status_code))
    keylime_logging.log_http_response(logger, logging.ERROR, response_body)
    return False
def doActivateAgent(registrar_ip, registrar_port, agent_id, key):
    data = {
        'auth_tag': crypto.do_hmac(key, agent_id),
    }
    client = RequestsClient(f'{registrar_ip}:{registrar_port}', tls_enabled)
    response = client.put(f'/v{api_version}/agents/{agent_id}/activate', cert=tls_cert_info, data=json.dumps(data), verify=False)
    response_body = response.json()

    if response.status_code == 200:
        logger.info("Registration activated for agent %s.", agent_id)
        return True

    logger.error(
        "Error: unexpected http response code from Registrar Server: %s", str(response.status_code))
    keylime_logging.log_http_response(logger, logging.ERROR, response_body)
    return False
Beispiel #23
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)
Beispiel #24
0
    async def get_agent_state(self, agent_id):
        try:
            res = tornado_requests.request(
                "GET",
                "http://%s:%s/agents/%s" %
                (tenant_templ.cloudverifier_ip,
                 tenant_templ.cloudverifier_port, agent_id),
                context=tenant_templ.context)
            response = await res

        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)
            common.echo_json_response(
                self, 500, "Unexpected response from Cloud Verifier", str(e))
            logger.error("Unexpected response from Cloud Verifier: ", str(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"
                % str(response.status_code))
            return None

        # Agent not added to CV (but still registered)
        if response.status_code == 404:
            return {
                "operational_state":
                cloud_verifier_common.CloudAgent_Operational_State.REGISTERED
            }
        else:
            return inst_response_body["results"]

        return None
Beispiel #25
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})
Beispiel #26
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})
Beispiel #27
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
        # 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)
                params = f'/quotes/identity?nonce={self.nonce}'
                response = httpclient_requests.request("GET",
                                                       "%s" %
                                                       (self.cloudagent_ip),
                                                       self.cloudagent_port,
                                                       params=params,
                                                       context=None)
                response_body = json.loads(response.read().decode())
            except Exception as e:
                if response == 503 or response == 504:
                    numtries += 1
                    maxr = config.getint('tenant', 'max_retries')
                    if numtries >= maxr:
                        logger.error(
                            f"tenant cannot establish connection to agent on {self.cloudagent_ip} with port {self.cloudagent_port}"
                        )
                        exit()
                    retry = config.getfloat('tenant', 'retry_interval')
                    logger.info(
                        f"tenant connection to agent at {self.cloudagent_ip} refused {numtries}/{maxr} times, trying again in {retry} seconds..."
                    )
                    time.sleep(retry)
                    continue
                else:
                    raise (e)
            break

        try:
            if response is not None and response.status != 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(f"agent_quote received quote: {quote}")

            public_key = response_body["results"]["pubkey"]
            logger.debug(f"agent_quote received public key: {public_key}")

            # Get tpm_version, hash_alg
            tpm_version = response_body["results"]["tpm_version"]
            logger.debug(
                f"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(f"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(
                f"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(f"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(f"Quote from {self.cloudagent_ip} validated")

            # encrypt U with the public key
            # encrypted_U = crypto.rsa_encrypt(crypto.rsa_import_pubkey(public_key),str(self.U))
            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: " + 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'
            response = httpclient_requests.request("POST",
                                                   "%s" % (self.cloudagent_ip),
                                                   self.cloudagent_port,
                                                   params=params,
                                                   data=u_json_message)

            if response == 503:
                logger.error(
                    f"Cannot connect to Agent at {self.cloudagent_ip} with Port {self.cloudagent_port}. Connection refused."
                )
                exit()
            elif response == 504:
                logger.error(
                    f"Verifier at {self.cloudverifier_ip} with Port {self.cloudverifier_port} timed out."
                )
                exit()

            if response.status != 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
Beispiel #28
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
Beispiel #29
0
def doRegisterAgent(registrar_ip,
                    registrar_port,
                    agent_id,
                    ek_tpm,
                    ekcert,
                    aik_tpm,
                    mtls_cert=None,
                    contact_ip=None,
                    contact_port=None):
    data = {
        "ekcert": ekcert,
        "aik_tpm": aik_tpm,
    }
    if ekcert is None or ekcert == "emulator":
        data["ek_tpm"] = ek_tpm

    if mtls_cert is not None:
        data["mtls_cert"] = mtls_cert
    else:
        logger.error(
            "Most actions require the agent to have mTLS enabled, but no cert was provided!"
        )
    if contact_ip is not None:
        data["ip"] = contact_ip
    if contact_port is not None:
        data["port"] = contact_port

    response = None
    try:
        client = RequestsClient(f"{registrar_ip}:{registrar_port}",
                                tls_enabled,
                                ignore_hostname=True)
        response = client.post(f"/v{api_version}/agents/{agent_id}",
                               cert=tls_cert_info,
                               data=json.dumps(data),
                               verify=ca_cert)
        response_body = response.json()

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

        logger.info("Agent registration requested for %s", agent_id)

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

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

        return response_body["results"]["blob"]
    except Exception as e:
        if response and response.status_code == 503:
            logger.error(
                "Agent cannot establish connection to registrar at %s:%s",
                registrar_ip, registrar_port)
            sys.exit()
        else:
            logger.exception(e)

    return None
Beispiel #30
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 = common.get_restful_params(self.request.uri)
        if rest_params is None:
            common.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()
                common.echo_json_response(self, 200, "Success",
                                          {'log': logValue[offset:]})
            return
        elif "agents" not in rest_params:
            # otherwise they must be looking for agent info
            common.echo_json_response(self, 400, "uri not supported")
            logger.warning('GET returning 400 response. uri not supported: ' +
                           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

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

        # If no agent ID, get list of all agents from Registrar
        try:
            res = tornado_requests.request(
                "GET",
                "http://%s:%s/agents/" %
                (tenant_templ.registrar_ip, tenant_templ.registrar_port),
                context=tenant_templ.context)
            response = await res

        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)
            common.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" %
                str(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 = {}
        states = cloud_verifier_common.CloudAgent_Operational_State.STR_MAPPINGS
        for state in 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 = [10, 9, 7, 3, 4, 5, 6, 2, 1, 8, 0]
        sorted_agents = []
        for state in print_order:
            for agent_id in sorted_by_state[state]:
                sorted_agents.append(agent_id)

        common.echo_json_response(self, 200, "Success",
                                  {'uuids': sorted_agents})