Пример #1
0
    def setUpClass(cls):
        """Prepare the keys and payload to give to the CV"""
        contents = "random garbage to test as payload"
        # contents = contents.encode('utf-8')
        ret = user_data_encrypt.encrypt(contents)
        cls.K = ret["k"]
        cls.U = ret["u"]
        cls.V = ret["v"]
        cls.payload = ret["ciphertext"]

        # Set up to register an agent
        cls.auth_tag = crypto.do_hmac(cls.K, tenant_templ.agent_uuid)

        # Prepare policies for agent
        cls.tpm_policy = config.get("tenant", "tpm_policy")
        cls.tpm_policy = tpm_abstract.TPM_Utilities.readPolicy(cls.tpm_policy)

        # Allow targeting a specific API version (default latest)
        cls.api_version = "2.0"

        # Set up allowlist bundles. Use invalid exclusion list regex for bad bundle.
        cls.ima_policy_bundle = ima.read_allowlist()
        cls.ima_policy_bundle["excllist"] = base64.b64encode(
            json.dumps([]).encode()).decode()

        cls.bad_ima_policy_bundle = ima.read_allowlist()
        cls.bad_ima_policy_bundle["excllist"] = base64.b64encode(
            json.dumps(["*"]).encode()).decode()
Пример #2
0
    def test_030_cv_agent_post(self):
        """Test CV's POST /agents/{UUID} Interface"""
        self.assertIsNotNone(
            self.V, "Required value not set.  Previous step may have failed?")

        b64_v = base64.b64encode(self.V)
        data = {
            "v":
            b64_v,
            "cloudagent_ip":
            tenant_templ.cloudagent_ip,
            "cloudagent_port":
            tenant_templ.cloudagent_port,
            "tpm_policy":
            json.dumps(self.tpm_policy),
            "ima_policy_bundle":
            json.dumps(self.ima_policy_bundle),
            "ima_sign_verification_keys":
            "",
            "mb_refstate":
            None,
            "metadata":
            json.dumps(self.metadata),
            "revocation_key":
            self.revocation_key,
            "accept_tpm_hash_algs":
            config.get("tenant", "accept_tpm_hash_algs").split(","),
            "accept_tpm_encryption_algs":
            config.get("tenant", "accept_tpm_encryption_algs").split(","),
            "accept_tpm_signing_algs":
            config.get("tenant", "accept_tpm_signing_algs").split(","),
            "supported_version":
            tenant_templ.supported_version,
            "ak_tpm":
            aik_tpm,
            "mtls_cert":
            mtls_cert,
        }

        test_030_cv_agent_post = RequestsClient(tenant_templ.verifier_base_url,
                                                tls_enabled)
        response = test_030_cv_agent_post.post(
            f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}",
            data=json.dumps(data),
            cert=tenant_templ.cert,
            verify=False,
        )

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

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

        time.sleep(10)
Пример #3
0
    def test_030_cv_agent_post(self):
        """Test CV's POST /agents/{UUID} Interface"""
        self.assertIsNotNone(
            self.V, "Required value not set.  Previous step may have failed?")

        b64_v = base64.b64encode(self.V)
        data = {
            'v':
            b64_v,
            'cloudagent_ip':
            tenant_templ.cloudagent_ip,
            'cloudagent_port':
            tenant_templ.cloudagent_port,
            'tpm_policy':
            json.dumps(self.tpm_policy),
            'vtpm_policy':
            json.dumps(self.vtpm_policy),
            'allowlist':
            json.dumps(self.allowlist),
            'ima_sign_verification_keys':
            '',
            'mb_refstate':
            None,
            'metadata':
            json.dumps(self.metadata),
            'revocation_key':
            self.revocation_key,
            'accept_tpm_hash_algs':
            config.get('tenant', 'accept_tpm_hash_algs').split(','),
            'accept_tpm_encryption_algs':
            config.get('tenant', 'accept_tpm_encryption_algs').split(','),
            'accept_tpm_signing_algs':
            config.get('tenant', 'accept_tpm_signing_algs').split(','),
            'supported_version':
            tenant_templ.supported_version
        }

        test_030_cv_agent_post = RequestsClient(tenant_templ.verifier_base_url,
                                                tls_enabled)
        response = test_030_cv_agent_post.post(
            f'/v{self.api_version}/agents/{tenant_templ.agent_uuid}',
            data=json.dumps(data),
            cert=tenant_templ.cert,
            verify=False)

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

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

        time.sleep(10)
Пример #4
0
def prepare_error(agent, msgtype="revocation", event=None):
    # prepare the revocation message:
    revocation = {
        "type": msgtype,
        "ip": agent["ip"],
        "agent_id": agent["agent_id"],
        "port": agent["port"],
        "tpm_policy": agent["tpm_policy"],
        "meta_data": agent["meta_data"],
        "event_time": time.asctime(),
    }
    if event:
        revocation["event_id"] = event.event_id
        revocation["severity_label"] = event.severity_label.name
        revocation["context"] = event.context

    tosend = {"msg": json.dumps(revocation).encode("utf-8")}

    # also need to load up private key for signing revocations
    if agent["revocation_key"] != "":
        signing_key = crypto.rsa_import_privkey(agent["revocation_key"])
        tosend["signature"] = crypto.rsa_sign(signing_key, tosend["msg"])

    else:
        tosend["signature"] = "none"
    return tosend
Пример #5
0
    def test_024_agent_keys_ukey_post(self):
        """Test agents's POST /keys/ukey Interface"""

        self.assertIsNotNone(public_key, "Required value not set.  Previous step may have failed?")
        self.assertIsNotNone(self.U, "Required value not set.  Previous step may have failed?")
        self.assertIsNotNone(self.auth_tag, "Required value not set.  Previous step may have failed?")
        self.assertIsNotNone(self.payload, "Required value not set.  Previous step may have failed?")

        encrypted_U = crypto.rsa_encrypt(crypto.rsa_import_pubkey(public_key), self.U)
        b64_encrypted_u = base64.b64encode(encrypted_U)
        data = {"encrypted_key": b64_encrypted_u, "auth_tag": self.auth_tag, "payload": self.payload}

        test_024_agent_keys_ukey_post = RequestsClient(
            tenant_templ.agent_base_url, tls_enabled=True, ignore_hostname=True
        )
        response = test_024_agent_keys_ukey_post.post(
            f"/v{self.api_version}/keys/ukey",
            data=json.dumps(data),
            cert=tenant_templ.agent_cert,
            verify=False,  # TODO: use agent certificate
        )

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

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
Пример #6
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))
Пример #7
0
    def test_011_reg_agent_activate_put(self):
        """Test registrar's PUT /agents/{UUID}/activate Interface"""

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

        key = tpm_instance.activate_identity(keyblob)
        data = {
            "auth_tag": crypto.do_hmac(key, tenant_templ.agent_uuid),
        }
        test_011_reg_agent_activate_put = RequestsClient(
            tenant_templ.registrar_base_url, tls_enabled=False)
        response = test_011_reg_agent_activate_put.put(
            f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}/activate",
            data=json.dumps(data),
            cert="",
            verify=False,
        )

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

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
Пример #8
0
    def test_023_agent_keys_vkey_post(self):
        """Test agent's POST /keys/vkey Interface"""
        # CV should do this (during CV POST/PUT test)
        # Running this test might hide problems with the CV sending the V key

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

        encrypted_V = crypto.rsa_encrypt(crypto.rsa_import_pubkey(public_key),
                                         str(self.V))
        b64_encrypted_V = base64.b64encode(encrypted_V)
        data = {"encrypted_key": b64_encrypted_V}

        test_023_agent_keys_vkey_post = RequestsClient(
            tenant_templ.agent_base_url, tls_enabled=False)
        response = test_023_agent_keys_vkey_post.post(
            f"/v{self.api_version}/keys/vkey",
            data=json.dumps(data),
            cert="",
            verify=False)

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

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
Пример #9
0
def echo_json_response(handler, code, status=None, results=None):
    """Takes a json package and returns it to the user w/ full HTTP headers"""
    if handler is None or code is None:
        return False
    if status is None:
        status = http.client.responses[code]
    if results is None:
        results = {}

    json_res = {"code": code, "status": status, "results": results}
    json_response = json.dumps(json_res)
    json_response = json_response.encode("utf-8")

    if isinstance(handler, BaseHTTPRequestHandler):
        handler.send_response(code)
        handler.send_header("Content-Type", "application/json")
        handler.end_headers()
        handler.wfile.write(json_response)
        return True
    if isinstance(handler, tornado.web.RequestHandler):
        handler.set_status(code)
        handler.set_header("Content-Type", "application/json")
        handler.write(json_response)
        handler.finish()
        return True

    return False
Пример #10
0
def add_vtpm_group(rsa_mod=None):
    """ Add new vtpm group"""
    fprt = "add_vtpm_group"
    if config.STUB_TPM and config.TPM_CANNED_VALUES is not None:
        # Use canned values for stubbing
        jsonIn = config.TPM_CANNED_VALUES
        if fprt in jsonIn:
            # The value we're looking for has been canned!
            thisTiming = jsonIn[fprt]['timing']
            thisRetout = jsonIn[fprt]['retout']
            logger.debug(
                "TPM call '{}' was stubbed out, with a simulated delay of {:f} sec"
                .format(fprt, thisTiming))
            time.sleep(thisTiming)
            return tuple(thisRetout)

        # Our command hasn't been canned!
        raise Exception("Command %s not found in canned JSON!" % (fprt))

    logger.debug('Adding group')

    t0 = time.time()

    if rsa_mod is None:
        rsa_mod = '\x00' * 256
    assert len(rsa_mod) == 256
    ca_digest = '\x00' * 20
    rsp = vtpm_cmd(VTPM_ORD_GROUP_NEW, ca_digest + rsa_mod)

    (uuid, aik_pub, aik_priv_ca) = struct.unpack('16s256s256s', rsp)
    uuid = struct.unpack(uuid_fmt, uuid)
    uuid = '-'.join([part.encode('hex') for part in uuid])
    logger.info('Created group with UUID: %s', uuid)

    aikpem = tpmconv(aik_pub)
    # return the group
    group_num = get_group_num(uuid)
    t1 = time.time()

    retout = (uuid, aikpem, group_num, base64.b64encode(aik_priv_ca))

    if config.TPM_CANNED_VALUES_PATH is not None:
        with open(config.TPM_CANNED_VALUES_PATH, "ab") as can:
            jsonObj = {
                'type': "add_vtpm_group",
                'retout': list(retout),
                'fileout': "",
                'cmd': "add_vtpm_group",
                'timing': t1 - t0,
                'code': 0,
                'nonce': None
            }
            can.write("\"{}\": {},\n".format(
                "add_vtpm_group",
                json.dumps(jsonObj,
                           indent=4,
                           sort_keys=True,
                           Dumper=SafeDumper)))

    return retout
Пример #11
0
 def do_GET(self):
     self.send_response(200)
     self.send_header('Content-Type', 'application/json')
     self.end_headers()
     if TESTING_MODE:
         myUUID = str(uuid.uuid4())
     else:
         myUUID = provider_vtpm_add.add_vtpm("current_group.tpm")
     self.request.sendall(json.dumps({'uuid': myUUID}))
Пример #12
0
    def test_ima_buf_verification(self):
        """The verification of ima-buf entries supporting keys loaded onto keyrings"""
        list_map = ima.process_allowlists(ALLOWLIST, "")
        ima_keyrings = file_signatures.ImaKeyrings()

        self.assertTrue(
            ima.process_measurement_list(AgentAttestState("1"),
                                         KEYRINGS.splitlines(),
                                         json.dumps(list_map),
                                         ima_keyrings=ima_keyrings)
            is not None)
Пример #13
0
    def test_025_cv_allowlist_post(self):
        """Test CV's POST /allowlist/{name} Interface"""
        data = {
            "name": "test-allowlist",
            "tpm_policy": json.dumps(self.tpm_policy),
            "ima_policy": json.dumps(self.allowlist),
        }

        cv_client = RequestsClient(tenant_templ.verifier_base_url, tls_enabled)
        response = cv_client.post(
            f"/v{self.api_version}/allowlists/test-allowlist",
            data=json.dumps(data),
            cert=tenant_templ.cert,
            verify=False,
        )

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

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
Пример #14
0
 def write_error(self, status_code, **kwargs):
     self.set_header("Content-Type", "text/json")
     if self.settings.get("serve_traceback") and "exc_info" in kwargs:
         # in debug mode, try to send a traceback
         lines = []
         for line in traceback.format_exception(*kwargs["exc_info"]):
             lines.append(line)
         self.finish(
             json.dumps({
                 "code": status_code,
                 "status": self._reason,
                 "traceback": lines,
                 "results": {},
             }))
     else:
         self.finish(
             json.dumps({
                 "code": status_code,
                 "status": self._reason,
                 "results": {},
             }))
Пример #15
0
 def write_error(self, status_code, **kwargs):
     self.set_header('Content-Type', 'text/json')
     if self.settings.get("serve_traceback") and "exc_info" in kwargs:
         # in debug mode, try to send a traceback
         lines = []
         for line in traceback.format_exception(*kwargs["exc_info"]):
             lines.append(line)
         self.finish(
             json.dumps({
                 'code': status_code,
                 'status': self._reason,
                 'traceback': lines,
                 'results': {},
             }))
     else:
         self.finish(
             json.dumps({
                 'code': status_code,
                 'status': self._reason,
                 'results': {},
             }))
Пример #16
0
    def test_010_reg_agent_post(self):
        """Test registrar's POST /agents/{UUID} Interface"""
        global keyblob, tpm_instance, ek_tpm, aik_tpm
        contact_ip = "127.0.0.1"
        contact_port = 9002
        tpm_instance = tpm_main.tpm()

        # Change CWD for TPM-related operations
        cwd = os.getcwd()
        fs_util.ch_dir(config.WORK_DIR)
        _ = secure_mount.mount()

        # Create a mTLS cert for testing
        global mtls_cert
        rsa_key = crypto.rsa_generate(2048)
        valid_util = datetime.datetime.utcnow() + datetime.timedelta(days=(360 * 5))
        mtls_cert = crypto.generate_selfsigned_cert("TEST_CERT", rsa_key, valid_util).public_bytes(
            serialization.Encoding.PEM
        )

        # Initialize the TPM with AIK
        (ekcert, ek_tpm, aik_tpm) = tpm_instance.tpm_init(
            self_activate=False, config_pw=config.get("cloud_agent", "tpm_ownerpassword")
        )

        # Handle emulated TPMs
        if ekcert is None:
            if tpm_instance.is_emulator():
                ekcert = "emulator"

        # Get back to our original CWD
        fs_util.ch_dir(cwd)

        data = {"ekcert": ekcert, "aik_tpm": aik_tpm, "ip": contact_ip, "port": contact_port, "mtls_cert": mtls_cert}
        if ekcert is None or ekcert == "emulator":
            data["ek_tpm"] = ek_tpm

        test_010_reg_agent_post = RequestsClient(tenant_templ.registrar_base_url, tls_enabled=False)
        response = test_010_reg_agent_post.post(
            f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}", data=json.dumps(data), cert="", verify=False
        )

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

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

        keyblob = json_response["results"]["blob"]
        self.assertIsNotNone(keyblob, "Malformed response body!")
Пример #17
0
    def test_034_cv_agent_post_invalid_exclude_list(self):
        """Test CV's POST /agents/{UUID} Interface"""
        self.assertIsNotNone(self.V, "Required value not set.  Previous step may have failed?")

        b64_v = base64.b64encode(self.V)
        # Set unsupported regex in exclude list
        allowlist = {"exclude": ["*"]}
        data = {
            "v": b64_v,
            "mb_refstate": None,
            "cloudagent_ip": tenant_templ.cloudagent_ip,
            "cloudagent_port": tenant_templ.cloudagent_port,
            "tpm_policy": json.dumps(self.tpm_policy),
            "allowlist": json.dumps(allowlist),
            "ima_sign_verification_keys": "",
            "metadata": json.dumps(self.metadata),
            "revocation_key": self.revocation_key,
            "accept_tpm_hash_algs": config.get("tenant", "accept_tpm_hash_algs").split(","),
            "accept_tpm_encryption_algs": config.get("tenant", "accept_tpm_encryption_algs").split(","),
            "accept_tpm_signing_algs": config.get("tenant", "accept_tpm_signing_algs").split(","),
            "supported_version": tenant_templ.supported_version,
        }

        client = RequestsClient(tenant_templ.verifier_base_url, tls_enabled)
        response = client.post(
            f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}",
            cert=tenant_templ.cert,
            data=json.dumps(data),
            verify=False,
        )

        self.assertEqual(response.status_code, 400, "Successful CV agent Post return code!")

        # Ensure response is well-formed
        json_response = response.json()
        self.assertIn("results", json_response, "Malformed response body!")
Пример #18
0
 def test_json_response_tornado(self):
     """Tests JSON response output for Tornado"""
     mock_handler = MagicMock(spec=tornado.web.RequestHandler)
     test_data = {"key_1": "value", "key_2": 2}
     expected_output = json.dumps({
             "code": 200,
             "status": "Success",
             "results": test_data,
         }).encode("utf-8")
     res = web_util.echo_json_response(mock_handler, 200, "Success", test_data)
     self.assertTrue(res)
     mock_handler.set_status.assert_called_once_with(200)
     mock_handler.set_header.assert_called_once_with('Content-Type', 'application/json')
     mock_handler.write.assert_called_once_with(expected_output)
     mock_handler.finish.assert_called_once()
Пример #19
0
def activate_group(uuid, keyblob):
    fprt = "activate_group"
    if config.STUB_TPM and config.TPM_CANNED_VALUES is not None:
        # Use canned values for stubbing
        jsonIn = config.TPM_CANNED_VALUES
        if fprt in jsonIn:
            # The value we're looking for has been canned!
            thisTiming = jsonIn[fprt]['timing']
            thisRetout = jsonIn[fprt]['retout']
            logger.debug(
                "TPM call '{}' was stubbed out, with a simulated delay of {:f} sec"
                .format(fprt, thisTiming))
            time.sleep(thisTiming)
            return base64.b64decode(thisRetout)

        # Our command hasn't been canned!
        raise Exception("Command %s not found in canned JSON!" % (fprt))

    t0 = time.time()
    group_id = get_group_num(uuid)
    priv_ca = base64.b64decode(keyblob)
    assert len(priv_ca) == 256
    logger.debug('Activating group number %d', group_id)
    body = vtpm_cmd(VTPM_ORD_GROUP_ACTIVATE,
                    struct.pack('>II', group_id, 256) + priv_ca)
    (algId, encScheme, size), body = unpack('>IHH', body)
    assert size == len(body)
    t1 = time.time()
    logger.info('Received Key. AlgID: 0x%x, encScheme: 0x%x, size: 0x%x',
                algId, encScheme, size)
    logger.info('Key: %r', body)

    if config.TPM_CANNED_VALUES_PATH is not None:
        with open(config.TPM_CANNED_VALUES_PATH, "ab") as can:
            jsonObj = {
                'type': "activate_group",
                'retout': base64.b64encode(body),
                'fileout': "",
                'cmd': "activate_group",
                'timing': t1 - t0,
                'code': 0,
                'nonce': None
            }
            can.write("\"{}\": {},\n".format(
                "activate_group", json.dumps(jsonObj, indent=4,
                                             sort_keys=True)))

    return body
Пример #20
0
async def request(method,
                  url,
                  params=None,
                  data=None,
                  context=None,
                  headers=None):

    http_client = httpclient.AsyncHTTPClient()
    if params is not None and len(list(params.keys())) > 0:
        url += "?"
        for key in list(params.keys()):
            url += f"{key}={params[key]}&"
        url = url[:-1]

    if context is not None:
        url = url.replace("http://", "https://", 1)

    # Convert dict to JSON before sending
    if isinstance(data, dict):
        data = json.dumps(data)
        if headers is None:
            headers = {}
        if "Content-Type" not in headers:
            headers["Content-Type"] = "application/json"

    try:
        req = httpclient.HTTPRequest(url=url,
                                     method=method,
                                     ssl_options=context,
                                     body=data,
                                     headers=headers)
        response = await http_client.fetch(req)

    except httpclient.HTTPError as e:
        if e.response is None:
            return TornadoResponse(500, str(e))

        return TornadoResponse(e.response.code, e.response.body)
    except ConnectionError as e:
        return TornadoResponse(599, f"Connection error: {str(e)}")
    except ssl.SSLError as e:
        return TornadoResponse(599, f"SSL connection error: {str(e)}")
    except OSError as e:
        return TornadoResponse(599, f"TCP/IP Connection error: {str(e)}")
    if response is None:
        return None
    return TornadoResponse(response.code, response.body)
Пример #21
0
    def test_measurment_verification(self):
        """Test IMA measurement list verification"""
        lines = MEASUREMENTS.splitlines()
        lists_map = ima.process_ima_policy(ALLOWLIST, "")
        lists_map_empty = ima.process_ima_policy(ALLOWLIST_EMPTY, "")

        _, failure = ima.process_measurement_list(AgentAttestState("1"), lines)
        self.assertTrue(not failure, "Validation should always work when no allowlist and no keyring is specified")

        _, failure = ima.process_measurement_list(AgentAttestState("1"), lines, lists_map)
        self.assertTrue(not failure)
        # test with list with JSON
        _, failure = ima.process_measurement_list(AgentAttestState("1"), lines, json.dumps(lists_map))
        self.assertTrue(not failure)

        # No files are in the allowlist -> this should fail
        _, failure = ima.process_measurement_list(AgentAttestState("1"), lines, lists_map_empty)
        self.assertTrue(failure)
Пример #22
0
 def test_json_response_http_server(self):
     """Tests JSON response output for Tornado"""
     mock_handler = MagicMock(spec=http.server.BaseHTTPRequestHandler)
     mock_handler.wfile = MagicMock()
     test_data = {"key_1": "value", "key_2": 2}
     expected_output = json.dumps({
         "code": 200,
         "status": "Success",
         "results": test_data,
     }).encode("utf-8")
     res = web_util.echo_json_response(mock_handler, 200, "Success",
                                       test_data)
     self.assertTrue(res)
     mock_handler.send_response.assert_called_once_with(200)
     mock_handler.send_header.assert_called_once_with(
         "Content-Type", "application/json")
     mock_handler.end_headers.assert_called_once()
     mock_handler.wfile.write.assert_called_once_with(expected_output)
Пример #23
0
    def __init__(self, component: Component,
                 sub_components: Optional[List[str]], event_id: str,
                 context: Union[str, Dict[str,
                                          json.JSONType]], recoverable: bool):

        # Build full event id with the format "component.[sub_component].event_id"
        self.event_id = component.value
        if sub_components is not None:
            self.event_id += "." + ".".join(sub_components)
        self.event_id += f".{event_id}"

        # Convert message
        if isinstance(context, str):
            context = {"message": context}
        self.context = json.dumps(context)

        self.severity_label = _severity_match(self.event_id)
        self.recoverable = recoverable
Пример #24
0
 def worker(tosend):
     context = zmq.Context()
     mysock = context.socket(zmq.PUB)
     mysock.connect(f"ipc://{_SOCKET_PATH}")
     # wait 100ms for connect to happen
     time.sleep(0.2)
     # now send it out via 0mq
     logger.info("Sending revocation event to listening nodes...")
     for i in range(config.getint('cloud_verifier', 'max_retries')):
         try:
             mysock.send_string(json.dumps(tosend))
             break
         except Exception as e:
             logger.debug(
                 "Unable to publish revocation message %d times, trying again in %f seconds: %s"
                 % (i, config.getfloat('cloud_verifier',
                                       'retry_interval'), e))
             time.sleep(config.getfloat('cloud_verifier', 'retry_interval'))
     mysock.close()
Пример #25
0
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: " +
        str(response.status_code))
    keylime_logging.log_http_response(logger, logging.ERROR, response_body)
    return False
Пример #26
0
def add_vtpm_to_group(uuid):
    fprt = "add_vtpm_to_group"
    if config.STUB_TPM and config.TPM_CANNED_VALUES is not None:
        # Use canned values for stubbing
        jsonIn = config.TPM_CANNED_VALUES
        if fprt in jsonIn:
            # The value we're looking for has been canned!
            thisTiming = jsonIn[fprt]['timing']
            thisRetout = jsonIn[fprt]['retout']
            logger.debug(
                "TPM call '{}' was stubbed out, with a simulated delay of {:f} sec"
                .format(fprt, thisTiming))
            time.sleep(thisTiming)
            return thisRetout

        # Our command hasn't been canned!
        raise Exception("Command %s not found in canned JSON!" % (fprt))

    t0 = time.time()
    num = get_group_num(uuid)
    vtpm_uuid = add_vtpm(num)
    t1 = time.time()

    retout = str(UUID(vtpm_uuid)).upper()

    if config.TPM_CANNED_VALUES_PATH is not None:
        with open(config.TPM_CANNED_VALUES_PATH, "ab") as can:
            jsonObj = {
                'type': "add_vtpm_to_group",
                'retout': retout,
                'fileout': "",
                'cmd': "add_vtpm_to_group",
                'timing': t1 - t0,
                'code': 0,
                'nonce': None
            }
            can.write("\"{}\": {},\n".format(
                "add_vtpm_to_group",
                json.dumps(jsonObj, indent=4, sort_keys=True)))

    return retout
Пример #27
0
 def worker(tosend):
     context = zmq.Context()
     mysock = context.socket(zmq.PUB)
     mysock.connect(f"ipc://{_SOCKET_PATH}")
     # wait 100ms for connect to happen
     time.sleep(0.2)
     # now send it out via 0mq
     logger.info("Sending revocation event to listening nodes...")
     for i in range(config.getint("cloud_verifier", "max_retries")):
         try:
             mysock.send_string(json.dumps(tosend))
             break
         except Exception as e:
             interval = config.getfloat("cloud_verifier", "retry_interval")
             exponential_backoff = config.getboolean(
                 "cloud_verifier", "exponential_backoff")
             next_retry = retry.retry_time(exponential_backoff, interval, i,
                                           logger)
             logger.debug(
                 "Unable to publish revocation message %d times, trying again in %f seconds: %s",
                 i, next_retry, e)
             time.sleep(next_retry)
     mysock.close()
Пример #28
0
def notify_error(agent, msgtype='revocation', event=None):
    send_mq = config.getboolean('cloud_verifier', 'revocation_notifier')
    send_webhook = config.getboolean('cloud_verifier',
                                     'revocation_notifier_webhook',
                                     fallback=False)
    if not (send_mq or send_webhook):
        return

    # prepare the revocation message:
    revocation = {
        'type': msgtype,
        'ip': agent['ip'],
        'agent_id': agent['agent_id'],
        'port': agent['port'],
        'tpm_policy': agent['tpm_policy'],
        'vtpm_policy': agent['vtpm_policy'],
        'meta_data': agent['meta_data'],
        'event_time': time.asctime()
    }
    if event:
        revocation['event_id'] = event.event_id
        revocation['severity_label'] = event.severity_label.name
        revocation['context'] = event.context

    tosend = {'msg': json.dumps(revocation).encode('utf-8')}

    # also need to load up private key for signing revocations
    if agent['revocation_key'] != "":
        signing_key = crypto.rsa_import_privkey(agent['revocation_key'])
        tosend['signature'] = crypto.rsa_sign(signing_key, tosend['msg'])

    else:
        tosend['signature'] = "none"
    if send_mq:
        revocation_notifier.notify(tosend)
    if send_webhook:
        revocation_notifier.notify_webhook(tosend)
Пример #29
0
def notify_error(agent, msgtype="revocation", event=None):
    send_mq = config.getboolean("cloud_verifier", "revocation_notifier")
    send_webhook = config.getboolean("cloud_verifier",
                                     "revocation_notifier_webhook",
                                     fallback=False)
    if not (send_mq or send_webhook):
        return

    # prepare the revocation message:
    revocation = {
        "type": msgtype,
        "ip": agent["ip"],
        "agent_id": agent["agent_id"],
        "port": agent["port"],
        "tpm_policy": agent["tpm_policy"],
        "meta_data": agent["meta_data"],
        "event_time": time.asctime(),
    }
    if event:
        revocation["event_id"] = event.event_id
        revocation["severity_label"] = event.severity_label.name
        revocation["context"] = event.context

    tosend = {"msg": json.dumps(revocation).encode("utf-8")}

    # also need to load up private key for signing revocations
    if agent["revocation_key"] != "":
        signing_key = crypto.rsa_import_privkey(agent["revocation_key"])
        tosend["signature"] = crypto.rsa_sign(signing_key, tosend["msg"])

    else:
        tosend["signature"] = "none"
    if send_mq:
        revocation_notifier.notify(tosend)
    if send_webhook:
        revocation_notifier.notify_webhook(tosend)
Пример #30
0
 def test_dumps(self):
     fixtures = [
         {"input": {}, "expected": "{}"},
         {"input": {"foo": "bar"}, "expected": '{"foo": "bar"}'},
         {"input": {"foo": b"bar"}, "expected": '{"foo": "bar"}'},
         {
             "input": {"foo": {"foo": {"foo": b"bar"}}},
             "expected": '{"foo": {"foo": {"foo": "bar"}}}',
         },
         {"input": [], "expected": "[]"},
         {"input": (), "expected": "[]"},
         {"input": [b"a", b"b", 1, 2.0], "expected": '["a", "b", 1, 2.0]'},
         {"input": {"foo": [b"bar"]}, "expected": '{"foo": ["bar"]}'},
         {
             "input": (
                 1,
                 2,
                 b"a",
             ),
             "expected": '[1, 2, "a"]',
         },
     ]
     for f in fixtures:
         self.assertEqual(keylime_json.dumps(f["input"]), f["expected"])