From 82b6a52c7c4d6f814886581b7bf7930e0e7cd38f Mon Sep 17 00:00:00 2001 From: DavHau Date: Wed, 9 Apr 2025 15:02:20 +0700 Subject: [PATCH] vars: add feature --no-sandbox Raise warning if sandbox cannot be used -> request user to run with --no-sandbox --- pkgs/clan-cli/clan_cli/tests/test_vars.py | 12 ++++++++++++ pkgs/clan-cli/clan_cli/vars/generate.py | 21 +++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/tests/test_vars.py b/pkgs/clan-cli/clan_cli/tests/test_vars.py index b8a306d8d..f4b1dd2b4 100644 --- a/pkgs/clan-cli/clan_cli/tests/test_vars.py +++ b/pkgs/clan-cli/clan_cli/tests/test_vars.py @@ -217,6 +217,18 @@ def test_generate_public_and_secret_vars( cli.run( ["vars", "generate", "--flake", str(flake.path), "my_machine", "--regenerate"] ) + # test regeneration without sandbox + cli.run( + [ + "vars", + "generate", + "--flake", + str(flake.path), + "my_machine", + "--regenerate", + "--no-sandbox", + ] + ) # TODO: it doesn't actually test if the group has access diff --git a/pkgs/clan-cli/clan_cli/vars/generate.py b/pkgs/clan-cli/clan_cli/vars/generate.py index 2bacb2d34..7baeffaa0 100644 --- a/pkgs/clan-cli/clan_cli/vars/generate.py +++ b/pkgs/clan-cli/clan_cli/vars/generate.py @@ -163,6 +163,7 @@ def execute_generator( secret_vars_store: StoreBase, public_vars_store: StoreBase, prompt_values: dict[str, str], + no_sandbox: bool = False, ) -> None: if not isinstance(machine.flake, Path): msg = f"flake is not a Path: {machine.flake}" @@ -211,6 +212,12 @@ def execute_generator( if sys.platform == "linux" and bwrap.bubblewrap_works(): cmd = bubblewrap_cmd(str(final_script), tmpdir) else: + if not no_sandbox: + msg = ( + f"Cannot safely execute generator {generator.name}: Sandboxing is not available on this system\n" + f"Re-run with --no-sandbox to disable sandboxing" + ) + raise ClanError(msg) cmd = ["bash", "-c", str(final_script)] run(cmd, RunOpts(env=env)) files_to_commit = [] @@ -427,6 +434,7 @@ def generate_vars_for_machine( machine: "Machine", generator_name: str | None, regenerate: bool, + no_sandbox: bool = False, ) -> bool: _generator = None if generator_name: @@ -459,6 +467,7 @@ def generate_vars_for_machine( secret_vars_store=machine.secret_vars_store, public_vars_store=machine.public_vars_store, prompt_values=_ask_prompts(generator), + no_sandbox=no_sandbox, ) return True @@ -467,13 +476,14 @@ def generate_vars( machines: list["Machine"], generator_name: str | None = None, regenerate: bool = False, + no_sandbox: bool = False, ) -> bool: was_regenerated = False for machine in machines: errors = [] try: was_regenerated |= generate_vars_for_machine( - machine, generator_name, regenerate + machine, generator_name, regenerate, no_sandbox=no_sandbox ) machine.flush_caches() except Exception as exc: @@ -501,7 +511,7 @@ def generate_command(args: argparse.Namespace) -> None: machines = get_all_machines(args.flake, args.option) else: machines = get_selected_machines(args.flake, args.option, args.machines) - generate_vars(machines, args.generator, args.regenerate) + generate_vars(machines, args.generator, args.regenerate, no_sandbox=args.no_sandbox) def register_generate_parser(parser: argparse.ArgumentParser) -> None: @@ -531,4 +541,11 @@ def register_generate_parser(parser: argparse.ArgumentParser) -> None: default=None, ) + parser.add_argument( + "--no-sandbox", + action="store_true", + help="disable sandboxing when executing the generator. WARNING: potentially executing untrusted code from external clan modules", + default=False, + ) + parser.set_defaults(func=generate_command)