Exemplo n.º 1
0
 def setUpClass(cls):
     """Prepare the keys and payload to give to the CV"""
     contents = "random garbage to test as payload"
     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 a node"""
     cls.auth_tag = crypto.do_hmac(cls.K, tenant_templ.node_uuid)
     """Prepare policies for node"""
     cls.tpm_policy = config.get('tenant', 'tpm_policy')
     cls.vtpm_policy = config.get('tenant', 'vtpm_policy')
     cls.tpm_policy = tpm_quote.readPolicy(cls.tpm_policy)
     cls.vtpm_policy = tpm_quote.readPolicy(cls.vtpm_policy)
Exemplo n.º 2
0
    def setUpClass(cls):
        """Prepare the keys and payload to give to the CV"""
        contents = "random garbage to test as payload"
        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_Utilities.readPolicy(cls.tpm_policy)
        cls.vtpm_policy = TPM_Utilities.readPolicy(cls.vtpm_policy)

        """Allow targeting a specific API version (default latest)"""
        cls.api_version = common.API_VERSION
Exemplo n.º 3
0
def main(argv=sys.argv):
    parser = argparse.ArgumentParser(argv[0])
    parser.add_argument(
        '-c',
        '---command',
        action='store',
        dest='command',
        default='add',
        help="valid commands are add,delete,status,reactivate. defaults to add"
    )
    parser.add_argument('-t',
                        '--targethost',
                        action='store',
                        dest='node_ip',
                        help="the IP address of the host to provision")
    parser.add_argument('-v',
                        '--cv',
                        action='store',
                        dest='verifier_ip',
                        help="the IP address of the cloud verifier")
    parser.add_argument('-u',
                        '--uuid',
                        action='store',
                        dest='node_uuid',
                        help="UUID for the node to provision")
    parser.add_argument('-m',
                        '--vtpm',
                        action='store_true',
                        default=False,
                        help='Use to provision a system with a VTPM')
    parser.add_argument(
        '-f',
        '--file',
        action='store',
        default=None,
        help='Deliver the specified plaintext to the provisioned node')
    parser.add_argument(
        '--cert',
        action='store',
        dest='ca_dir',
        default=None,
        help=
        'Create and deliver a certificate using a CA created by ca-util. Pass in the CA directory or use "default" to use the standard dir'
    )
    parser.add_argument(
        '-k',
        '--key',
        action='store',
        dest='keyfile',
        help='an intermedia key file produced by user_data_encrypt')
    parser.add_argument(
        '-p',
        '--payload',
        action='store',
        default=None,
        help=
        'Specify the encrypted payload to deliver with encrypted keys specified by -k'
    )

    if common.DEVELOP_IN_ECLIPSE:
        #tmp = ['-c','add','-t','127.0.0.1','-v', '127.0.0.1','-u','C432FBB3-D2F1-4A97-9EF7-75BD81C866E9','-p','content_payload.txt','-k','content_keys.txt']
        tmp = [
            '-c', 'add', '-t', '127.0.0.1', '-v', '127.0.0.1', '-u',
            'C432FBB3-D2F1-4A97-9EF7-75BD81C866E9', '-f', 'tenant.py'
        ]
        #tmp = ['-c','delete','-t','127.0.0.1','-v','127.0.0.1','-u','C432FBB3-D2F1-4A97-9EF7-75BD81C866E9']
        #tmp = ['-c','reactivate','-t','127.0.0.1','-v','127.0.0.1','-u','C432FBB3-D2F1-4A97-9EF7-75BD81C866E9']
        #tmp = ['-c','list','-v', '127.0.0.1','-u','C432FBB3-D2F1-4A97-9EF7-75BD81C866E9']
    else:
        tmp = argv[1:]

    args = parser.parse_args(tmp)

    mytenant = Tenant(args.vtpm)

    if args.command != 'list' and args.node_ip is None:
        logger.error("-t/--targethost is required for command %s" %
                     args.command)

    if args.node_uuid is not None:
        mytenant.node_uuid = args.node_uuid
        # if the uuid is actually a public key, then hash it
        if mytenant.node_uuid.startswith('-----BEGIN PUBLIC KEY-----'):
            mytenant.node_uuid = hashlib.sha256(mytenant.node_uuid).hexdigest()
    else:
        logger.warning(
            "Using default UUID D432FBB3-D2F1-4A97-9EF7-75BD81C00000")
        mytenant.node_uuid = "D432FBB3-D2F1-4A97-9EF7-75BD81C00000"

    if args.command == 'add':
        # command line options can overwrite config values
        mytenant.cloudnode_ip = args.node_ip

        # if none
        if (args.file is None and args.keyfile is None
                and args.ca_dir is None):
            logger.error(
                "You must specify one of -k, -f, or --cert to specify the key/contents to be securely delivered to the node"
            )
            sys.exit(2)

        if args.keyfile is not None:
            if args.file is not None or args.ca_dir is not None:
                logger.error(
                    "You must specify one of -k, -f, or --cert to specify the key/contents to be securely delivered to the node"
                )
                sys.exit(2)

            # read the keys in
            f = open(args.keyfile, 'r')
            mytenant.K = base64.b64decode(f.readline())
            mytenant.U = base64.b64decode(f.readline())
            mytenant.V = base64.b64decode(f.readline())
            f.close()

            if args.payload is not None:
                f = open(args.payload, 'r')
                mytenant.payload = f.read()
                f.close()

        if args.file is not None:
            if args.keyfile is not None or args.ca_dir is not None:
                logger.error(
                    "You must specify one of -k, -f, or --cert to specify the key/contents to be securely delivered to the node"
                )
                sys.exit(2)

            with open(args.file, 'r') as f:
                contents = f.read()
            ret = user_data_encrypt.encrypt(contents)
            mytenant.K = ret['k']
            mytenant.U = ret['u']
            mytenant.V = ret['v']
            mytenant.payload = ret['ciphertext']

        if args.ca_dir is not None:
            if args.file is not None or args.keyfile is not None:
                logger.error(
                    "You must specify one of -k, -f, or --cert to specify the key/contents to be securely delivered to the node"
                )
                sys.exit(2)
            if args.ca_dir == 'default':
                args.ca_dir = common.CA_WORK_DIR

            if not os.path.exists(args.ca_dir):
                logger.error("CA directory does not exist")
                sys.exit(2)

            print "Creating a certificate for %s in CA directory %s" % (
                mytenant.node_uuid, args.ca_dir)
            ca_util.cmd_mkcert(args.ca_dir, mytenant.node_uuid)
            contents = ca_util.cmd_certpkg(args.ca_dir,
                                           mytenant.node_uuid,
                                           needfile=False)
            ret = user_data_encrypt.encrypt(contents)
            mytenant.K = ret['k']
            mytenant.U = ret['u']
            mytenant.V = ret['v']
            mytenant.payload = ret['ciphertext']

        if mytenant.payload is not None and len(
                mytenant.payload) > config.getint('tenant',
                                                  'max_payload_size'):
            raise Exception("Payload size %s exceeds max size %d" %
                            (len(mytenant.payload),
                             config.getint('tenant', 'max_payload_size')))

    if args.verifier_ip is not None:
        mytenant.cloudverifier_ip = args.verifier_ip

    try:
        if args.command == 'add':
            mytenant.preloop()
            mytenant.do_cv()
            mytenant.do_quote()
            if common.DEVELOP_IN_ECLIPSE:
                time.sleep(5)
                logger.debug("Deleting node from verifier")
                mytenant.do_cvdelete()
        elif args.command == 'delete':
            mytenant.do_cvdelete()
        elif args.command == 'status':
            mytenant.do_cvstatus()
        elif args.command == 'list':
            mytenant.do_cvstatus(listing=True)
        elif args.command == 'reactivate':
            mytenant.do_cvreactivate()
        else:
            logger.error("Invalid command specified %s" % (args.command))
            sys.exit(2)
    except Exception as e:
        logger.error(traceback.print_exc())
        logger.error("Error getting info from cloud verifier: " + str(e))
Exemplo n.º 4
0
    def init_add(self, args):
        # command line options can overwrite config values
        if "agent_ip" in args:
            self.cloudagent_ip = args["agent_ip"]

        if 'cv_agent_ip' in args and args['cv_agent_ip'] is not None:
            self.cv_cloudagent_ip = args['cv_agent_ip']
        else:
            self.cv_cloudagent_ip = self.cloudagent_ip

        # Make sure all keys exist in dictionary
        if "file" not in args:
            args["file"] = None
        if "keyfile" not in args:
            args["keyfile"] = None
        if "payload" not in args:
            args["payload"] = None
        if "ca_dir" not in args:
            args["ca_dir"] = None
        if "incl_dir" not in args:
            args["incl_dir"] = None
        if "ca_dir_pw" not in args:
            args["ca_dir_pw"] = None

        # Set up accepted algorithms
        self.accept_tpm_hash_algs = config.get(
            'tenant', 'accept_tpm_hash_algs').split(',')
        self.accept_tpm_encryption_algs = config.get(
            'tenant', 'accept_tpm_encryption_algs').split(',')
        self.accept_tpm_signing_algs = config.get(
            'tenant', 'accept_tpm_signing_algs').split(',')

        # Set up PCR values
        tpm_policy = config.get('tenant', 'tpm_policy')
        if "tpm_policy" in args and args["tpm_policy"] is not None:
            tpm_policy = args["tpm_policy"]
        self.tpm_policy = TPM_Utilities.readPolicy(tpm_policy)
        logger.info("TPM PCR Mask from policy is %s" % self.tpm_policy['mask'])

        vtpm_policy = config.get('tenant', 'vtpm_policy')
        if "vtpm_policy" in args and args["vtpm_policy"] is not None:
            vtpm_policy = args["vtpm_policy"]
        self.vtpm_policy = TPM_Utilities.readPolicy(vtpm_policy)
        logger.info("vTPM PCR Mask from policy is %s" %
                    self.vtpm_policy['mask'])

        # Read command-line path string IMA whitelist
        wl_data = None
        if "ima_whitelist" in args and args["ima_whitelist"] is not None:

            # Auto-enable IMA (or-bit mask)
            self.tpm_policy['mask'] = "0x%X" % (
                int(self.tpm_policy['mask'], 0) + (1 << common.IMA_PCR))

            if type(args["ima_whitelist"]) in [str, unicode]:
                if args["ima_whitelist"] == "default":
                    args["ima_whitelist"] = config.get('tenant',
                                                       'ima_whitelist')
                wl_data = ima.read_whitelist(args["ima_whitelist"])
            elif type(args["ima_whitelist"]) is list:
                wl_data = args["ima_whitelist"]
            else:
                raise UserError("Invalid whitelist provided")

        # Read command-line path string IMA exclude list
        excl_data = None
        if "ima_exclude" in args and args["ima_exclude"] is not None:
            if type(args["ima_exclude"]) in [str, unicode]:
                if args["ima_exclude"] == "default":
                    args["ima_exclude"] = config.get('tenant',
                                                     'ima_excludelist')
                excl_data = ima.read_excllist(args["ima_exclude"])
            elif type(args["ima_exclude"]) is list:
                excl_data = args["ima_exclude"]
            else:
                raise UserError("Invalid exclude list provided")

        # Set up IMA
        if TPM_Utilities.check_mask(self.tpm_policy['mask'],common.IMA_PCR) or \
            TPM_Utilities.check_mask(self.vtpm_policy['mask'],common.IMA_PCR):

            # Process IMA whitelists
            self.ima_whitelist = ima.process_whitelists(wl_data, excl_data)

        # if none
        if (args["file"] is None and args["keyfile"] is None
                and args["ca_dir"] is None):
            raise UserError(
                "You must specify one of -k, -f, or --cert to specify the key/contents to be securely delivered to the agent"
            )

        if args["keyfile"] is not None:
            if args["file"] is not None or args["ca_dir"] is not None:
                raise UserError(
                    "You must specify one of -k, -f, or --cert to specify the key/contents to be securely delivered to the agent"
                )

            # read the keys in
            if type(args["keyfile"]) is dict and "data" in args["keyfile"]:
                if type(args["keyfile"]["data"]) is list and len(
                        args["keyfile"]["data"]) == 1:
                    keyfile = args["keyfile"]["data"][0]
                    if keyfile is None:
                        raise UserError("Invalid key file contents")
                    f = StringIO.StringIO(keyfile)
                else:
                    raise UserError("Invalid key file provided")
            else:
                f = open(args["keyfile"], 'r')
            self.K = base64.b64decode(f.readline())
            self.U = base64.b64decode(f.readline())
            self.V = base64.b64decode(f.readline())
            f.close()

            # read the payload in (opt.)
            if type(args["payload"]) is dict and "data" in args["payload"]:
                if type(args["payload"]["data"]) is list and len(
                        args["payload"]["data"]) > 0:
                    self.payload = args["payload"]["data"][0]
            else:
                if args["payload"] is not None:
                    f = open(args["payload"], 'r')
                    self.payload = f.read()
                    f.close()

        if args["file"] is not None:
            if args["keyfile"] is not None or args["ca_dir"] is not None:
                raise UserError(
                    "You must specify one of -k, -f, or --cert to specify the key/contents to be securely delivered to the agent"
                )

            if type(args["file"]) is dict and "data" in args["file"]:
                if type(args["file"]["data"]) is list and len(
                        args["file"]["data"]) > 0:
                    contents = args["file"]["data"][0]
                    if contents is None:
                        raise UserError("Invalid file payload contents")
                else:
                    raise UserError("Invalid file payload provided")
            else:
                with open(args["file"], 'r') as f:
                    contents = f.read()
            ret = user_data_encrypt.encrypt(contents)
            self.K = ret['k']
            self.U = ret['u']
            self.V = ret['v']
            self.payload = ret['ciphertext']

        if args["ca_dir"] is None and args["incl_dir"] is not None:
            raise UserError(
                "--include option is only valid when used with --cert")
        if args["ca_dir"] is not None:
            if args["file"] is not None or args["keyfile"] is not None:
                raise UserError(
                    "You must specify one of -k, -f, or --cert to specify the key/contents to be securely delivered to the agent"
                )
            if args["ca_dir"] == 'default':
                args["ca_dir"] = common.CA_WORK_DIR

            if "ca_dir_pw" in args and args["ca_dir_pw"] is not None:
                ca_util.setpassword(args["ca_dir_pw"])

            if not os.path.exists(args["ca_dir"]):
                logger.warning(" CA directory does not exist.  Creating...")
                ca_util.cmd_init(args["ca_dir"])

            if not os.path.exists("%s/%s-private.pem" %
                                  (args["ca_dir"], self.agent_uuid)):
                ca_util.cmd_mkcert(args["ca_dir"], self.agent_uuid)

            cert_pkg, serial, subject = ca_util.cmd_certpkg(
                args["ca_dir"], self.agent_uuid)

            # support revocation
            if not os.path.exists(
                    "%s/RevocationNotifier-private.pem" % args["ca_dir"]):
                ca_util.cmd_mkcert(args["ca_dir"], "RevocationNotifier")
            rev_package, _, _ = ca_util.cmd_certpkg(args["ca_dir"],
                                                    "RevocationNotifier")

            # extract public and private keys from package
            sf = cStringIO.StringIO(rev_package)
            with zipfile.ZipFile(sf) as zf:
                privkey = zf.read("RevocationNotifier-private.pem")
                cert = zf.read("RevocationNotifier-cert.crt")

            # put the cert of the revoker into the cert package
            sf = StringIO.StringIO(cert_pkg)
            with zipfile.ZipFile(sf, 'a',
                                 compression=zipfile.ZIP_STORED) as zf:
                zf.writestr('RevocationNotifier-cert.crt', cert)

                # add additional files to zip
                if args["incl_dir"] is not None:
                    if type(args["incl_dir"]) is dict and "data" in args[
                            "incl_dir"] and "name" in args["incl_dir"]:
                        if type(args["incl_dir"]["data"]) is list and type(
                                args["incl_dir"]["name"]) is list:
                            if len(args["incl_dir"]["data"]) != len(
                                    args["incl_dir"]["name"]):
                                raise UserError("Invalid incl_dir provided")
                            for i in range(len(args["incl_dir"]["data"])):
                                zf.writestr(
                                    os.path.basename(
                                        args["incl_dir"]["name"][i]),
                                    args["incl_dir"]["data"][i])
                    else:
                        if os.path.exists(args["incl_dir"]):
                            files = next(os.walk(args["incl_dir"]))[2]
                            for filename in files:
                                with open(
                                        "%s/%s" % (args["incl_dir"], filename),
                                        'rb') as f:
                                    zf.writestr(os.path.basename(f.name),
                                                f.read())
                        else:
                            logger.warn(
                                "Specified include directory %s does not exist.  Skipping..."
                                % args["incl_dir"])

            cert_pkg = sf.getvalue()

            # put the private key into the data to be send to the CV
            self.revocation_key = privkey

            # encrypt up the cert package
            ret = user_data_encrypt.encrypt(cert_pkg)
            self.K = ret['k']
            self.U = ret['u']
            self.V = ret['v']
            self.metadata = {'cert_serial': serial, 'subject': subject}
            self.payload = ret['ciphertext']

        if self.payload is not None and len(self.payload) > config.getint(
                'tenant', 'max_payload_size'):
            raise UserError("Payload size %s exceeds max size %d" % (len(
                self.payload), config.getint('tenant', 'max_payload_size')))