def encrypt_inplace_with_seperate_header_file(passphrase_file, device_item, disk_util, bek_util, ongoing_item_config=None): """ if ongoing_item_config is not None, then this is a resume case. """ current_phase = CommonVariables.EncryptionPhaseEncryptDevice if(ongoing_item_config is None): ongoing_item_config = OnGoingItemConfig(encryption_environment=encryption_environment,logger=logger) mapper_name = str(uuid.uuid4()) ongoing_item_config.current_block_size = CommonVariables.default_block_size ongoing_item_config.current_slice_index = 0 ongoing_item_config.device_size = device_item.size ongoing_item_config.file_system = device_item.file_system ongoing_item_config.mapper_name = mapper_name ongoing_item_config.mount_point = device_item.mount_point ongoing_item_config.mount_point = device_item.mount_point ongoing_item_config.original_dev_name_path = os.path.join('/dev/', device_item.name) ongoing_item_config.original_dev_path = os.path.join('/dev/disk/by-uuid', device_item.uuid) luks_header_file = disk_util.create_luks_header(mapper_name=mapper_name) if(luks_header_file is None): logger.log(msg="create header file failed", level=CommonVariables.ErrorLevel) return current_phase else: ongoing_item_config.luks_header_file_path = luks_header_file ongoing_item_config.phase = CommonVariables.EncryptionPhaseEncryptDevice ongoing_item_config.commit() else: logger.log(msg = "ongoing item config is not none, this is resuming: " + str(ongoing_item_config),level = CommonVariables.WarningLevel) current_phase = ongoing_item_config.get_phase() while(current_phase != CommonVariables.EncryptionPhaseDone): if(current_phase == CommonVariables.EncryptionPhaseEncryptDevice): disabled = False try: mapper_name = ongoing_item_config.get_mapper_name() original_dev_path = ongoing_item_config.get_original_dev_path() luks_header_file = ongoing_item_config.get_header_file_path() disabled = toggle_se_linux_for_centos7(True) encrypt_result = disk_util.encrypt_disk(dev_path = original_dev_path, passphrase_file = passphrase_file, \ mapper_name = mapper_name, header_file = luks_header_file) if(encrypt_result != CommonVariables.process_success): logger.log(msg=("the encrypton for " + str(original_dev_path) + " failed"),level=CommonVariables.ErrorLevel) return current_phase else: ongoing_item_config.phase = CommonVariables.EncryptionPhaseCopyData ongoing_item_config.commit() current_phase = CommonVariables.EncryptionPhaseCopyData finally: toggle_se_linux_for_centos7(False) elif(current_phase == CommonVariables.EncryptionPhaseCopyData): disabled = False try: mapper_name = ongoing_item_config.get_mapper_name() original_dev_path = ongoing_item_config.get_original_dev_path() luks_header_file = ongoing_item_config.get_header_file_path() disabled = toggle_se_linux_for_centos7(True) device_mapper_path = os.path.join("/dev/mapper", mapper_name) if(not os.path.exists(device_mapper_path)): open_result = disk_util.luks_open(passphrase_file = passphrase_file, dev_path = original_dev_path, \ mapper_name = mapper_name, header_file = luks_header_file) if(open_result != CommonVariables.process_success): logger.log(msg=("the luks open for " + str(original_dev_path) + " failed"),level = CommonVariables.ErrorLevel) return current_phase else: logger.log(msg = "the device mapper path existed, so skip the luks open.", level = CommonVariables.InfoLevel) device_size = ongoing_item_config.get_device_size() current_slice_index = ongoing_item_config.get_current_slice_index() if(current_slice_index is None): ongoing_item_config.current_slice_index = 0 ongoing_item_config.current_source_path = original_dev_path ongoing_item_config.current_destination = device_mapper_path ongoing_item_config.current_total_copy_size = device_size ongoing_item_config.from_end = True ongoing_item_config.commit() copy_result = disk_util.copy(ongoing_item_config = ongoing_item_config) if(copy_result != CommonVariables.success): error_message = "the copying result is " + str(copy_result) + " so skip the mounting" logger.log(msg = (error_message), level = CommonVariables.ErrorLevel) return current_phase else: crypt_item_to_update = CryptItem() crypt_item_to_update.mapper_name = mapper_name original_dev_name_path = ongoing_item_config.get_original_dev_name_path() crypt_item_to_update.dev_path = original_dev_name_path crypt_item_to_update.luks_header_path = luks_header_file crypt_item_to_update.file_system = ongoing_item_config.get_file_system() # if the original mountpoint is empty, then leave # it as None mount_point = ongoing_item_config.get_mount_point() if mount_point == "" or mount_point is None: crypt_item_to_update.mount_point = "None" else: crypt_item_to_update.mount_point = mount_point update_crypt_item_result = disk_util.update_crypt_item(crypt_item_to_update) if(not update_crypt_item_result): logger.log(msg="update crypt item failed",level = CommonVariables.ErrorLevel) if(crypt_item_to_update.mount_point != "None"): disk_util.mount_filesystem(device_mapper_path, mount_point) else: logger.log("the crypt_item_to_update.mount_point is None, so we do not mount it.") current_phase = CommonVariables.EncryptionPhaseDone ongoing_item_config.phase = current_phase ongoing_item_config.commit() ongoing_item_config.clear_config() return current_phase finally: toggle_se_linux_for_centos7(False)
def daemon(): hutil.do_parse_context('Executing') try: # Ensure the same configuration is executed only once # If the previous enable failed, we do not have retry logic here. # TODO Remount all encryption_marker = EncryptionMarkConfig(logger, encryption_environment) if(encryption_marker.config_file_exists()): logger.log("encryption is marked.") """ search for the bek volume, then mount it:) """ disk_util = DiskUtil(hutil, MyPatching, logger, encryption_environment) encryption_config = EncryptionConfig(encryption_environment,logger) bek_passphrase_file = None """ try to find the attached bek volume, and use the file to mount the crypted volumes, and if the passphrase file is found, then we will re-use it for the future. """ bek_util = BekUtil(disk_util, logger) if(encryption_config.config_file_exists()): bek_passphrase_file = bek_util.get_bek_passphrase_file(encryption_config) if(bek_passphrase_file is None): hutil.do_exit(0, 'Enable', CommonVariables.extension_error_status, CommonVariables.passphrase_file_not_found, 'Passphrase file not found.') else: """ check whether there's a scheduled encryption task """ logger.log("trying to install the extras") MyPatching.install_extras() mount_all_result = disk_util.mount_all() if(mount_all_result != CommonVariables.process_success): logger.log(msg=("mount all failed with code " + str(mount_all_result)), level=CommonVariables.ErrorLevel) """ TODO: resuming the encryption for rebooting suddenly scenario we need the special handling is because the half done device can be a error state: say, the file system header missing.so it could be identified. """ ongoing_item_config = OnGoingItemConfig(encryption_environment=encryption_environment, logger=logger) if(ongoing_item_config.config_file_exists()): header_file_path = ongoing_item_config.get_header_file_path() mount_point = ongoing_item_config.get_mount_point() if(not none_or_empty(mount_point)): logger.log("mount point is not empty, trying to unmount it first." + str(mount_point)) umount_status_code = disk_util.umount(mount_point) logger.log("unmount return code is " + str(umount_status_code)) if(none_or_empty(header_file_path)): encryption_result_phase = encrypt_inplace_without_seperate_header_file(passphrase_file = bek_passphrase_file, device_item = None,\ disk_util = disk_util, bek_util = bek_util, ongoing_item_config = ongoing_item_config) else: encryption_result_phase = encrypt_inplace_with_seperate_header_file(passphrase_file = bek_passphrase_file, device_item = None,\ disk_util = disk_util, bek_util = bek_util, ongoing_item_config = ongoing_item_config) """ if the resuming failed, we should fail. """ if(encryption_result_phase != CommonVariables.EncryptionPhaseDone): hutil.do_exit(exit_code = 0, operation = 'Enable', status = CommonVariables.extension_error_status, code = CommonVariables.encryption_failed,\ message = 'resuming encryption for ' + str(ongoing_item_config.original_dev_path) + ' failed.') else: ongoing_item_config.clear_config() else: failed_item = None if(encryption_marker.get_current_command() == CommonVariables.EnableEncryption): failed_item = enable_encryption_all_in_place(passphrase_file= bek_passphrase_file, encryption_marker = encryption_marker, disk_util = disk_util, bek_util = bek_util) elif(encryption_marker.get_current_command() == CommonVariables.EnableEncryptionFormat): failed_item = enable_encryption_format(passphrase = bek_passphrase_file, encryption_marker = encryption_marker, disk_util = disk_util) else: logger.log(msg = ("command " + str(encryption_marker.get_current_command()) + " not supported"), level = CommonVariables.ErrorLevel) #TODO do exit here if(failed_item != None): hutil.do_exit(exit_code = 0, operation = 'Enable', status = CommonVariables.extension_error_status, code = CommonVariables.encryption_failed,\ message = 'encryption failed for ' + str(failed_item)) else: hutil.do_exit(exit_code = 0, operation = 'Enable', status = CommonVariables.extension_success_status, code = str(CommonVariables.success), message = encryption_config.get_secret_id()) except Exception as e: # mount the file systems back. error_msg = ("Failed to enable the extension with error: %s, stack trace: %s" % (str(e), traceback.format_exc())) logger.log(msg = error_msg, level = CommonVariables.ErrorLevel) hutil.do_exit(exit_code = 0, operation = 'Enable', status = CommonVariables.extension_error_status, code = str(CommonVariables.encryption_failed), \ message = error_msg) finally: encryption_marker = EncryptionMarkConfig(logger, encryption_environment) #TODO not remove it, backed it up. logger.log("clearing the encryption mark.") encryption_marker.clear_config() bek_util.umount_azure_passhprase(encryption_config) logger.log("finally in daemon")
def encrypt_inplace_without_seperate_header_file(passphrase_file, device_item, disk_util, bek_util, ongoing_item_config=None): """ if ongoing_item_config is not None, then this is a resume case. this function will return the phase """ current_phase = CommonVariables.EncryptionPhaseBackupHeader if(ongoing_item_config is None): ongoing_item_config = OnGoingItemConfig(encryption_environment = encryption_environment, logger = logger) ongoing_item_config.current_block_size = CommonVariables.default_block_size ongoing_item_config.current_slice_index = 0 ongoing_item_config.device_size = device_item.size ongoing_item_config.file_system = device_item.file_system ongoing_item_config.luks_header_file_path = None ongoing_item_config.mapper_name = str(uuid.uuid4()) ongoing_item_config.mount_point = device_item.mount_point ongoing_item_config.original_dev_name_path = os.path.join('/dev', device_item.name) ongoing_item_config.original_dev_path = os.path.join('/dev', device_item.name) ongoing_item_config.phase = CommonVariables.EncryptionPhaseBackupHeader ongoing_item_config.commit() else: logger.log(msg = "ongoing item config is not none, this is resuming: " + str(ongoing_item_config), level = CommonVariables.WarningLevel) logger.log(msg=("encrypting device item:" + str(ongoing_item_config.get_original_dev_path()))) # we only support ext file systems. current_phase = ongoing_item_config.get_phase() original_dev_path = ongoing_item_config.get_original_dev_path() mapper_name = ongoing_item_config.get_mapper_name() device_size = ongoing_item_config.get_device_size() luks_header_size = CommonVariables.luks_header_size size_shrink_to = (device_size - luks_header_size) / CommonVariables.sector_size while(current_phase != CommonVariables.EncryptionPhaseDone): if(current_phase == CommonVariables.EncryptionPhaseBackupHeader): if(not ongoing_item_config.get_file_system().lower() in ["ext2","ext3","ext4"]): logger.log(msg = "we only support ext file systems for centos 6.5/6.6/6.7 and redhat 6.7", level = CommonVariables.WarningLevel) return current_phase chk_shrink_result = disk_util.check_shrink_fs(dev_path = original_dev_path,size_shrink_to = size_shrink_to) if(chk_shrink_result != CommonVariables.process_success): logger.log(msg = ("check shrink fs failed with code " + str(chk_shrink_result) + " for: " + str(original_dev_path)), level = CommonVariables.ErrorLevel) logger.log(msg = "your file system may not have enough space to do the encryption.") return current_phase else: ongoing_item_config.current_slice_index = 0 ongoing_item_config.current_source_path = original_dev_path ongoing_item_config.current_destination = encryption_environment.copy_header_slice_file_path ongoing_item_config.current_total_copy_size = CommonVariables.default_block_size ongoing_item_config.from_end = False ongoing_item_config.header_slice_file_path = encryption_environment.copy_header_slice_file_path ongoing_item_config.original_dev_path = original_dev_path ongoing_item_config.commit() if(os.path.exists(encryption_environment.copy_header_slice_file_path)): os.remove(encryption_environment.copy_header_slice_file_path) copy_result = disk_util.copy(ongoing_item_config = ongoing_item_config) if(copy_result != CommonVariables.process_success): logger.log(msg=("copy the header block failed, return code is: " + str(copy_result)),level=CommonVariables.ErrorLevel) return current_phase else: ongoing_item_config.current_slice_index = 0 ongoing_item_config.phase = CommonVariables.EncryptionPhaseEncryptDevice ongoing_item_config.commit() current_phase = CommonVariables.EncryptionPhaseEncryptDevice elif(current_phase == CommonVariables.EncryptionPhaseEncryptDevice): encrypt_result = disk_util.encrypt_disk(dev_path = original_dev_path, passphrase_file = passphrase_file, mapper_name = mapper_name, header_file = None) # after the encrypt_disk without seperate header, then the uuid # would change. if(encrypt_result != CommonVariables.process_success): logger.log(msg = "encrypt file system failed.", level = CommonVariables.ErrorLevel) return current_phase else: ongoing_item_config.current_slice_index = 0 ongoing_item_config.phase = CommonVariables.EncryptionPhaseCopyData ongoing_item_config.commit() current_phase = CommonVariables.EncryptionPhaseCopyData elif(current_phase == CommonVariables.EncryptionPhaseCopyData): device_mapper_path = os.path.join(CommonVariables.dev_mapper_root, mapper_name) ongoing_item_config.current_destination = device_mapper_path ongoing_item_config.current_source_path = original_dev_path ongoing_item_config.current_total_copy_size = (device_size - luks_header_size) ongoing_item_config.from_end = True ongoing_item_config.phase = CommonVariables.EncryptionPhaseCopyData ongoing_item_config.commit() copy_result = disk_util.copy(ongoing_item_config = ongoing_item_config) if(copy_result != CommonVariables.process_success): logger.log(msg = ("copy the main content block failed, return code is: " + str(copy_result)),level = CommonVariables.ErrorLevel) return current_phase else: ongoing_item_config.phase = CommonVariables.EncryptionPhaseRecoverHeader ongoing_item_config.commit() current_phase = CommonVariables.EncryptionPhaseRecoverHeader elif(current_phase == CommonVariables.EncryptionPhaseRecoverHeader): ongoing_item_config.from_end = False backed_up_header_slice_file_path = ongoing_item_config.get_header_slice_file_path() ongoing_item_config.current_slice_index = 0 ongoing_item_config.current_source_path = backed_up_header_slice_file_path device_mapper_path = os.path.join(CommonVariables.dev_mapper_root, mapper_name) ongoing_item_config.current_destination = device_mapper_path ongoing_item_config.current_total_copy_size = CommonVariables.default_block_size ongoing_item_config.commit() copy_result = disk_util.copy(ongoing_item_config = ongoing_item_config) if(copy_result == CommonVariables.process_success): crypt_item_to_update = CryptItem() crypt_item_to_update.mapper_name = mapper_name original_dev_name_path = ongoing_item_config.get_original_dev_name_path() crypt_item_to_update.dev_path = original_dev_name_path crypt_item_to_update.luks_header_path = "None" crypt_item_to_update.file_system = ongoing_item_config.get_file_system() # if the original mountpoint is empty, then leave # it as None mount_point = ongoing_item_config.get_mount_point() if mount_point == "" or mount_point is None: crypt_item_to_update.mount_point = "None" else: crypt_item_to_update.mount_point = mount_point update_crypt_item_result = disk_util.update_crypt_item(crypt_item_to_update) if(not update_crypt_item_result): logger.log(msg="update crypt item failed",level = CommonVariables.ErrorLevel) if(os.path.exists(encryption_environment.copy_header_slice_file_path)): os.remove(encryption_environment.copy_header_slice_file_path) current_phase = CommonVariables.EncryptionPhaseDone ongoing_item_config.phase = current_phase ongoing_item_config.commit() expand_fs_result = disk_util.expand_fs(dev_path=device_mapper_path) if(crypt_item_to_update.mount_point != "None"): disk_util.mount_filesystem(device_mapper_path, ongoing_item_config.get_mount_point()) else: logger.log("the crypt_item_to_update.mount_point is None, so we do not mount it.") ongoing_item_config.clear_config() if(expand_fs_result != CommonVariables.process_success): logger.log(msg=("expand fs result is: " + str(expand_fs_result)),level = CommonVariables.ErrorLevel) return current_phase else: logger.log(msg=("recover header failed result is: " + str(copy_result)),level = CommonVariables.ErrorLevel) return current_phase