69 lines
2.4 KiB
Nix
69 lines
2.4 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
let
|
|
perl = "${pkgs.perl}/bin/perl";
|
|
sshAdd = "${pkgs.openssh}/bin/ssh-add";
|
|
pKill = "${pkgs.procps}/bin/pkill";
|
|
awk = "${pkgs.gawk}/bin/awk";
|
|
|
|
# fido-add-device is started by a systemd unit. It runs continuously waiting for a USR1 signal
|
|
# that is triggered by inserting a Yubikey. Once it receives the signal, it executes 'ssh-add -K'
|
|
# which when run without a terminal will use SSH_ASKPASS to prompt the user for the unlock
|
|
# phrase for their YK FIDO setup.
|
|
fidoAddDevice = pkgs.writeScriptBin "fido-add-device" ''
|
|
#!${perl}
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
$ENV{'SSH_AUTH_SOCK'} = "$ENV{'XDG_RUNTIME_DIR'}/ssh-agent";
|
|
$ENV{'DISPLAY'} = `systemctl --user show-environment | ${awk} -F= '/^DISPLAY/ {print \$NF}'`;
|
|
|
|
$SIG{USR1} = sub { system("${sshAdd}", "-K") };
|
|
|
|
while (1) {
|
|
sleep;
|
|
}
|
|
'';
|
|
|
|
# fido-send-sig is called by a udev rule when a YK is attached. It sends SIGUSR1 to fido-add-device.
|
|
fidoSendSig = pkgs.writeScriptBin "fido-send-sig" ''
|
|
#! ${pkgs.runtimeShell} -e
|
|
|
|
${pKill} -USR1 -xf "${perl} ${fidoAddDevice}/bin/fido-add-device"
|
|
'';
|
|
|
|
# my-ssh-askpass-wrapper wraps programs.ssh.askPassword in order to supply user-specific environment
|
|
# variables.
|
|
# TODO: replace this with makeWrapper
|
|
askPassWrapper = pkgs.writeScript "my-ssh-askpass-wrapper" ''
|
|
#! ${pkgs.runtimeShell} -e
|
|
export DISPLAY="$(systemctl --user show-environment | ${awk} -F= '/^DISPLAY/ {print $NF}')"
|
|
export SSH_AUTH_SOCK="$(echo $XDG_RUNTIME_DIR/ssh-agent)";
|
|
exec ${config.programs.ssh.askPassword} "$@"
|
|
'';
|
|
in {
|
|
options = {
|
|
sshFidoAgent = {
|
|
enable = lib.mkEnableOption "Add FIDO keys to ssh-agent when attached.";
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf config.sshFidoAgent.enable {
|
|
environment.systemPackages = [ fidoAddDevice ];
|
|
systemd.user.services.sshfidoagent = {
|
|
script = ''
|
|
${fidoAddDevice}/bin/fido-add-device
|
|
'';
|
|
wantedBy = [ "graphical-session.target" ];
|
|
partOf = [ "graphical-session.target" ];
|
|
after = [ "graphical-session.target" ];
|
|
environment.DISPLAY = "fake";
|
|
environment.SSH_ASKPASS = askPassWrapper;
|
|
#serviceConfig = { Restart = "on-failure"; };
|
|
};
|
|
services.udev.extraRules = ''
|
|
SUBSYSTEM=="hidraw", ACTION=="add", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0407|0402", RUN+="${fidoSendSig}/bin/fido-send-sig"
|
|
'';
|
|
};
|
|
}
|