this post was submitted on 14 Nov 2023
2 points (100.0% liked)

Nix

10 readers
1 users here now

founded 1 year ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
[–] [email protected] 1 points 1 year ago (1 children)

I treat secrets like dependency injection: You don't make a thing that knows how to connect to the database / knows a secret / knows how to get a secret. Instead, you make a thing that takes an argument that is a database connection / secret. You bind late — at execution time. This keeps things very simple and needs no special frameworks / libraries / secrets-tools.

Concrete example:

  • Passing a secret to a VM
  • by wrapping it in a script
  • that copies the secret into an ephemeral filesystem image
  • that the VM mounts

In demo.nix:

{ pkgs ? import  { }, }:
let
  vmConfiguration = { lib, modulesPath, ... }: {
    imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ];
    config = {
      networking.hostName = "demo";
      system.stateVersion = lib.versions.majorMinor lib.version; # Ephemeral

      boot.initrd.availableKernelModules = [ "iso9660" ];
      fileSystems = lib.mkVMOverride {
        "/suitcase" = {
          device = "/dev/disk/by-label/suitcase";
          fsType = "iso9660";
          options = [ "ro" ];
        };
      };

      systemd.services.demo-secret-access = {
        description = "Demonstrate access to secret";
        wants = [ "suitcase.mount" ];
        after = [ "suitcase.mount" ];
        wantedBy = [ "multi-user.target" ];
        script = ''
          echo "Demo: The secret is: $(cat /suitcase/secret)" >&2
        '';
      };
    };
  };

  vmWrapper = { nixos, cdrtools, writeShellApplication, }:
    writeShellApplication {
      name = "demo";
      runtimeInputs = [ cdrtools ];
      text = ''
        if (( $# < 1 ));then
          echo usage: demo suitcase_path ... >&2
          exit 1
        fi
        if [[ ! -d "$1" ]];then
          echo Expected first argument to be a directory >&2
          exit 1
        fi

        suitcase_contents=$(realpath "$1")
        shift

        d=
        trap '[[ "$d" && -e "$d" ]] && rm -r "$d"' EXIT
        d=$(mktemp -d)
        cd "$d"

        (umask 077; mkisofs -R -uid 0 -gid 0 -V suitcase -o suitcase.iso "$suitcase_contents")

        ${(nixos vmConfiguration).config.system.build.vm}/bin/run-demo-vm \
          -drive file="$d/suitcase.iso",format=raw,id=suitcase,if=none,read-only=on,werror=report \
          -device virtio-blk-pci,drive=suitcase \
          "$@"
      '';
    };

in pkgs.callPackage vmWrapper { }

Use:

$ mkdir foo
$ (umask 077; echo hello > foo/secret)
$ $(nix-build demo.nix)/bin/demo foo

and the VM logs:

Nov 15 01:31:27 demo demo-secret-access-start[639]: Demo: The secret is: hello
[–] [email protected] 1 points 1 year ago (1 children)

Isn't sops / agenix basically the same thing except instead of you manually putting the secret in foo/secret it's stored encrypted in the Git repo and then it automatically decrypts it at execution time into /var/wherever?

[–] [email protected] 1 points 1 year ago (1 children)
[–] [email protected] 1 points 1 year ago

I've spent a significant amount of time over the past two weeks evaluating the differences and pros/cons between agenix and sops-nix. And a bit of time looking over your wall of text.

The reality is that your thinking/comic is completely backwards.