about summary refs log tree commit diff
path: root/modules/yubikey.nix
blob: 6473050a40126c14183b84923e093b68014e04ab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{
  config,
  inputs,
  lib,
  pkgs,
  this,
  ...
}:
let
  cfg = config.nixfiles.modules.yubikey;
in
{
  options.nixfiles.modules.yubikey = {
    enable = lib.mkEnableOption "Yubikey support";

    serials = lib.mkOption {
      type = with lib.types; listOf str;
      default = [ ];
      description = "List of YubiKey device serials.";
    };
  };

  config = lib.mkIf cfg.enable (
    lib.mkMerge [
      {
        security.pam = {
          rssh = {
            enable = true;
            settings.cue = true;
          };

          services.sudo.rssh = true;
        };
      }
      (lib.mkIf this.isHeadful {
        secrets.u2f.file = "${inputs.self}/secrets/u2f";

        hm = {
          home.packages = with pkgs; [
            yubikey-manager
            yubioath-flutter
          ];

          programs = {
            git.extraConfig = {
              gpg = {
                format = "ssh";
                ssh = {
                  # https://git-scm.com/docs/git-config#Documentation/git-config.txt-usersigningKey
                  defaultKeyCommand =
                    pkgs.writeShellScript "default-key-command" ''
                      key="$(ssh-add -L | head -n 1 | cut -d ' ' -f 1-2)"
                      printf 'key::%s\n' "$key"
                    ''
                    |> toString;

                  # https://man7.org/linux/man-pages/man1/ssh-keygen.1.html#ALLOWED_SIGNERS
                  allowedSignersFile =
                    config.my.openssh.authorizedKeys.keys
                    |> map (x: x |> lib.splitString " " |> lib.take 2 |> lib.concatStringsSep " ")
                    |> map (x: ''${lib.my.email} namespaces="git" ${x}'')
                    |> lib.concatLines
                    |> pkgs.writeText "allowed-signers-file"
                    |> toString;
                };
              };

              commit.gpgSign = true;
              tag.gpgSign = true;
            };

            # https://wiki.archlinux.org/title/YubiKey#gpg:_no_such_device
            gpg.scdaemonSettings = {
              disable-ccid = true;
              pcsc-shared = true;
            };
          };

          services = {
            gpg-agent.enableScDaemon = true;
            ssh-agent.enable = false;
          };
        };

        programs.yubikey-touch-detector.enable = true;

        # NOTE: This needs setting up with `yubikey-agent -setup`[1]. For
        # firmware version 7.2+ see these issues[2] in case of an error.
        #
        # [1]: https://filippo.io/yubikey-agent
        # [2]: https://github.com/FiloSottile/yubikey-agent/issues/153
        # [2]: https://github.com/sigstore/cosign/issues/3742
        #
        # ```
        # yubikey-agent -setup
        # ```
        services.yubikey-agent.enable = true;

        # NOTE: This also needs setting up[1].
        #
        # [1]: https://developers.yubico.com/pam-u2f/
        security.pam.u2f = {
          enable = true;
          settings = {
            origin = "pam://nixos";
            appid = "pam://nixos";
            authfile = config.secrets.u2f.path;
            cue = true;
          };
        };
      })
    ]
  );
}

Consider giving Nix/NixOS a try! <3