diff --git a/modules/services/ssh-tpm-agent.nix b/modules/services/ssh-tpm-agent.nix new file mode 100644 index 000000000..ebe579b6a --- /dev/null +++ b/modules/services/ssh-tpm-agent.nix @@ -0,0 +1,91 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + inherit (lib) + mkIf + mkOption + mkEnableOption + mkPackageOption + types + ; + cfg = config.services.ssh-tpm-agent; + +in +{ + meta.maintainers = [ lib.maintainers.yethal ]; + + options.services.ssh-tpm-agent = { + enable = mkEnableOption "SSH agent for TPMs"; + + package = mkPackageOption pkgs "ssh-tpm-agent" { }; + + keyDir = mkOption { + type = with types; nullOr path; + description = "Path of the directory to look for TPM sealed keys in, defaults to $HOME/.ssh if unset"; + default = null; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.ssh-tpm-agent" pkgs lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user = { + services.ssh-tpm-agent = { + Unit = { + Description = "ssh-tpm-agent service"; + Documentation = "https://github.com/Foxboron/ssh-tpm-agent"; + Requires = "ssh-tpm-agent.socket"; + After = "ssh-tpm-agent.socket"; + RefuseManualStart = true; + }; + + Service = { + Type = "simple"; + SuccessExitStatus = 2; + ExecStart = "${lib.getExe cfg.package} -l %t/ssh-tpm-agent.sock${ + lib.optionalString (cfg.keyDir != null) " --key-dir ${cfg.keyDir}" + }"; + Environment = [ + "SSH_TPM_AUTH_SOCK=%t/ssh-tpm-agent.sock" + ]; + PassEnvironment = [ + "SSH_AGENT_PID" + ]; + }; + }; + + sockets.ssh-tpm-agent = { + Unit = { + Description = "SSH TPM agent socket"; + Documentation = "https://github.com/Foxboron/ssh-tpm-agent"; + }; + + Socket = { + ListenStream = "%t/ssh-tpm-agent.sock"; + RuntimeDirectory = "ssh-tpm-agent"; + SocketMode = "0600"; + DirectoryMode = "0700"; + Service = "ssh-tpm-agent.service"; + }; + + Install = { + WantedBy = [ "sockets.target" ]; + }; + }; + }; + + home.sessionVariables = { + SSH_AUTH_SOCK = "\${XDG_RUNTIME_DIR:-/run/user/$UID}/ssh-tpm-agent.sock"; + SSH_TPM_AUTH_SOCK = "\${XDG_RUNTIME_DIR:-/run/user/$UID}/ssh-tpm-agent.sock"; + }; + }; +} diff --git a/tests/modules/services/ssh-tpm-agent/default.nix b/tests/modules/services/ssh-tpm-agent/default.nix new file mode 100644 index 000000000..d8dfbae7e --- /dev/null +++ b/tests/modules/services/ssh-tpm-agent/default.nix @@ -0,0 +1,5 @@ +{ lib, pkgs, ... }: + +lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { + ssh-tpm-agent = ./service.nix; +} diff --git a/tests/modules/services/ssh-tpm-agent/service.nix b/tests/modules/services/ssh-tpm-agent/service.nix new file mode 100644 index 000000000..1b7088632 --- /dev/null +++ b/tests/modules/services/ssh-tpm-agent/service.nix @@ -0,0 +1,48 @@ +{ config, ... }: + +{ + services.ssh-tpm-agent = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@ssh-tpm-agent@"; }; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/ssh-tpm-agent.service + socketFile=home-files/.config/systemd/user/ssh-tpm-agent.socket + + assertFileExists $serviceFile + assertFileExists $socketFile + + assertFileContent $serviceFile ${builtins.toFile "expected-service" '' + [Service] + Environment=SSH_TPM_AUTH_SOCK=%t/ssh-tpm-agent.sock + ExecStart=@ssh-tpm-agent@/bin/dummy -l %t/ssh-tpm-agent.sock + PassEnvironment=SSH_AGENT_PID + SuccessExitStatus=2 + Type=simple + + [Unit] + After=ssh-tpm-agent.socket + Description=ssh-tpm-agent service + Documentation=https://github.com/Foxboron/ssh-tpm-agent + RefuseManualStart=true + Requires=ssh-tpm-agent.socket + ''} + + assertFileContent $socketFile ${builtins.toFile "expected-socket" '' + [Install] + WantedBy=sockets.target + + [Socket] + DirectoryMode=0700 + ListenStream=%t/ssh-tpm-agent.sock + RuntimeDirectory=ssh-tpm-agent + Service=ssh-tpm-agent.service + SocketMode=0600 + + [Unit] + Description=SSH TPM agent socket + Documentation=https://github.com/Foxboron/ssh-tpm-agent + ''} + ''; +}