Implement alternate AES key loading as in #56

This commit is contained in:
deajan 2024-05-06 18:44:46 +02:00
parent b01590871d
commit 8203d5c6b3
5 changed files with 58 additions and 12 deletions

View file

@ -26,7 +26,7 @@ from npbackup.__debug__ import _DEBUG
from npbackup.common import execution_logs
from npbackup.core import upgrade_runner
from npbackup.core.i18n_helper import _t
from npbackup import key_management
if os.name == "nt":
from npbackup.windows.task import create_scheduled_task
@ -304,7 +304,9 @@ This is free software, and you are welcome to redistribute it under certain cond
json_error_logging(False, msg, "critical")
sys.exit(70)
full_config = npbackup.configuration.load_config(CONFIG_FILE)
aes_key = key_management.get_aes_key()
full_config = npbackup.configuration.load_config(CONFIG_FILE, aes_key)
if not full_config:
msg = "Cannot obtain repo config"
json_error_logging(False, msg, "critical")

View file

@ -7,7 +7,7 @@ __intname__ = "npbackup.configuration"
__author__ = "Orsiris de Jong"
__copyright__ = "Copyright (C) 2022-2024 NetInvent"
__license__ = "GPL-3.0-only"
__build__ = "2024042301"
__build__ = "2024050301"
__version__ = "npbackup 3.0.0+"
MIN_CONF_VERSION = 3.0
@ -690,7 +690,9 @@ def _load_config_file(config_file: Path) -> Union[bool, dict]:
return False
def load_config(config_file: Path) -> Optional[dict]:
def load_config(config_file: Path, aes_key: bytes = None) -> Optional[dict]:
if not aes_key:
aes_key = AES_KEY
logger.info(f"Loading configuration file {config_file}")
full_config = _load_config_file(config_file)
@ -726,7 +728,7 @@ def load_config(config_file: Path) -> Optional[dict]:
config_file_is_updated = True
# Decrypt variables
full_config = crypt_config(
full_config, AES_KEY, ENCRYPTED_OPTIONS, operation="decrypt"
full_config, aes_key, ENCRYPTED_OPTIONS, operation="decrypt"
)
if full_config == False:
if EARLIER_AES_KEY:
@ -760,20 +762,22 @@ def load_config(config_file: Path) -> Optional[dict]:
return full_config
def save_config(config_file: Path, full_config: dict) -> bool:
def save_config(config_file: Path, full_config: dict, aes_key: bytes = None) -> bool:
if not aes_key:
aes_key = AES_KEY
try:
with open(config_file, "w", encoding="utf-8") as file_handle:
full_config = inject_permissions_into_full_config(full_config)
if not is_encrypted(full_config):
full_config = crypt_config(
full_config, AES_KEY, ENCRYPTED_OPTIONS, operation="encrypt"
full_config, aes_key, ENCRYPTED_OPTIONS, operation="encrypt"
)
yaml = YAML(typ="rt")
yaml.dump(full_config, file_handle)
# Since yaml is a "pointer object", we need to decrypt after saving
full_config = crypt_config(
full_config, AES_KEY, ENCRYPTED_OPTIONS, operation="decrypt"
full_config, aes_key, ENCRYPTED_OPTIONS, operation="decrypt"
)
# We also need to extract permissions again
full_config = extract_permissions_from_full_config(full_config)

View file

@ -55,10 +55,13 @@ from npbackup.path_helper import CURRENT_DIR
from npbackup.__version__ import version_string
from npbackup.__debug__ import _DEBUG
from npbackup.restic_wrapper import ResticRunner
from npbackup import key_management
logger = getLogger()
backend_binary = None
aes_key = key_management.get_aes_key()
sg.theme(PYSIMPLEGUI_THEME)
sg.SetOptions(icon=OEM_ICON)
@ -451,7 +454,7 @@ def _main_gui(viewer_mode: bool):
if not values["-config_file-"] or not config_file.exists():
sg.PopupError(_t("generic.file_does_not_exist"))
continue
full_config = npbackup.configuration.load_config(config_file)
full_config = npbackup.configuration.load_config(config_file, aes_key)
if not full_config:
sg.PopupError(_t("generic.bad_file"))
continue
@ -549,7 +552,7 @@ def _main_gui(viewer_mode: bool):
Load config file until we got something
"""
if config_file:
full_config = npbackup.configuration.load_config(config_file)
full_config = npbackup.configuration.load_config(config_file, aes_key)
if not config_file.exists():
config_file = None
if not full_config:
@ -569,7 +572,7 @@ def _main_gui(viewer_mode: bool):
)
if config_file:
logger.info(f"Using configuration file {config_file}")
full_config = npbackup.configuration.load_config(config_file)
full_config = npbackup.configuration.load_config(config_file, aes_key)
if not full_config:
sg.PopupError(f"{_t('main_gui.config_error')} {config_file}")
config_file = None

View file

@ -31,11 +31,13 @@ from npbackup.customization import (
TREE_ICON,
INHERITED_TREE_ICON,
)
from npbackup import key_management
if os.name == "nt":
from npbackup.windows.task import create_scheduled_task
logger = getLogger()
aes_key = key_management.get_aes_key()
# Monkeypatching PySimpleGUI
@ -1922,7 +1924,7 @@ def config_gui(full_config: dict, config_file: str):
full_config = update_config_dict(
full_config, current_object_type, current_object_name, values
)
result = configuration.save_config(config_file, full_config)
result = configuration.save_config(config_file, full_config, aes_key)
if result:
sg.Popup(_t("config_gui.configuration_saved"), keep_on_top=True)
logger.info("Configuration saved successfully.")

View file

@ -0,0 +1,35 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# This file is part of npbackup
__intname__ = "npbackup.get_key"
import os
from command_runner import command_runner
def get_aes_key():
"""
Get encryption key from environment variable or file
"""
key = None
key_location = os.environ.get("NPBACKUP_KEY_LOCATION", None)
if key_location and os.path.isfile(key_location):
try:
with open(key_location, "rb") as key_file:
key = key_file.read()
except OSError as exc:
msg = f"Cannot read encryption key file: {exc}"
return False, msg
else:
key_command = os.environ.get("NPBACKUP_KEY_COMMAND", None)
if key_command:
exit_code, output = command_runner(key_command, shell=True)
if exit_code != 0:
msg = f"Cannot run encryption key command: {output}"
return False, msg
key = output
return key