コード例 #1
0
ファイル: test_restful.py プロジェクト: lukehinds/keylime
    def test_034_cv_agent_post_invalid_exclude_list(self):
        """Test CV's POST /v2/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,
            '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(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(','),
        }

        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!")
コード例 #2
0
def _eval_severity_config() -> Tuple[List[Callable[[str], Optional[SeverityLabel]]], SeverityLabel]:
    """
    Generates the list of rules to match a event_id against.
    """

    labels_list = ast.literal_eval(config.get("cloud_verifier", "severity_labels"))
    labels = {}
    for label, level in zip(labels_list, range(0, len(labels_list))):
        labels[label] = SeverityLabel(label, level)

    label_max = labels[labels_list[-1]]

    policies = ast.literal_eval(config.get("cloud_verifier", "severity_policy"))
    rules = []
    for policy in policies:
        # TODO validate regex
        regex = re.compile(policy["event_id"])

        def rule(policy_regex: Pattern[Any], label_str: str, event_id: str) -> Optional[SeverityLabel]:
            if policy_regex.fullmatch(event_id):
                policy_label = labels.get(label_str)
                if policy_label is None:
                    logger.error("Label %s is not a valid label. Defaulting to maximal severity label!", label_str)
                    return label_max
                return policy_label
            return None

        new_rule: Callable[[str], Optional[SeverityLabel]] = functools.partial(rule, regex, policy["severity_label"])
        rules.append(new_rule)
    return rules, label_max
コード例 #3
0
def get_tls_context():
    ca_cert = config.get('tenant', 'ca_cert')

    tls_dir = config.get('tenant', 'tls_dir')

    if tls_dir == 'default':
        ca_cert = 'cacert.crt'
        tls_dir = 'cv_ca'

    # this is relative path, convert to absolute in WORK_DIR
    if tls_dir[0] != '/':
        tls_dir = os.path.abspath('%s/%s' % (config.WORK_DIR, tls_dir))

    logger.info("Setting up client TLS in %s", tls_dir)

    ca_path = "%s/%s" % (tls_dir, ca_cert)
    my_tls_cert = "%s/%s" % (tls_dir, my_cert)
    my_tls_priv_key = "%s/%s" % (tls_dir, my_priv_key)

    context = ssl.create_default_context()
    context.load_verify_locations(cafile=ca_path)
    context.load_cert_chain(certfile=my_tls_cert, keyfile=my_tls_priv_key)
    context.verify_mode = ssl.CERT_REQUIRED
    context.check_hostname = config.getboolean('general',
                                               'tls_check_hostnames')
    return context
コード例 #4
0
def add_vtpm(inputfile):
    # read in the file
    with open(inputfile, encoding="utf-8") as f:
        group = yaml.load(f, Loader=SafeLoader)

    # fetch configuration parameters
    provider_reg_port = config.get('registrar', 'provider_registrar_port')
    provider_reg_ip = config.get('registrar', 'provider_registrar_ip')

    # request a vtpm uuid from the manager
    vtpm_uuid = vtpm_manager.add_vtpm_to_group(group['uuid'])

    # registrar it and get back a blob
    keyblob = registrar_client.doRegisterAgent(provider_reg_ip,
                                               provider_reg_port, vtpm_uuid,
                                               group['pubekpem'],
                                               group['ekcert'],
                                               group['aikpem'])

    # get the ephemeral registrar key by activating in the hardware tpm
    key = base64.b64encode(vtpm_manager.activate_group(group['uuid'], keyblob))

    # tell the registrar server we know the key
    registrar_client.doActivateAgent(provider_reg_ip, provider_reg_port,
                                     vtpm_uuid, key)

    logger.info("Registered new vTPM with UUID: %s", vtpm_uuid)

    return vtpm_uuid
コード例 #5
0
ファイル: keylime_agent.py プロジェクト: kgold2/keylime
    def __init__(self, server_address, RequestHandlerClass, agent_uuid):
        """Constructor overridden to provide ability to pass configuration arguments to the server"""
        secdir = secure_mount.mount()
        keyname = "%s/%s" % (secdir, config.get('cloud_agent', 'rsa_keyname'))
        # read or generate the key depending on configuration
        if os.path.isfile(keyname):
            # read in private key
            logger.debug("Using existing key in %s", keyname)
            f = open(keyname, "rb")
            rsa_key = crypto.rsa_import_privkey(f.read())
        else:
            logger.debug("key not found, generating a new one")
            rsa_key = crypto.rsa_generate(2048)
            with open(keyname, "wb") as f:
                f.write(crypto.rsa_export_privkey(rsa_key))

        self.rsaprivatekey = rsa_key
        self.rsapublickey_exportable = crypto.rsa_export_pubkey(
            self.rsaprivatekey)

        # attempt to get a U value from the TPM NVRAM
        nvram_u = tpm_instance.read_key_nvram()
        if nvram_u is not None:
            logger.info("Existing U loaded from TPM NVRAM")
            self.add_U(nvram_u)
        http.server.HTTPServer.__init__(self, server_address,
                                        RequestHandlerClass)
        self.enc_keyname = config.get('cloud_agent', 'enc_keyname')
        self.agent_uuid = agent_uuid
コード例 #6
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)
コード例 #7
0
def init_client_tls(section):
    global tls_cert_info
    global tls_enabled

    # make this reentrant
    if tls_cert_info:
        return

    if not config.getboolean('general', "enable_tls"):
        logger.warning("TLS is currently disabled, AIKs may not be authentic.")
        return

    logger.warning("TLS is enabled.")
    tls_enabled = True

    logger.info("Setting up client TLS...")
    tls_dir = config.get(section, 'registrar_tls_dir')

    my_cert = config.get(section, 'registrar_my_cert')
    my_priv_key = config.get(section, 'registrar_private_key')
    my_key_pw = config.get(section, 'registrar_private_key_pw')

    if tls_dir == 'default':
        tls_dir = 'reg_ca'
        my_cert = 'client-cert.crt'
        my_priv_key = 'client-private.pem'

    if tls_dir == 'CV':
        tls_dir = 'cv_ca'
        my_cert = 'client-cert.crt'
        my_priv_key = 'client-private.pem'

    # this is relative path, convert to absolute in WORK_DIR
    if tls_dir[0] != '/':
        tls_dir = os.path.abspath('%s/%s' % (config.WORK_DIR, tls_dir))

    ca_cert = config.get(section, 'registrar_ca_cert')

    if ca_cert == 'default':
        ca_path = "%s/cacert.crt" % (tls_dir)
    else:
        ca_path = "%s/%s" % (tls_dir, ca_cert)

    if os.path.isabs(my_cert):
        tls_cert = my_cert
    else:
        tls_cert = "%s/%s" % (tls_dir, my_cert)
    if os.path.isabs(my_priv_key):
        tls_priv_key = my_priv_key
    else:
        tls_priv_key = "%s/%s" % (tls_dir, my_priv_key)

    tls_cert_info = (tls_cert, tls_priv_key)
コード例 #8
0
def init_client_tls(section):
    global tls_cert_info
    global tls_enabled
    global ca_cert

    # make this reentrant
    if tls_cert_info:
        return

    if not config.getboolean("general", "enable_tls"):
        logger.warning(
            "Warning: TLS is currently disabled, AIKs may not be authentic.")
        return

    logger.warning("TLS is enabled.")
    tls_enabled = True

    logger.info("Setting up client TLS...")
    tls_dir = config.get(section, "registrar_tls_dir")

    ca_cert = config.get(section, "registrar_ca_cert")
    my_cert = config.get(section, "registrar_my_cert")
    my_priv_key = config.get(section, "registrar_private_key")

    if tls_dir == "default":
        tls_dir = "reg_ca"
        ca_cert = "cacert.crt"
        my_cert = "client-cert.crt"
        my_priv_key = "client-private.pem"

    if tls_dir == "CV":
        tls_dir = "cv_ca"
        ca_cert = "cacert.crt"
        my_cert = "client-cert.crt"
        my_priv_key = "client-private.pem"

    # this is relative path, convert to absolute in WORK_DIR
    if tls_dir[0] != "/":
        tls_dir = os.path.abspath(os.path.join(config.WORK_DIR, tls_dir))

    if not os.path.isabs(ca_cert):
        ca_cert = os.path.join(tls_dir, ca_cert)

    if os.path.isabs(my_cert):
        tls_cert = my_cert
    else:
        tls_cert = os.path.join(tls_dir, my_cert)
    if os.path.isabs(my_priv_key):
        tls_priv_key = my_priv_key
    else:
        tls_priv_key = os.path.join(tls_dir, my_priv_key)

    tls_cert_info = (tls_cert, tls_priv_key)
コード例 #9
0
    def test_030_cv_agent_post(self):
        """Test CV's POST /v2/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(','),
        }

        test_030_cv_agent_post = RequestsClient(tenant_templ.verifier_base_url,
                                                tls_enabled)
        response = test_030_cv_agent_post.post(
            f'/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)
コード例 #10
0
ファイル: ca_impl_openssl.py プロジェクト: mpeters/keylime
def mk_name(common_name):
    return x509.Name([
        x509.NameAttribute(NameOID.COUNTRY_NAME,
                           config.get("ca", "cert_country")),
        x509.NameAttribute(NameOID.COMMON_NAME, common_name),
        x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME,
                           config.get("ca", "cert_state")),
        x509.NameAttribute(NameOID.LOCALITY_NAME,
                           config.get("ca", "cert_locality")),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME,
                           config.get("ca", "cert_organization")),
        x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME,
                           config.get("ca", "cert_org_unit")),
    ])
コード例 #11
0
    def __init__(self, server_address, RequestHandlerClass, agent_uuid):
        """Constructor overridden to provide ability to pass configuration arguments to the server"""
        secdir = secure_mount.mount()
        keyname = os.path.join(secdir, config.get('cloud_agent',
                                                  'rsa_keyname'))
        certname = os.path.join(secdir, config.get('cloud_agent', 'mtls_cert'))
        # read or generate the key depending on configuration
        if os.path.isfile(keyname):
            # read in private key
            logger.debug("Using existing key in %s", keyname)
            f = open(keyname, "rb")
            rsa_key = crypto.rsa_import_privkey(f.read())
        else:
            logger.debug("key not found, generating a new one")
            rsa_key = crypto.rsa_generate(2048)
            with open(keyname, "wb") as f:
                f.write(crypto.rsa_export_privkey(rsa_key))

        self.rsakey_path = keyname
        self.rsaprivatekey = rsa_key
        self.rsapublickey_exportable = crypto.rsa_export_pubkey(
            self.rsaprivatekey)

        if os.path.isfile(certname):
            logger.debug("Using existing mTLS cert in %s", certname)
            with open(certname, "rb") as f:
                mtls_cert = x509.load_pem_x509_certificate(f.read())
        else:
            logger.debug("No mTLS certificate found generating a new one")
            with open(certname, "wb") as f:
                # By default generate a TLS certificate valid for 5 years
                valid_util = datetime.datetime.utcnow() + datetime.timedelta(
                    days=(360 * 5))
                mtls_cert = crypto.generate_selfsigned_cert(
                    agent_uuid, rsa_key, valid_util)
                f.write(mtls_cert.public_bytes(serialization.Encoding.PEM))

        self.mtls_cert_path = certname
        self.mtls_cert = mtls_cert

        # attempt to get a U value from the TPM NVRAM
        nvram_u = tpm_instance.read_key_nvram()
        if nvram_u is not None:
            logger.info("Existing U loaded from TPM NVRAM")
            self.add_U(nvram_u)
        http.server.HTTPServer.__init__(self, server_address,
                                        RequestHandlerClass)
        self.enc_keyname = config.get('cloud_agent', 'enc_keyname')
        self.agent_uuid = agent_uuid
コード例 #12
0
        def perform_actions(revocation):
            actionlist = []

            # load the actions from inside the keylime module
            actionlisttxt = config.get('cloud_agent', 'revocation_actions')
            if actionlisttxt.strip() != "":
                actionlist = actionlisttxt.split(',')
                actionlist = ["revocation_actions.%s" % i for i in actionlist]

            # load actions from unzipped
            if os.path.exists("%s/unzipped/action_list" % secdir):
                with open("%s/unzipped/action_list" % secdir, 'r') as f:
                    actionlisttxt = f.read()
                if actionlisttxt.strip() != "":
                    localactions = actionlisttxt.strip().split(',')
                    for action in localactions:
                        if not action.startswith('local_action_'):
                            logger.warning("Invalid local action: %s. Must start with local_action_", action)
                        else:
                            actionlist.append(action)

                    uzpath = "%s/unzipped" % secdir
                    if uzpath not in sys.path:
                        sys.path.append(uzpath)

            for action in actionlist:
                logger.info("Executing revocation action %s", action)
                try:
                    module = importlib.import_module(action)
                    execute = getattr(module, 'execute')
                    asyncio.get_event_loop().run_until_complete(execute(revocation))
                except Exception as e:
                    logger.warning("Exception during execution of revocation action %s: %s", action, e)
コード例 #13
0
def notify_webhook(tosend):
    url = config.get('cloud_verifier', 'webhook_url', fallback='')
    # Check if a url was specified
    if url == '':
        return

    def worker_webhook(tosend, url):
        retry_interval = config.getfloat('cloud_verifier', 'retry_interval')
        session = requests.session()
        logger.info("Sending revocation event via webhook...")
        for i in range(config.getint('cloud_verifier', 'max_retries')):
            try:
                response = session.post(url, json=tosend)
                if response.status_code in [200, 202]:
                    break

                logger.debug(
                    f"Unable to publish revocation message {i} times via webhook, "
                    f"trying again in {retry_interval} seconds. "
                    f"Server returned status code: {response.status_code}")
            except requests.exceptions.RequestException as e:
                logger.debug(
                    f"Unable to publish revocation message {i} times via webhook, "
                    f"trying again in {retry_interval} seconds: {e} ")

            time.sleep(retry_interval)

    w = functools.partial(worker_webhook, tosend, url)
    t = threading.Thread(target=w)
    t.start()
コード例 #14
0
def await_notifications(callback, revocation_cert_path):
    # keep old typo "listen_notfications" around for a few versions
    assert config.getboolean(
        "cloud_agent", "listen_notifications",
        fallback=False) or config.getboolean(
            "cloud_agent", "listen_notfications", fallback=False)
    try:
        import zmq  # pylint: disable=import-outside-toplevel
    except ImportError as error:
        raise Exception(
            "install PyZMQ for 'listen_notifications' option") from error

    if revocation_cert_path is None:
        raise Exception("must specify revocation_cert_path")

    context = zmq.Context()
    mysock = context.socket(zmq.SUB)
    mysock.setsockopt(zmq.SUBSCRIBE, b"")
    mysock.connect(f"tcp://{config.get('general', 'receive_revocation_ip')}:"
                   f"{config.getint('general', 'receive_revocation_port')}")

    logger.info(
        "Waiting for revocation messages on 0mq %s:%s",
        config.get("general", "receive_revocation_ip"),
        config.getint("general", "receive_revocation_port"),
    )

    while True:
        rawbody = mysock.recv()
        body = json.loads(rawbody)
        process_revocation(body, callback, revocation_cert_path)
コード例 #15
0
    def perform_actions(revocation):
        actionlist = []

        # load the actions from inside the keylime module
        actionlisttxt = config.get("cloud_agent", "revocation_actions")
        if actionlisttxt.strip() != "":
            actionlist = actionlisttxt.split(",")
            actionlist = [f"revocation_actions.{i}" % i for i in actionlist]

        # load actions from unzipped
        action_list_path = os.path.join(secdir, "unzipped/action_list")
        if os.path.exists(action_list_path):
            with open(action_list_path, encoding="utf-8") as f:
                actionlisttxt = f.read()
            if actionlisttxt.strip() != "":
                localactions = actionlisttxt.strip().split(",")
                for action in localactions:
                    if not action.startswith("local_action_"):
                        logger.warning("Invalid local action: %s. Must start with local_action_", action)
                    else:
                        actionlist.append(action)

                uzpath = os.path.join(secdir, "unzipped")
                if uzpath not in sys.path:
                    sys.path.append(uzpath)

        for action in actionlist:
            logger.info("Executing revocation action %s", action)
            try:
                module = importlib.import_module(action)
                execute = getattr(module, "execute")
                asyncio.get_event_loop().run_until_complete(execute(revocation))
            except Exception as e:
                logger.warning("Exception during execution of revocation action %s: %s", action, e)
コード例 #16
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"] = []

        cls.bad_ima_policy_bundle = ima.read_allowlist()
        cls.bad_ima_policy_bundle["excllist"] = ["*"]
コード例 #17
0
ファイル: ca_util.py プロジェクト: axelsimon/keylime
def convert_crl_to_pem(derfile, pemfile):
    if config.get('general', 'ca_implementation') == 'openssl':
        with open(pemfile, 'w', encoding="utf-8") as f:
            f.write("")
    else:
        cmd = ('openssl', 'crl', '-in', derfile, '-inform', 'der',
               '-out', pemfile)
        cmd_exec.run(cmd)
コード例 #18
0
ファイル: ca_impl_openssl.py プロジェクト: mpeters/keylime
def mk_cacert(name=None):
    """
    Make a CA certificate.
    Returns the certificate, private key and public key.
    """

    if name is None:
        name = config.get("ca", "cert_ca_name")
    cert_req, privkey = mk_request(config.getint("ca", "cert_bits"), name)

    pubkey = privkey.public_key()
    cert_req = cert_req.public_key(pubkey)

    cert_req = cert_req.serial_number(1)
    cert_req = mk_cert_valid(cert_req, config.getint("ca", "cert_ca_lifetime"))
    cert_req = cert_req.issuer_name(mk_name(name))

    # Extensions.
    extensions = [
        # Basic Constraints.
        x509.BasicConstraints(ca=True, path_length=None),
        # Subject Key Identifier.
        x509.SubjectKeyIdentifier.from_public_key(pubkey),
        # CRL Distribution Points.
        x509.CRLDistributionPoints([
            x509.DistributionPoint(
                full_name=[
                    x509.UniformResourceIdentifier("http://localhost/crl.pem"),
                ],
                relative_name=None,
                reasons=None,
                crl_issuer=None,
            ),
        ]),
        # Key Usage.
        x509.KeyUsage(
            key_cert_sign=True,
            crl_sign=True,
            digital_signature=False,
            content_commitment=False,
            key_encipherment=False,
            data_encipherment=False,
            key_agreement=False,
            encipher_only=False,
            decipher_only=False,
        ),
    ]

    for ext in extensions:
        cert_req = cert_req.add_extension(ext, critical=False)

    cert = cert_req.sign(
        private_key=privkey,
        algorithm=hashes.SHA256(),
        backend=default_backend(),
    )

    return cert, privkey, pubkey
コード例 #19
0
    def test_010_reg_agent_post(self):
        """Test registrar's POST /v2/agents/{UUID} Interface"""
        global keyblob, aik, vtpm, ek

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

        # Initialize the TPM with AIK
        (ek, ekcert, aik, ek_tpm,
         aik_name) = tpm.tpm_init(self_activate=False,
                                  config_pw=config.get('cloud_agent',
                                                       'tpm_ownerpassword'))
        vtpm = tpm.is_vtpm()

        # Seed RNG (root only)
        if config.REQUIRE_ROOT:
            tpm.init_system_rand()

        # Handle virtualized and emulated TPMs
        if ekcert is None:
            if vtpm:
                ekcert = 'virtual'
            elif tpm.is_emulator():
                ekcert = 'emulator'

        # Get back to our original CWD
        config.ch_dir(cwd, None)

        data = {
            'ek': ek,
            'ekcert': ekcert,
            'aik': aik,
            'aik_name': aik_name,
            'ek_tpm': ek_tpm,
            'tpm_version': tpm.VERSION,
        }

        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!")
コード例 #20
0
def await_notifications(callback, revocation_cert_path):
    global cert_key

    if revocation_cert_path is None:
        raise Exception("must specify revocation_cert_path")

    context = zmq.Context()
    mysock = context.socket(zmq.SUB)
    mysock.setsockopt(zmq.SUBSCRIBE, b'')
    mysock.connect("tcp://%s:%s" %
                   (config.get('general', 'receive_revocation_ip'),
                    config.getint('general', 'receive_revocation_port')))

    logger.info('Waiting for revocation messages on 0mq %s:%s' %
                (config.get('general', 'receive_revocation_ip'),
                 config.getint('general', 'receive_revocation_port')))

    while True:
        rawbody = mysock.recv()
        body = json.loads(rawbody)

        if cert_key is None:
            # load up the CV signing public key
            if revocation_cert_path is not None and os.path.exists(
                    revocation_cert_path):
                logger.info("Lazy loading the revocation certificate from %s" %
                            revocation_cert_path)
                with open(revocation_cert_path, 'r') as f:
                    certpem = f.read()
                cert_key = crypto.x509_import_pubkey(certpem)

        if cert_key is None:
            logger.warning(
                "Unable to check signature of revocation message: %s not available"
                % revocation_cert_path)
        elif 'signature' not in body or body['signature'] == 'none':
            logger.warning("No signature on revocation message from server")
        elif not crypto.rsa_verify(cert_key, body['msg'].encode('utf-8'),
                                   body['signature'].encode('utf-8')):
            logger.error("Invalid revocation message siganture %s" % body)
        else:
            message = json.loads(body['msg'])
            logger.debug("Revocation signature validated for revocation: %s" %
                         message)
            callback(message)
コード例 #21
0
def main(argv=sys.argv):
    # if we are configured to auto-migrate the DB, check if there are any migrations to perform
    if config.has_option('registrar', 'auto_migrate_db') and config.getboolean(
            'registrar', 'auto_migrate_db'):
        keylime.cmd.migrations_apply.apply('registrar')

    registrar_common.start(config.get('registrar', 'registrar_ip'),
                           config.getint('registrar', 'registrar_tls_port'),
                           config.getint('registrar', 'registrar_port'))
コード例 #22
0
def await_notifications(callback, revocation_cert_path):
    # keep old typo "listen_notfications" around for a few versions
    assert config.getboolean(
        "cloud_agent", "listen_notifications",
        fallback=False) or config.getboolean(
            "cloud_agent", "listen_notfications", fallback=False)
    try:
        import zmq  # pylint: disable=import-outside-toplevel
    except ImportError as error:
        raise Exception(
            "install PyZMQ for 'listen_notifications' option") from error

    global cert_key

    if revocation_cert_path is None:
        raise Exception("must specify revocation_cert_path")

    context = zmq.Context()
    mysock = context.socket(zmq.SUB)
    mysock.setsockopt(zmq.SUBSCRIBE, b"")
    mysock.connect(f"tcp://{config.get('general', 'receive_revocation_ip')}:"
                   f"{config.getint('general', 'receive_revocation_port')}")

    logger.info(
        "Waiting for revocation messages on 0mq %s:%s",
        config.get("general", "receive_revocation_ip"),
        config.getint("general", "receive_revocation_port"),
    )

    while True:
        rawbody = mysock.recv()
        body = json.loads(rawbody)

        if cert_key is None:
            # load up the CV signing public key
            if revocation_cert_path is not None and os.path.exists(
                    revocation_cert_path):
                logger.info("Lazy loading the revocation certificate from %s",
                            revocation_cert_path)
                with open(revocation_cert_path, "rb") as f:
                    certpem = f.read()
                cert_key = crypto.x509_import_pubkey(certpem)

        if cert_key is None:
            logger.warning(
                "Unable to check signature of revocation message: %s not available",
                revocation_cert_path)
        elif "signature" not in body or body["signature"] == "none":
            logger.warning("No signature on revocation message from server")
        elif not crypto.rsa_verify(cert_key, body["msg"].encode("utf-8"),
                                   body["signature"].encode("utf-8")):
            logger.error("Invalid revocation message siganture %s", body)
        else:
            message = json.loads(body["msg"])
            logger.debug("Revocation signature validated for revocation: %s",
                         message)
            callback(message)
コード例 #23
0
    def test_010_reg_agent_post(self):
        """Test registrar's POST /agents/{UUID} Interface"""
        global keyblob, vtpm, 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()
        config.ch_dir(config.WORK_DIR, None)
        _ = secure_mount.mount()

        # 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'))
        vtpm = tpm_instance.is_vtpm()

        # Handle virtualized and emulated TPMs
        if ekcert is None:
            if vtpm:
                ekcert = 'virtual'
            elif tpm_instance.is_emulator():
                ekcert = 'emulator'

        # Get back to our original CWD
        config.ch_dir(cwd, None)

        data = {
            'ekcert': ekcert,
            'aik_tpm': aik_tpm,
            'ip': contact_ip,
            'port': contact_port
        }
        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!")
コード例 #24
0
ファイル: registrar.py プロジェクト: mbestavros/keylime
def main():
    # if we are configured to auto-migrate the DB, check if there are any migrations to perform
    if config.has_option("registrar", "auto_migrate_db") and config.getboolean(
            "registrar", "auto_migrate_db"):
        keylime.cmd.migrations_apply.apply("registrar")

    registrar_common.start(
        config.get("registrar", "registrar_ip"),
        config.getint("registrar", "registrar_tls_port"),
        config.getint("registrar", "registrar_port"),
    )
コード例 #25
0
def read_mb_refstate(mb_path=None):
    if mb_path is None:
        mb_path = config.get('tenant', 'mb_refstate')

    mb_data = None
    # Purposefully die if path doesn't exist
    with open(mb_path, 'r') as f:
        mb_data = json.load(f)

    logger.debug(f"Loaded measured boot reference state from {mb_path}")

    return mb_data
コード例 #26
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.vtpm_policy = config.get('tenant', 'vtpm_policy')
        cls.tpm_policy = tpm_abstract.TPM_Utilities.readPolicy(cls.tpm_policy)
        cls.vtpm_policy = tpm_abstract.TPM_Utilities.readPolicy(cls.vtpm_policy)

        # Allow targeting a specific API version (default latest)
        cls.api_version = config.API_VERSION
コード例 #27
0
def read_mb_refstate(mb_path=None):
    if mb_path is None:
        mb_path = config.get("tenant", "mb_refstate")

    mb_data = None
    # Purposefully die if path doesn't exist
    with open(mb_path, encoding="utf-8") as f:
        mb_data = json.load(f)

    logger.debug("Loaded measured boot reference state from %s", mb_path)

    return mb_data
コード例 #28
0
def mk_cacert():
    csr = {
        "CN":
        config.get('ca', 'cert_ca_name'),
        "key": {
            "algo": "rsa",
            "size": config.getint('ca', 'cert_bits')
        },
        "names": [{
            "C": config.get('ca', 'cert_country'),
            "L": config.get('ca', 'cert_locality'),
            "O": config.get('ca', 'cert_organization'),
            "OU": config.get('ca', 'cert_org_unit'),
            "ST": config.get('ca', 'cert_state')
        }]
    }
    try:
        start_cfssl()
        body = post_cfssl('api/v1/cfssl/init_ca', csr)
    finally:
        stop_cfssl()

    if body['success']:
        pk_str = body['result']['private_key']
        pk = EVP.load_key_string(body['result']['private_key'].encode('utf-8'))
        cert = X509.load_cert_string(
            body['result']['certificate'].encode('utf-8'))
        pkey = cert.get_pubkey()

        return pk_str, cert, pk, pkey

    raise Exception("Unable to create CA")
コード例 #29
0
    def __init__(self):
        """ Set up required values and TLS
        """
        self.nonce = None
        self.agent_ip = None
        self.agent_port = config.get('cloud_agent', 'cloudagent_port')
        self.verifier_ip = config.get('tenant', 'cloudverifier_ip')
        self.verifier_port = config.get('tenant', 'cloudverifier_port')
        self.registrar_ip = config.get('tenant', 'registrar_ip')
        self.registrar_port = config.get('tenant', 'registrar_port')
        self.webapp_port = config.getint('webapp', 'webapp_port')
        if not config.REQUIRE_ROOT and self.webapp_port < 1024:
            self.webapp_port += 2000
        self.webapp_ip = config.get('webapp', 'webapp_ip')

        self.my_cert, self.my_priv_key = self.get_tls_context()
        self.cert = (self.my_cert, self.my_priv_key)
        if config.getboolean('general', "enable_tls"):
            self.tls_enabled = True
        else:
            self.tls_enabled = False
            self.cert = ""
            logger.warning(
                "Warning: TLS is currently disabled, keys will be sent in the clear! This should only be used for testing."
            )
コード例 #30
0
    def make_engine(self, service):
        """
        To use: engine = self.make_engine('cloud_verifier')
        """
        self.service = service

        drivername = config.get(service, 'drivername')

        if drivername == 'sqlite':
            database = "%s/%s" % (config.WORK_DIR,
                                  config.get(service, 'database'))
            # Create the path to where the sqlite database will be store with a perm umask of 077
            os.umask(0o077)
            kl_dir = os.path.dirname(os.path.abspath(database))
            if not os.path.exists(kl_dir):
                os.makedirs(kl_dir, 0o700)

            url = URL(drivername=drivername,
                      username=None,
                      password=None,
                      host=None,
                      database=(database))
            engine = create_engine(
                url,
                connect_args={'check_same_thread': False},
            )
        else:
            url = URL(drivername=drivername,
                      username=config.get(service, 'username'),
                      password=config.get(service, 'password'),
                      host=config.get(service, 'host'),
                      database=config.get(service, 'database'))
            engine = create_engine(url)

        return engine