diff --git a/src/arion b/src/arion index f8aff15..afb6e8a 100755 --- a/src/arion +++ b/src/arion @@ -118,7 +118,9 @@ fi debug docker_compose_args: "${docker_compose_args[@]}" debug files: "${files[@]}" -docker_compose_yaml=.tmp-nix-docker-compose-$$-$RANDOM.yaml +docker_system_id="$(docker info --format '{{.Name}}-{{.ID}}')" + +docker_compose_yaml=.tmp-arion-$$-$RANDOM.yaml cleanup() { rm -f $docker_compose_yaml } @@ -203,6 +205,26 @@ do_build() { } EOF )" + + # FIXME: Do something else for swarm + # FIXME: Include project name + export ARION_SECRETS_DIR="arion-secrets/$docker_system_id" + + if [[ true = "$(jq <"$docker_compose_yaml" '.["x-arion"].hasTextSecrets')" ]]; then + echo 1>&2 "Evaluating configuration read-only for secrets..." + eval "$(nix-instantiate \ + "$nix_dir/eval-composition.nix" \ + --eval \ + --readonly-mode \ + --json \ + --argstr uid "$UID" \ + --arg modules "$modules" \ + --arg pkgs "$pkgs_argument" \ + --arg writableStore false \ + --show-trace \ + --attr 'config.build.writeSecretsScript' \ + | jq -r)" + fi } diff --git a/src/nix/eval-composition.nix b/src/nix/eval-composition.nix index b3fc78a..1dd39f5 100644 --- a/src/nix/eval-composition.nix +++ b/src/nix/eval-composition.nix @@ -1,4 +1,9 @@ -{ modules ? [], uid ? "0", pkgs, hostNixStorePrefix ? "", }: +{ modules ? [] +, uid ? "0" +, pkgs +, hostNixStorePrefix ? "" +, writableStore ? true +}: let _pkgs = pkgs; in @@ -22,6 +27,7 @@ let ./modules/composition/host-environment.nix ./modules/composition/images.nix ./modules/composition/service-info.nix + ./modules/composition/text-secrets.nix ]; argsModule = { @@ -30,6 +36,7 @@ let config._module.args.pkgs = lib.mkIf (pkgs != null) (lib.mkForce pkgs); config.host.nixStorePrefix = hostNixStorePrefix; config.host.uid = lib.toInt uid; + config.host.writableStore = writableStore; }; in diff --git a/src/nix/modules/composition/docker-compose.nix b/src/nix/modules/composition/docker-compose.nix index 518da5e..999ff40 100644 --- a/src/nix/modules/composition/docker-compose.nix +++ b/src/nix/modules/composition/docker-compose.nix @@ -13,7 +13,7 @@ let cfg = config.docker-compose; inherit (lib) mkOption optionalAttrs mapAttrs; - inherit (lib.types) submodule attrsOf nullOr str path bool; + inherit (lib.types) submodule attrsOf nullOr either str path bool; evalService = name: modules: pkgs.callPackage ../../eval-service.nix {} { inherit name modules; inherit (config) host; }; dockerComposeRef = fragment: diff --git a/src/nix/modules/composition/host-environment.nix b/src/nix/modules/composition/host-environment.nix index 3e36531..4202b06 100644 --- a/src/nix/modules/composition/host-environment.nix +++ b/src/nix/modules/composition/host-environment.nix @@ -29,5 +29,14 @@ ''; }; + host.writableStore = lib.mkOption { + type = lib.types.bool; + description = '' + Whether the Nix store is writable. Normally it is, but when extracting + secrets, it must not be writable in order to prevent secrets from + accidentally leaking into the Nix store. + ''; + }; + }; } diff --git a/src/nix/modules/composition/text-secrets.nix b/src/nix/modules/composition/text-secrets.nix new file mode 100644 index 0000000..f1503ae --- /dev/null +++ b/src/nix/modules/composition/text-secrets.nix @@ -0,0 +1,29 @@ +{ config, lib, ... }: +let + inherit (lib) mkOption mapAttrsToList concatStrings escapeShellArg; + inherit (lib.types) attrsOf unspecified; + +in +{ + options = { + textSecrets = mkOption { + type = attrsOf unspecified; # unspecified for laziness + default = {}; + description = "Secrets to write to files."; + }; + build.writeSecretsScript = mkOption { + type = unspecified; # unspecified for laziness + readOnly = true; + internal = true; + description = "Generated script that writes the textSecrets."; + }; + }; + + config = { + docker-compose.extended.hasTextSecrets = config.textSecrets != {}; + build.writeSecretsScript = concatStrings (mapAttrsToList (k: v: '' + mkdir -p "$ARION_SECRETS_DIR" + echo ${escapeShellArg v} >$ARION_SECRETS_DIR/${escapeShellArg k} + '') config.textSecrets); + }; +} \ No newline at end of file