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)
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
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))
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')))