• 0 Posts
  • 2 Comments
Joined 1 year ago
cake
Cake day: October 30th, 2023

help-circle

  • 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