Пример #1
0
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)
Пример #2
0
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")
Пример #3
0
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