at master 3.6 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.boot.initrd.clevis; 9 systemd = config.boot.initrd.systemd; 10 supportedFs = [ 11 "zfs" 12 "bcachefs" 13 ]; 14in 15{ 16 meta.maintainers = with lib.maintainers; [ 17 julienmalka 18 camillemndn 19 ]; 20 meta.doc = ./clevis.md; 21 22 options = { 23 boot.initrd.clevis.enable = lib.mkEnableOption "Clevis in initrd"; 24 25 boot.initrd.clevis.package = lib.mkPackageOption pkgs "clevis" { }; 26 27 boot.initrd.clevis.devices = lib.mkOption { 28 description = "Encrypted devices that need to be unlocked at boot using Clevis"; 29 default = { }; 30 type = lib.types.attrsOf ( 31 lib.types.submodule ({ 32 options.secretFile = lib.mkOption { 33 description = "Clevis JWE file used to decrypt the device at boot, in concert with the chosen pin (one of TPM2, Tang server, or SSS)."; 34 type = lib.types.path; 35 }; 36 }) 37 ); 38 }; 39 40 boot.initrd.clevis.useTang = lib.mkOption { 41 description = "Whether the Clevis JWE file used to decrypt the devices uses a Tang server as a pin."; 42 default = false; 43 type = lib.types.bool; 44 }; 45 46 }; 47 48 config = lib.mkIf cfg.enable { 49 50 # Implementation of clevis unlocking for the supported filesystems are located directly in the respective modules. 51 52 assertions = ( 53 lib.attrValues ( 54 lib.mapAttrs (device: _: { 55 assertion = 56 (lib.any ( 57 fs: 58 fs.device == device && (lib.elem fs.fsType supportedFs) 59 || (fs.fsType == "zfs" && lib.hasPrefix "${device}/" fs.device) 60 ) config.system.build.fileSystems) 61 || (lib.hasAttr device config.boot.initrd.luks.devices); 62 message = ''No filesystem or LUKS device with the name ${device} is declared in your configuration.''; 63 }) cfg.devices 64 ) 65 ); 66 67 warnings = 68 if 69 cfg.useTang && !config.boot.initrd.network.enable && !config.boot.initrd.systemd.network.enable 70 then 71 [ "In order to use a Tang pinned secret you must configure networking in initrd" ] 72 else 73 [ ]; 74 75 boot.initrd = { 76 extraUtilsCommands = lib.mkIf (!systemd.enable) '' 77 copy_bin_and_libs ${pkgs.jose}/bin/jose 78 copy_bin_and_libs ${pkgs.curl}/bin/curl 79 copy_bin_and_libs ${pkgs.bashNonInteractive}/bin/bash 80 81 copy_bin_and_libs ${pkgs.tpm2-tools}/bin/.tpm2-wrapped 82 mv $out/bin/{.tpm2-wrapped,tpm2} 83 cp {${pkgs.tpm2-tss},$out}/lib/libtss2-tcti-device.so.0 84 85 copy_bin_and_libs ${cfg.package}/bin/.clevis-wrapped 86 mv $out/bin/{.clevis-wrapped,clevis} 87 88 for BIN in ${cfg.package}/bin/clevis-decrypt*; do 89 copy_bin_and_libs $BIN 90 done 91 92 for BIN in $out/bin/clevis{,-decrypt{,-null,-tang,-tpm2}}; do 93 sed -i $BIN -e 's,${pkgs.bashNonInteractive},,' -e 's,${pkgs.coreutils},,' 94 done 95 96 sed -i $out/bin/clevis-decrypt-tpm2 -e 's,tpm2_,tpm2 ,' 97 ''; 98 99 secrets = lib.mapAttrs' ( 100 name: value: lib.nameValuePair "/etc/clevis/${name}.jwe" value.secretFile 101 ) cfg.devices; 102 103 systemd = { 104 extraBin = lib.mkIf systemd.enable { 105 clevis = "${cfg.package}/bin/clevis"; 106 curl = "${pkgs.curl}/bin/curl"; 107 }; 108 109 storePaths = lib.mkIf systemd.enable [ 110 cfg.package 111 "${pkgs.jose}/bin/jose" 112 "${pkgs.curl}/bin/curl" 113 "${pkgs.tpm2-tools}/bin/tpm2_createprimary" 114 "${pkgs.tpm2-tools}/bin/tpm2_flushcontext" 115 "${pkgs.tpm2-tools}/bin/tpm2_load" 116 "${pkgs.tpm2-tools}/bin/tpm2_unseal" 117 ]; 118 }; 119 }; 120 }; 121}