From 410378e6a1466aa9f5c6126311ab8f70cda63468 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Tue, 9 Sep 2025 02:17:31 -0500 Subject: [PATCH] passed env vars to subprocess and defined dict for mandatory env vars --- travel-backup-script.py | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) mode change 100644 => 100755 travel-backup-script.py diff --git a/travel-backup-script.py b/travel-backup-script.py old mode 100644 new mode 100755 index 4846d25..83bc07a --- a/travel-backup-script.py +++ b/travel-backup-script.py @@ -17,7 +17,7 @@ def build_repo(endpoint: str, bucket: str, prefix: str = None) -> str: parts.append(prefix.strip("/")) return "/".join(parts) -def run_restic(repo: str, source: str, dry_run: bool = False): +def run_restic(repo: str, source: str, dry_run: bool = False, env: dict = None): """Run restic backup command.""" cmd = [ "restic", @@ -30,10 +30,14 @@ def run_restic(repo: str, source: str, dry_run: bool = False): print("Command:", " ".join(cmd)) print("Environment (redacted):") - # Check which env vars are available + # Use provided env or fall back to current process env + if env is None: + env = os.environ.copy() + + # Check which env vars are available in the environment we're passing to restic env_vars = ("WASABI_ENDPOINT", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "RESTIC_PASSWORD") for key in env_vars: - if key in os.environ: + if key in env and env.get(key) is not None: print(f" {key}=***REDACTED***") else: print(f" {key}=NOT SET") @@ -42,8 +46,8 @@ def run_restic(repo: str, source: str, dry_run: bool = False): print("Dry-run mode: not running restic.") return 0 - # Pass the current environment explicitly - return subprocess.call(cmd, env=os.environ.copy()) + # Pass the provided environment explicitly to the restic subprocess + return subprocess.call(cmd, env=env) def main(): # Load environment variables from .env.local (if present) @@ -53,7 +57,7 @@ def main(): parser.add_argument("--source", required=True, help="Path to file or directory to back up") parser.add_argument("--bucket", help="Wasabi S3 bucket name") parser.add_argument("--prefix", help="Prefix (folder) inside bucket", default=None) - parser.add_argument("--region", default="us-east-1", help="Wasabi region, e.g. us-west-1") + parser.add_argument("--region", default="us-west-1", help="Wasabi region, e.g. us-west-1") parser.add_argument("--repository", help="Full restic repository string (overrides bucket/prefix)") parser.add_argument("--dry-run", action="store_true", help="Print command instead of running it") @@ -71,7 +75,28 @@ def main(): return 2 repo = build_repo(endpoint, args.bucket, args.prefix) - return run_restic(repo, args.source, args.dry_run) + # Capture the current process environment (including values loaded by load_dotenv) + proc_env = os.environ.copy() + + # Build a minimal env dict to pass to restic. Include only the keys restic needs + # plus PATH and HOME so the restic binary can be resolved and user context is preserved. + needed_keys = ("WASABI_ENDPOINT", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "RESTIC_PASSWORD") + minimal_env = {} + for k in needed_keys: + v = proc_env.get(k) + if v is not None: + minimal_env[k] = v + + # Ensure WASABI_ENDPOINT is provided (use computed endpoint fallback) + if "WASABI_ENDPOINT" not in minimal_env or not minimal_env.get("WASABI_ENDPOINT"): + minimal_env["WASABI_ENDPOINT"] = endpoint + + # Preserve PATH and HOME so subprocess can find restic and use user's home directory + minimal_env["PATH"] = proc_env.get("PATH", "") + if proc_env.get("HOME") is not None: + minimal_env["HOME"] = proc_env.get("HOME") + + return run_restic(repo, args.source, args.dry_run, env=minimal_env) if __name__ == "__main__": sys.exit(main()) \ No newline at end of file