def update_encryption_settings()

in VMEncryption/main/handle.py [0:0]


def update_encryption_settings():
    hutil.do_parse_context('UpdateEncryptionSettings')
    logger.log('Updating encryption settings')

    # re-install extra packages like cryptsetup if no longer on system from earlier enable
    try:
        DistroPatcher.install_extras()
    except Exception as e:
        message = "Failed to update encryption settings with error: {0}, stack trace: {1}".format(e, traceback.format_exc())
        hutil.do_exit(exit_code=CommonVariables.missing_dependency,
                      operation='UpdateEncryptionSettings',
                      status=CommonVariables.extension_error_status,
                      code=str(CommonVariables.missing_dependency),
                      message=message)

    encryption_config = EncryptionConfig(encryption_environment, logger)
    config_secret_seq = encryption_config.get_secret_seq_num()
    current_secret_seq_num = int(config_secret_seq if config_secret_seq else -1)
    update_call_seq_num = hutil.get_current_seq()

    logger.log("Current secret was created in operation #{0}".format(current_secret_seq_num))
    logger.log("The update call is operation #{0}".format(update_call_seq_num))

    executor = CommandExecutor(logger)
    executor.Execute("mount /boot")

    try:
        disk_util = DiskUtil(hutil=hutil, patching=DistroPatcher, logger=logger, encryption_environment=encryption_environment)
        bek_util = BekUtil(disk_util, logger)

        extension_parameter = ExtensionParameter(hutil, logger, DistroPatcher, encryption_environment, get_protected_settings(), get_public_settings())
        existing_passphrase_file = bek_util.get_bek_passphrase_file(encryption_config)

        if current_secret_seq_num < update_call_seq_num:
            if extension_parameter.passphrase is None or extension_parameter.passphrase == "":
                extension_parameter.passphrase = bek_util.generate_passphrase(extension_parameter.KeyEncryptionAlgorithm)

            logger.log('Recreating secret to store in the KeyVault')

            keyVaultUtil = KeyVaultUtil(logger)

            temp_keyfile = tempfile.NamedTemporaryFile(delete=False)
            temp_keyfile.write(extension_parameter.passphrase)
            temp_keyfile.close()

            for crypt_item in disk_util.get_crypt_items():
                if not crypt_item:
                    continue

                before_keyslots = disk_util.luks_dump_keyslots(crypt_item.dev_path, crypt_item.luks_header_path)

                logger.log("Before key addition, keyslots for {0}: {1}".format(crypt_item.dev_path, before_keyslots))

                logger.log("Adding new key for {0}".format(crypt_item.dev_path))

                luks_add_result = disk_util.luks_add_key(passphrase_file=existing_passphrase_file,
                                                         dev_path=crypt_item.dev_path,
                                                         mapper_name=crypt_item.mapper_name,
                                                         header_file=crypt_item.luks_header_path,
                                                         new_key_path=temp_keyfile.name)

                logger.log("luks add result is {0}".format(luks_add_result))

                after_keyslots = disk_util.luks_dump_keyslots(crypt_item.dev_path, crypt_item.luks_header_path)

                logger.log("After key addition, keyslots for {0}: {1}".format(crypt_item.dev_path, after_keyslots))

                new_keyslot = list(map(lambda x: x[0] != x[1], zip(before_keyslots, after_keyslots))).index(True)

                logger.log("New key was added in keyslot {0}".format(new_keyslot))

                # crypt_item.current_luks_slot = new_keyslot

                # disk_util.update_crypt_item(crypt_item)

            logger.log("New key successfully added to all encrypted devices")

            if DistroPatcher.distro_info[0] == "Ubuntu":
                logger.log("Updating initrd image with new osluksheader.")
                executor.Execute("update-initramfs -u -k all", True)

            if DistroPatcher.distro_info[0] == "redhat" or DistroPatcher.distro_info[0] == "centos":
                distro_version = DistroPatcher.distro_info[1]

                if distro_version.startswith('7.'):
                    logger.log("Updating initrd image with new osluksheader.")
                    executor.ExecuteInBash("/usr/sbin/dracut -f -v --kver `grubby --default-kernel | sed 's|/boot/vmlinuz-||g'`", True)

            os.unlink(temp_keyfile.name)

            # install Python ADAL support if using client certificate authentication
            if extension_parameter.AADClientCertThumbprint:
                DistroPatcher.install_adal()

            kek_secret_id_created = keyVaultUtil.create_kek_secret(Passphrase=extension_parameter.passphrase,
                                                                   KeyVaultURL=extension_parameter.KeyVaultURL,
                                                                   KeyEncryptionKeyURL=extension_parameter.KeyEncryptionKeyURL,
                                                                   AADClientID=extension_parameter.AADClientID,
                                                                   AADClientCertThumbprint=extension_parameter.AADClientCertThumbprint,
                                                                   KeyEncryptionAlgorithm=extension_parameter.KeyEncryptionAlgorithm,
                                                                   AADClientSecret=extension_parameter.AADClientSecret,
                                                                   DiskEncryptionKeyFileName=extension_parameter.DiskEncryptionKeyFileName)

            if kek_secret_id_created is None:
                hutil.do_exit(exit_code=CommonVariables.create_encryption_secret_failed,
                              operation='UpdateEncryptionSettings',
                              status=CommonVariables.extension_error_status,
                              code=str(CommonVariables.create_encryption_secret_failed),
                              message='UpdateEncryptionSettings failed.')
            else:
                encryption_config.passphrase_file_name = extension_parameter.DiskEncryptionKeyFileName
                encryption_config.secret_id = kek_secret_id_created
                encryption_config.secret_seq_num = hutil.get_current_seq()
                encryption_config.commit()

                shutil.copy(existing_passphrase_file, encryption_environment.bek_backup_path)
                logger.log("Backed up BEK at {0}".format(encryption_environment.bek_backup_path))

                hutil.do_exit(exit_code=0,
                              operation='UpdateEncryptionSettings',
                              status=CommonVariables.extension_success_status,
                              code=str(CommonVariables.success),
                              message=str(kek_secret_id_created))
        else:
            logger.log('Secret has already been updated')
            mount_encrypted_disks(disk_util, bek_util, existing_passphrase_file, encryption_config)
            disk_util.log_lsblk_output()
            hutil.exit_if_same_seq()

            # remount bek volume
            existing_passphrase_file = bek_util.get_bek_passphrase_file(encryption_config)

            if extension_parameter.passphrase and extension_parameter.passphrase != file(existing_passphrase_file).read():
                logger.log("The new passphrase has not been placed in BEK volume yet")
                logger.log("Skipping removal of old passphrase")
                exit_without_status_report()

            logger.log('Removing old passphrase')

            for crypt_item in disk_util.get_crypt_items():
                if not crypt_item:
                    continue

                if filecmp.cmp(existing_passphrase_file, encryption_environment.bek_backup_path):
                    logger.log('Current BEK and backup are the same, skipping removal')
                    continue

                logger.log('Removing old passphrase from {0}'.format(crypt_item.dev_path))

                keyslots = disk_util.luks_dump_keyslots(crypt_item.dev_path, crypt_item.luks_header_path)
                logger.log("Keyslots before removal: {0}".format(keyslots))

                luks_remove_result = disk_util.luks_remove_key(passphrase_file=encryption_environment.bek_backup_path,
                                                               dev_path=crypt_item.dev_path,
                                                               header_file=crypt_item.luks_header_path)
                logger.log("luks remove result is {0}".format(luks_remove_result))

                keyslots = disk_util.luks_dump_keyslots(crypt_item.dev_path, crypt_item.luks_header_path)
                logger.log("Keyslots after removal: {0}".format(keyslots))

            logger.log("Old key successfully removed from all encrypted devices")

            if DistroPatcher.distro_info[0] == "Ubuntu":
                logger.log("Updating initrd image with new osluksheader.")
                executor.Execute("update-initramfs -u -k all", True)

            if DistroPatcher.distro_info[0] == "redhat" or DistroPatcher.distro_info[0] == "centos":
                distro_version = DistroPatcher.distro_info[1]

                if distro_version.startswith('7.'):
                    logger.log("Updating initrd image with new osluksheader.")
                    executor.ExecuteInBash("/usr/sbin/dracut -f -v --kver `grubby --default-kernel | sed 's|/boot/vmlinuz-||g'`", True)

            hutil.save_seq()
            extension_parameter.commit()
            os.unlink(encryption_environment.bek_backup_path)

        hutil.do_exit(exit_code=0,
                      operation='UpdateEncryptionSettings',
                      status=CommonVariables.extension_success_status,
                      code=str(CommonVariables.success),
                      message='Encryption settings updated')
    except Exception as e:
        message = "Failed to update encryption settings with error: {0}, stack trace: {1}".format(e, traceback.format_exc())
        logger.log(msg=message, level=CommonVariables.ErrorLevel)
        hutil.do_exit(exit_code=CommonVariables.unknown_error,
                      operation='UpdateEncryptionSettings',
                      status=CommonVariables.extension_error_status,
                      code=str(CommonVariables.unknown_error),
                      message=message)