Only hide encrypted env variables, leave standard ones available

This commit is contained in:
deajan 2025-02-12 16:51:26 +01:00
parent 11dd20a4d4
commit 34f920d008
4 changed files with 59 additions and 11 deletions

View file

@ -23,7 +23,7 @@ This will prevent local backups, so we need to think of a better zero knowledge
# NPF-SEC-00005: Viewer mode can bypass permissions
Since viewer mode requires actual knowledge of repo URI and repo password, there's no need to manage local permissions.
Viewer mode permissions are set to "restore".
Viewer mode permissions are set to "restore-only".
# NPF-SEC-00006: Never inject permissions if some are already present
@ -60,4 +60,8 @@ Using obfuscation() symmetric function in order to not store the bare AES key.
# NPF-SEC-00012: Don't add PRIVATE directory to wheel / bdist builds
The PRIVATE directory might contain alternative AES keys and obfuscation functions which should never be bundled for a PyPI release.
The PRIVATE directory might contain alternative AES keys and obfuscation functions which should never be bundled for a PyPI release.
# NPF-SEC-00013: Don't leave encrypted envrionment variables for script usage
Sensible environment variables aren't available for scripts / additional parameters and will be replaced by a given string from __env__.py

View file

@ -43,4 +43,8 @@ def set_build_type(build_type: str) -> None:
BUILD_TYPE = build_type
# Allowed server ids for upgrade
ALLOWED_UPGRADE_SERVER_IDS = ("npbackup.upgrader", "npbackup.deployment_server")
# Replacement string for sensible data
HIDDEN_BY_NPBACKUP = "_[o_O]_hidden_by_npbackup"

View file

@ -7,7 +7,7 @@ __intname__ = "npbackup.gui.core.runner"
__author__ = "Orsiris de Jong"
__copyright__ = "Copyright (C) 2022-2025 NetInvent"
__license__ = "GPL-3.0-only"
__build__ = "2025021201"
__build__ = "2025021202"
from typing import Optional, Callable, Union, List
@ -857,7 +857,6 @@ class NPBackupRunner:
except KeyError:
encrypted_env_variables = []
env_variables += encrypted_env_variables
expanded_env_vars = {}
if isinstance(env_variables, list):
for env_variable in env_variables:
@ -874,8 +873,26 @@ class NPBackupRunner:
)
logger.debug("Trace:", exc_info=True)
expanded_encrypted_env_vars = {}
if isinstance(encrypted_env_variables, list):
for encrypted_env_variable in encrypted_env_variables:
if isinstance(encrypted_env_variable, dict):
for k, v in encrypted_env_variable.items():
try:
v = os.path.expanduser(v)
v = os.path.expandvars(v)
expanded_encrypted_env_vars[k.strip()] = v.strip()
except Exception as exc:
self.write_logs(
f"Cannot expand encrypted environment variable {k}: {exc}",
level="error",
)
logger.debug("Trace:", exc_info=True)
try:
self.restic_runner.environment_variables = expanded_env_vars
self.restic_runner.encrypted_environment_variables = (
expanded_encrypted_env_vars
)
except ValueError:
self.write_logs(
"Cannot initialize additional environment variables", level="error"

View file

@ -7,8 +7,8 @@ __intname__ = "npbackup.restic_wrapper"
__author__ = "Orsiris de Jong"
__copyright__ = "Copyright (C) 2022-2025 NetInvent"
__license__ = "GPL-3.0-only"
__build__ = "2025012201"
__version__ = "2.3.6"
__build__ = "2025021201"
__version__ = "2.4.0"
from typing import Tuple, List, Optional, Callable, Union
@ -28,6 +28,7 @@ from npbackup.__env__ import (
CHECK_INTERVAL,
HEARTBEAT_INTERVAL,
BUILD_TYPE,
HIDDEN_BY_NPBACKUP
)
from npbackup.path_helper import CURRENT_DIR
from npbackup.restic_wrapper import schema
@ -96,6 +97,7 @@ class ResticRunner:
self._ignore_cloud_files = True
self._additional_parameters = None
self._environment_variables = {}
self._encrypted_environment_variables = {}
# Function which will make executor abort if result is True
self._stop_on = None
@ -137,6 +139,16 @@ class ResticRunner:
)
os.environ[env_variable] = value
for (
encrypted_env_variable,
value,
) in self.encrypted_environment_variables.items():
self.write_logs(
f'Setting encrypted envrionment variable "{encrypted_env_variable}"',
level="debug",
)
os.environ[encrypted_env_variable] = value
# Configure default cpu usage when not specifically set
if not "GOMAXPROCS" in self.environment_variables:
nb_cores = os.cpu_count()
@ -154,11 +166,12 @@ class ResticRunner:
"""
Unsets repository & password environment, we don't need to keep that data when not requested
"""
os.environ["RESTIC_PASSWORD"] = "o_O"
os.environ["RESTIC_PASSWORD"] = HIDDEN_BY_NPBACKUP
os.environ["RESTIC_REPOSITORY"] = self.repository_anonymous
for env_variable in self.environment_variables.keys():
os.environ[env_variable] = "__ooOO(° °)OOoo__"
# NPF-SEC-00013 Don't leave encrypted environment variables for script usage
for encrypted_env_variable in self.encrypted_environment_variables.keys():
os.environ[encrypted_env_variable] = HIDDEN_BY_NPBACKUP
@property
def stdout(self) -> Optional[Union[int, str, Callable, queue.Queue]]:
@ -268,7 +281,7 @@ class ResticRunner:
@property
def repository_anonymous(self):
if self.repository:
return self.repository.split(":")[0] + ":_(o_O)_hidden_by_npbackup"
return self.repository.split(":")[0] + ":" + HIDDEN_BY_NPBACKUP
return None
def write_logs(
@ -519,9 +532,19 @@ class ResticRunner:
@environment_variables.setter
def environment_variables(self, value):
if not isinstance(value, dict):
raise ValueError("Bogus environment variables set")
raise ValueError(f"Bogus environment variables set: {value}")
self._environment_variables = value
@property
def encrypted_environment_variables(self):
return self._encrypted_environment_variables
@encrypted_environment_variables.setter
def encrypted_environment_variables(self, value):
if not isinstance(value, dict):
raise ValueError(f"Bogus encrypted environment variables set: {value}")
self._encrypted_environment_variables = value
@property
def binary(self):
return self._binary