mirror of
https://github.com/netinvent/npbackup.git
synced 2025-10-13 23:18:01 +08:00
Implement alternate AES key loading as in #56
This commit is contained in:
parent
b01590871d
commit
8203d5c6b3
5 changed files with 58 additions and 12 deletions
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.")
|
||||
|
|
35
npbackup/key_management.py
Normal file
35
npbackup/key_management.py
Normal 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
|
Loading…
Add table
Reference in a new issue