diff --git a/third_party/nixpkgs/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/third_party/nixpkgs/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
index d7bc1471aa..b20aabd859 100644
--- a/third_party/nixpkgs/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+++ b/third_party/nixpkgs/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
@@ -1271,6 +1271,15 @@
been added by default.
+
+
+ security.pam.ussh has been added, which
+ allows authorizing PAM sessions based on SSH
+ certificates held within an SSH agent,
+ using
+ pam-ussh.
+
+
The zrepl package has been updated from
diff --git a/third_party/nixpkgs/nixos/doc/manual/release-notes/rl-2205.section.md b/third_party/nixpkgs/nixos/doc/manual/release-notes/rl-2205.section.md
index 4e1e70be49..88c1dd5729 100644
--- a/third_party/nixpkgs/nixos/doc/manual/release-notes/rl-2205.section.md
+++ b/third_party/nixpkgs/nixos/doc/manual/release-notes/rl-2205.section.md
@@ -466,6 +466,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- `services.logrotate.enable` now defaults to true if any rotate path has
been defined, and some paths have been added by default.
+- `security.pam.ussh` has been added, which allows authorizing PAM sessions based on SSH _certificates_ held within an SSH agent, using [pam-ussh](https://github.com/uber/pam-ussh).
+
- The `zrepl` package has been updated from 0.4.0 to 0.5:
- The RPC protocol version was bumped; all zrepl daemons in a setup must be updated and restarted before replication can resume.
diff --git a/third_party/nixpkgs/nixos/modules/security/pam.nix b/third_party/nixpkgs/nixos/modules/security/pam.nix
index c0ef8b5f30..f9697d61f1 100644
--- a/third_party/nixpkgs/nixos/modules/security/pam.nix
+++ b/third_party/nixpkgs/nixos/modules/security/pam.nix
@@ -61,6 +61,19 @@ let
'';
};
+ usshAuth = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ If set, users with an SSH certificate containing an authorized principal
+ in their SSH agent are able to log in. Specific options are controlled
+ using the options.
+
+ Note that the must also be
+ set for this option to take effect.
+ '';
+ };
+
yubicoAuth = mkOption {
default = config.security.pam.yubico.enable;
defaultText = literalExpression "config.security.pam.yubico.enable";
@@ -475,6 +488,9 @@ let
optionalString cfg.usbAuth ''
auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so
'' +
+ (let ussh = config.security.pam.ussh; in optionalString (config.security.pam.ussh.enable && cfg.usshAuth) ''
+ auth ${ussh.control} ${pkgs.pam_ussh}/lib/security/pam_ussh.so ${optionalString (ussh.caFile != null) "ca_file=${ussh.caFile}"} ${optionalString (ussh.authorizedPrincipals != null) "authorized_principals=${ussh.authorizedPrincipals}"} ${optionalString (ussh.authorizedPrincipalsFile != null) "authorized_principals_file=${ussh.authorizedPrincipalsFile}"} ${optionalString (ussh.group != null) "group=${ussh.group}"}
+ '') +
(let oath = config.security.pam.oath; in optionalString cfg.oathAuth ''
auth requisite ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}
'') +
@@ -926,6 +942,96 @@ in
};
};
+ security.pam.ussh = {
+ enable = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Enables Uber's USSH PAM (pam-ussh) module.
+
+ This is similar to pam-ssh-agent, except that
+ the presence of a CA-signed SSH key with a valid principal is checked
+ instead.
+
+ Note that this module must both be enabled using this option and on a
+ per-PAM-service level as well (using usshAuth).
+
+ More information can be found here.
+ '';
+ };
+
+ caFile = mkOption {
+ default = null;
+ type = with types; nullOr path;
+ description = ''
+ By default pam-ussh reads the trusted user CA keys
+ from /etc/ssh/trusted_user_ca.
+
+ This should be set the same as your TrustedUserCAKeys
+ option for sshd.
+ '';
+ };
+
+ authorizedPrincipals = mkOption {
+ default = null;
+ type = with types; nullOr commas;
+ description = ''
+ Comma-separated list of authorized principals to permit; if the user
+ presents a certificate with one of these principals, then they will be
+ authorized.
+
+ Note that pam-ussh also requires that the certificate
+ contain a principal matching the user's username. The principals from
+ this list are in addition to those principals.
+
+ Mutually exclusive with authorizedPrincipalsFile.
+ '';
+ };
+
+ authorizedPrincipalsFile = mkOption {
+ default = null;
+ type = with types; nullOr path;
+ description = ''
+ Path to a list of principals; if the user presents a certificate with
+ one of these principals, then they will be authorized.
+
+ Note that pam-ussh also requires that the certificate
+ contain a principal matching the user's username. The principals from
+ this file are in addition to those principals.
+
+ Mutually exclusive with authorizedPrincipals.
+ '';
+ };
+
+ group = mkOption {
+ default = null;
+ type = with types; nullOr str;
+ description = ''
+ If set, then the authenticating user must be a member of this group
+ to use this module.
+ '';
+ };
+
+ control = mkOption {
+ default = "sufficient";
+ type = types.enum [ "required" "requisite" "sufficient" "optional" ];
+ description = ''
+ This option sets pam "control".
+ If you want to have multi factor authentication, use "required".
+ If you want to use the SSH certificate instead of the regular password,
+ use "sufficient".
+
+ Read
+
+ pam.conf
+ 5
+
+ for better understanding of this option.
+ '';
+ };
+ };
+
security.pam.yubico = {
enable = mkOption {
default = false;
@@ -1110,6 +1216,9 @@ in
optionalString (isEnabled (cfg: cfg.usbAuth)) ''
mr ${pkgs.pam_usb}/lib/security/pam_usb.so,
'' +
+ optionalString (isEnabled (cfg: cfg.usshAuth)) ''
+ mr ${pkgs.pam_ussh}/lib/security/pam_ussh.so,
+ '' +
optionalString (isEnabled (cfg: cfg.oathAuth)) ''
"mr ${pkgs.oathToolkit}/lib/security/pam_oath.so,
'' +
diff --git a/third_party/nixpkgs/nixos/modules/security/sudo.nix b/third_party/nixpkgs/nixos/modules/security/sudo.nix
index 99e578f8ad..4bf239fca8 100644
--- a/third_party/nixpkgs/nixos/modules/security/sudo.nix
+++ b/third_party/nixpkgs/nixos/modules/security/sudo.nix
@@ -245,7 +245,7 @@ in
environment.systemPackages = [ sudo ];
- security.pam.services.sudo = { sshAgentAuth = true; };
+ security.pam.services.sudo = { sshAgentAuth = true; usshAuth = true; };
environment.etc.sudoers =
{ source =
diff --git a/third_party/nixpkgs/nixos/tests/all-tests.nix b/third_party/nixpkgs/nixos/tests/all-tests.nix
index 15b54cd9fe..953261e172 100644
--- a/third_party/nixpkgs/nixos/tests/all-tests.nix
+++ b/third_party/nixpkgs/nixos/tests/all-tests.nix
@@ -387,6 +387,7 @@ in
pam-file-contents = handleTest ./pam/pam-file-contents.nix {};
pam-oath-login = handleTest ./pam/pam-oath-login.nix {};
pam-u2f = handleTest ./pam/pam-u2f.nix {};
+ pam-ussh = handleTest ./pam/pam-ussh.nix {};
pantalaimon = handleTest ./matrix/pantalaimon.nix {};
pantheon = handleTest ./pantheon.nix {};
paperless-ng = handleTest ./paperless-ng.nix {};
diff --git a/third_party/nixpkgs/nixos/tests/pam/pam-ussh.nix b/third_party/nixpkgs/nixos/tests/pam/pam-ussh.nix
new file mode 100644
index 0000000000..ba0570dbf9
--- /dev/null
+++ b/third_party/nixpkgs/nixos/tests/pam/pam-ussh.nix
@@ -0,0 +1,70 @@
+import ../make-test-python.nix ({ pkgs, lib, ... }:
+
+let
+ testOnlySSHCredentials = pkgs.runCommand "pam-ussh-test-ca" {
+ nativeBuildInputs = [ pkgs.openssh ];
+ } ''
+ mkdir $out
+ ssh-keygen -t ed25519 -N "" -f $out/ca
+
+ ssh-keygen -t ed25519 -N "" -f $out/alice
+ ssh-keygen -s $out/ca -I "alice user key" -n "alice,root" -V 19700101:forever $out/alice.pub
+
+ ssh-keygen -t ed25519 -N "" -f $out/bob
+ ssh-keygen -s $out/ca -I "bob user key" -n "bob" -V 19700101:forever $out/bob.pub
+ '';
+ makeTestScript = user: pkgs.writeShellScript "pam-ussh-${user}-test-script" ''
+ set -euo pipefail
+
+ eval $(${pkgs.openssh}/bin/ssh-agent)
+
+ mkdir -p $HOME/.ssh
+ chmod 700 $HOME/.ssh
+ cp ${testOnlySSHCredentials}/${user}{,.pub,-cert.pub} $HOME/.ssh
+ chmod 600 $HOME/.ssh/${user}
+ chmod 644 $HOME/.ssh/${user}{,-cert}.pub
+
+ set -x
+
+ ${pkgs.openssh}/bin/ssh-add $HOME/.ssh/${user}
+ ${pkgs.openssh}/bin/ssh-add -l &>2
+
+ exec sudo id -u -n
+ '';
+in {
+ name = "pam-ussh";
+ meta.maintainers = with lib.maintainers; [ lukegb ];
+
+ machine =
+ { ... }:
+ {
+ users.users.alice = { isNormalUser = true; extraGroups = [ "wheel" ]; };
+ users.users.bob = { isNormalUser = true; extraGroups = [ "wheel" ]; };
+
+ security.pam.ussh = {
+ enable = true;
+ authorizedPrincipals = "root";
+ caFile = "${testOnlySSHCredentials}/ca.pub";
+ };
+
+ security.sudo = {
+ enable = true;
+ extraConfig = ''
+ Defaults lecture="never"
+ '';
+ };
+ };
+
+ testScript =
+ ''
+ with subtest("alice should be allowed to escalate to root"):
+ machine.succeed(
+ 'su -c "${makeTestScript "alice"}" -l alice | grep root'
+ )
+
+ with subtest("bob should not be allowed to escalate to root"):
+ machine.fail(
+ 'su -c "${makeTestScript "bob"}" -l bob | grep root'
+ )
+ '';
+})
diff --git a/third_party/nixpkgs/patches/pr164025.patch b/third_party/nixpkgs/patches/pr164025.patch
new file mode 100644
index 0000000000..237cdd315e
--- /dev/null
+++ b/third_party/nixpkgs/patches/pr164025.patch
@@ -0,0 +1,433 @@
+From f63d93bc3d0ad73b24b2cf9c0ee0381161071395 Mon Sep 17 00:00:00 2001
+From: Luke Granger-Brown
+Date: Sun, 13 Mar 2022 17:20:16 +0000
+Subject: [PATCH 1/2] pam_ussh: init at unstable-20210615
+
+---
+ pkgs/os-specific/linux/pam_ussh/default.nix | 64 +++++++++++++++++++++
+ pkgs/os-specific/linux/pam_ussh/go.mod | 15 +++++
+ pkgs/top-level/all-packages.nix | 2 +
+ 3 files changed, 81 insertions(+)
+ create mode 100644 pkgs/os-specific/linux/pam_ussh/default.nix
+ create mode 100644 pkgs/os-specific/linux/pam_ussh/go.mod
+
+diff --git a/pkgs/os-specific/linux/pam_ussh/default.nix b/pkgs/os-specific/linux/pam_ussh/default.nix
+new file mode 100644
+index 0000000000000..499239500acce
+--- /dev/null
++++ b/pkgs/os-specific/linux/pam_ussh/default.nix
+@@ -0,0 +1,64 @@
++{ buildGoModule
++, fetchFromGitHub
++, pam
++, lib
++}:
++
++buildGoModule rec {
++ pname = "pam_ussh";
++ version = "unstable-20210615";
++
++ src = fetchFromGitHub {
++ owner = "uber";
++ repo = "pam-ussh";
++ rev = "e9524bda90ba19d3b9eb24f49cb63a6a56a19193"; # HEAD as of 2022-03-13
++ sha256 = "0nb9hpqbghgi3zvq41kabydzyc6ffaaw9b4jkc5jrwn1klpw1xk8";
++ };
++
++ prePatch = ''
++ cp ${./go.mod} go.mod
++ '';
++ overrideModAttrs = (_: {
++ inherit prePatch;
++ });
++
++ vendorSha256 = "0hjifc3kbwmx7kjn858vi05cwwra6q19cqjfd94k726pwhk37qkw";
++
++ buildInputs = [
++ pam
++ ];
++
++ buildPhase = ''
++ runHook preBuild
++
++ if [ -z "$enableParallelBuilding" ]; then
++ export NIX_BUILD_CORES=1
++ fi
++ go build -buildmode=c-shared -o pam_ussh.so -v -p $NIX_BUILD_CORES .
++
++ runHook postBuild
++ '';
++ checkPhase = ''
++ runHook preCheck
++
++ go test -v -p $NIX_BUILD_CORES .
++
++ runHook postCheck
++ '';
++ installPhase = ''
++ runHook preInstall
++
++ mkdir -p $out/lib/security
++ cp pam_ussh.so $out/lib/security
++
++ runHook postInstall
++ '';
++
++ meta = with lib; {
++ homepage = "https://github.com/uber/pam-ussh";
++ description = "PAM module to authenticate using SSH certificates";
++ license = licenses.mit;
++ platforms = platforms.linux;
++ maintainers = with maintainers; [ lukegb ];
++ };
++}
+diff --git a/pkgs/os-specific/linux/pam_ussh/go.mod b/pkgs/os-specific/linux/pam_ussh/go.mod
+new file mode 100644
+index 0000000000000..9adc453560a43
+--- /dev/null
++++ b/pkgs/os-specific/linux/pam_ussh/go.mod
+@@ -0,0 +1,15 @@
++module github.com/uber/pam-ussh
++
++go 1.17
++
++require (
++ github.com/stretchr/testify v1.7.0
++ golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000
++)
++
++require (
++ github.com/davecgh/go-spew v1.1.0 // indirect
++ github.com/pmezard/go-difflib v1.0.0 // indirect
++ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
++ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
++)
+diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
+index 6c6832ae05475..539ecd4ec481b 100644
+--- a/pkgs/top-level/all-packages.nix
++++ b/pkgs/top-level/all-packages.nix
+@@ -23052,6 +23052,8 @@ with pkgs;
+
+ pam_usb = callPackage ../os-specific/linux/pam_usb { };
+
++ pam_ussh = callPackage ../os-specific/linux/pam_ussh { };
++
+ paxctl = callPackage ../os-specific/linux/paxctl { };
+
+ paxtest = callPackage ../os-specific/linux/paxtest { };
+
+From 1853015550a78acbc3e9d090d174120796c4b784 Mon Sep 17 00:00:00 2001
+From: Luke Granger-Brown
+Date: Sun, 13 Mar 2022 17:20:23 +0000
+Subject: [PATCH 2/2] nixos/pam: add support for pam-ussh
+
+pam-ussh allows authorizing using an SSH certificate stored in your
+SSH agent, in a similar manner to pam-ssh-agent-auth, but for
+certificates rather than raw public keys.
+---
+ .../from_md/release-notes/rl-2205.section.xml | 9 ++
+ .../manual/release-notes/rl-2205.section.md | 2 +
+ nixos/modules/security/pam.nix | 109 ++++++++++++++++++
+ nixos/modules/security/sudo.nix | 2 +-
+ nixos/tests/all-tests.nix | 1 +
+ nixos/tests/pam/pam-ussh.nix | 70 +++++++++++
+ pkgs/os-specific/linux/pam_ussh/default.nix | 3 +
+ 7 files changed, 195 insertions(+), 1 deletion(-)
+ create mode 100644 nixos/tests/pam/pam-ussh.nix
+
+diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+index 9cf27e56827a1..ede0e10e03466 100644
+--- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
++++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+@@ -1286,6 +1286,15 @@
+ been added by default.
+
+
++
++
++ security.pam.ussh has been added, which
++ allows authorizing PAM sessions based on SSH
++ certificates held within an SSH agent,
++ using
++ pam-ussh.
++
++
+
+
+ The zrepl package has been updated from
+diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md
+index 58a1b23d17bf6..90ac7e90e7295 100644
+--- a/nixos/doc/manual/release-notes/rl-2205.section.md
++++ b/nixos/doc/manual/release-notes/rl-2205.section.md
+@@ -470,6 +470,8 @@ In addition to numerous new and upgraded packages, this release has the followin
+ - `services.logrotate.enable` now defaults to true if any rotate path has
+ been defined, and some paths have been added by default.
+
++- `security.pam.ussh` has been added, which allows authorizing PAM sessions based on SSH _certificates_ held within an SSH agent, using [pam-ussh](https://github.com/uber/pam-ussh).
++
+ - The `zrepl` package has been updated from 0.4.0 to 0.5:
+
+ - The RPC protocol version was bumped; all zrepl daemons in a setup must be updated and restarted before replication can resume.
+diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
+index c0ef8b5f30bd4..f9697d61f1b27 100644
+--- a/nixos/modules/security/pam.nix
++++ b/nixos/modules/security/pam.nix
+@@ -61,6 +61,19 @@ let
+ '';
+ };
+
++ usshAuth = mkOption {
++ default = false;
++ type = types.bool;
++ description = ''
++ If set, users with an SSH certificate containing an authorized principal
++ in their SSH agent are able to log in. Specific options are controlled
++ using the options.
++
++ Note that the must also be
++ set for this option to take effect.
++ '';
++ };
++
+ yubicoAuth = mkOption {
+ default = config.security.pam.yubico.enable;
+ defaultText = literalExpression "config.security.pam.yubico.enable";
+@@ -475,6 +488,9 @@ let
+ optionalString cfg.usbAuth ''
+ auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so
+ '' +
++ (let ussh = config.security.pam.ussh; in optionalString (config.security.pam.ussh.enable && cfg.usshAuth) ''
++ auth ${ussh.control} ${pkgs.pam_ussh}/lib/security/pam_ussh.so ${optionalString (ussh.caFile != null) "ca_file=${ussh.caFile}"} ${optionalString (ussh.authorizedPrincipals != null) "authorized_principals=${ussh.authorizedPrincipals}"} ${optionalString (ussh.authorizedPrincipalsFile != null) "authorized_principals_file=${ussh.authorizedPrincipalsFile}"} ${optionalString (ussh.group != null) "group=${ussh.group}"}
++ '') +
+ (let oath = config.security.pam.oath; in optionalString cfg.oathAuth ''
+ auth requisite ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}
+ '') +
+@@ -926,6 +942,96 @@ in
+ };
+ };
+
++ security.pam.ussh = {
++ enable = mkOption {
++ default = false;
++ type = types.bool;
++ description = ''
++ Enables Uber's USSH PAM (pam-ussh) module.
++
++ This is similar to pam-ssh-agent, except that
++ the presence of a CA-signed SSH key with a valid principal is checked
++ instead.
++
++ Note that this module must both be enabled using this option and on a
++ per-PAM-service level as well (using usshAuth).
++
++ More information can be found here.
++ '';
++ };
++
++ caFile = mkOption {
++ default = null;
++ type = with types; nullOr path;
++ description = ''
++ By default pam-ussh reads the trusted user CA keys
++ from /etc/ssh/trusted_user_ca.
++
++ This should be set the same as your TrustedUserCAKeys
++ option for sshd.
++ '';
++ };
++
++ authorizedPrincipals = mkOption {
++ default = null;
++ type = with types; nullOr commas;
++ description = ''
++ Comma-separated list of authorized principals to permit; if the user
++ presents a certificate with one of these principals, then they will be
++ authorized.
++
++ Note that pam-ussh also requires that the certificate
++ contain a principal matching the user's username. The principals from
++ this list are in addition to those principals.
++
++ Mutually exclusive with authorizedPrincipalsFile.
++ '';
++ };
++
++ authorizedPrincipalsFile = mkOption {
++ default = null;
++ type = with types; nullOr path;
++ description = ''
++ Path to a list of principals; if the user presents a certificate with
++ one of these principals, then they will be authorized.
++
++ Note that pam-ussh also requires that the certificate
++ contain a principal matching the user's username. The principals from
++ this file are in addition to those principals.
++
++ Mutually exclusive with authorizedPrincipals.
++ '';
++ };
++
++ group = mkOption {
++ default = null;
++ type = with types; nullOr str;
++ description = ''
++ If set, then the authenticating user must be a member of this group
++ to use this module.
++ '';
++ };
++
++ control = mkOption {
++ default = "sufficient";
++ type = types.enum [ "required" "requisite" "sufficient" "optional" ];
++ description = ''
++ This option sets pam "control".
++ If you want to have multi factor authentication, use "required".
++ If you want to use the SSH certificate instead of the regular password,
++ use "sufficient".
++
++ Read
++
++ pam.conf
++ 5
++
++ for better understanding of this option.
++ '';
++ };
++ };
++
+ security.pam.yubico = {
+ enable = mkOption {
+ default = false;
+@@ -1110,6 +1216,9 @@ in
+ optionalString (isEnabled (cfg: cfg.usbAuth)) ''
+ mr ${pkgs.pam_usb}/lib/security/pam_usb.so,
+ '' +
++ optionalString (isEnabled (cfg: cfg.usshAuth)) ''
++ mr ${pkgs.pam_ussh}/lib/security/pam_ussh.so,
++ '' +
+ optionalString (isEnabled (cfg: cfg.oathAuth)) ''
+ "mr ${pkgs.oathToolkit}/lib/security/pam_oath.so,
+ '' +
+diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix
+index 99e578f8adae6..4bf239fca8f90 100644
+--- a/nixos/modules/security/sudo.nix
++++ b/nixos/modules/security/sudo.nix
+@@ -245,7 +245,7 @@ in
+
+ environment.systemPackages = [ sudo ];
+
+- security.pam.services.sudo = { sshAgentAuth = true; };
++ security.pam.services.sudo = { sshAgentAuth = true; usshAuth = true; };
+
+ environment.etc.sudoers =
+ { source =
+diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
+index 043d8a56d0c63..1ed12c54c5752 100644
+--- a/nixos/tests/all-tests.nix
++++ b/nixos/tests/all-tests.nix
+@@ -388,6 +388,7 @@ in
+ pam-file-contents = handleTest ./pam/pam-file-contents.nix {};
+ pam-oath-login = handleTest ./pam/pam-oath-login.nix {};
+ pam-u2f = handleTest ./pam/pam-u2f.nix {};
++ pam-ussh = handleTest ./pam/pam-ussh.nix {};
+ pantalaimon = handleTest ./matrix/pantalaimon.nix {};
+ pantheon = handleTest ./pantheon.nix {};
+ paperless-ng = handleTest ./paperless-ng.nix {};
+diff --git a/nixos/tests/pam/pam-ussh.nix b/nixos/tests/pam/pam-ussh.nix
+new file mode 100644
+index 0000000000000..ba0570dbf97d2
+--- /dev/null
++++ b/nixos/tests/pam/pam-ussh.nix
+@@ -0,0 +1,70 @@
++import ../make-test-python.nix ({ pkgs, lib, ... }:
++
++let
++ testOnlySSHCredentials = pkgs.runCommand "pam-ussh-test-ca" {
++ nativeBuildInputs = [ pkgs.openssh ];
++ } ''
++ mkdir $out
++ ssh-keygen -t ed25519 -N "" -f $out/ca
++
++ ssh-keygen -t ed25519 -N "" -f $out/alice
++ ssh-keygen -s $out/ca -I "alice user key" -n "alice,root" -V 19700101:forever $out/alice.pub
++
++ ssh-keygen -t ed25519 -N "" -f $out/bob
++ ssh-keygen -s $out/ca -I "bob user key" -n "bob" -V 19700101:forever $out/bob.pub
++ '';
++ makeTestScript = user: pkgs.writeShellScript "pam-ussh-${user}-test-script" ''
++ set -euo pipefail
++
++ eval $(${pkgs.openssh}/bin/ssh-agent)
++
++ mkdir -p $HOME/.ssh
++ chmod 700 $HOME/.ssh
++ cp ${testOnlySSHCredentials}/${user}{,.pub,-cert.pub} $HOME/.ssh
++ chmod 600 $HOME/.ssh/${user}
++ chmod 644 $HOME/.ssh/${user}{,-cert}.pub
++
++ set -x
++
++ ${pkgs.openssh}/bin/ssh-add $HOME/.ssh/${user}
++ ${pkgs.openssh}/bin/ssh-add -l &>2
++
++ exec sudo id -u -n
++ '';
++in {
++ name = "pam-ussh";
++ meta.maintainers = with lib.maintainers; [ lukegb ];
++
++ machine =
++ { ... }:
++ {
++ users.users.alice = { isNormalUser = true; extraGroups = [ "wheel" ]; };
++ users.users.bob = { isNormalUser = true; extraGroups = [ "wheel" ]; };
++
++ security.pam.ussh = {
++ enable = true;
++ authorizedPrincipals = "root";
++ caFile = "${testOnlySSHCredentials}/ca.pub";
++ };
++
++ security.sudo = {
++ enable = true;
++ extraConfig = ''
++ Defaults lecture="never"
++ '';
++ };
++ };
++
++ testScript =
++ ''
++ with subtest("alice should be allowed to escalate to root"):
++ machine.succeed(
++ 'su -c "${makeTestScript "alice"}" -l alice | grep root'
++ )
++
++ with subtest("bob should not be allowed to escalate to root"):
++ machine.fail(
++ 'su -c "${makeTestScript "bob"}" -l bob | grep root'
++ )
++ '';
++})
+diff --git a/pkgs/os-specific/linux/pam_ussh/default.nix b/pkgs/os-specific/linux/pam_ussh/default.nix
+index 499239500acce..889c8bc6f57cf 100644
+--- a/pkgs/os-specific/linux/pam_ussh/default.nix
++++ b/pkgs/os-specific/linux/pam_ussh/default.nix
+@@ -2,6 +2,7 @@
+ , fetchFromGitHub
+ , pam
+ , lib
++, nixosTests
+ }:
+
+ buildGoModule rec {
+@@ -54,6 +55,8 @@ buildGoModule rec {
+ runHook postInstall
+ '';
+
++ passthru.tests = { inherit (nixosTests) pam-ussh; };
++
+ meta = with lib; {
+ homepage = "https://github.com/uber/pam-ussh";
+ description = "PAM module to authenticate using SSH certificates";
diff --git a/third_party/nixpkgs/patches/series b/third_party/nixpkgs/patches/series
index 07b333bcb4..3cc1ca6fd2 100644
--- a/third_party/nixpkgs/patches/series
+++ b/third_party/nixpkgs/patches/series
@@ -1,5 +1,6 @@
nvidia-sideband-socket.patch
pr163673.patch
pr163678.patch
+pr164025.patch
networkd-support-more-wg-options.patch
networkd-global-options.patch
diff --git a/third_party/nixpkgs/pkgs/os-specific/linux/pam_ussh/default.nix b/third_party/nixpkgs/pkgs/os-specific/linux/pam_ussh/default.nix
new file mode 100644
index 0000000000..889c8bc6f5
--- /dev/null
+++ b/third_party/nixpkgs/pkgs/os-specific/linux/pam_ussh/default.nix
@@ -0,0 +1,67 @@
+{ buildGoModule
+, fetchFromGitHub
+, pam
+, lib
+, nixosTests
+}:
+
+buildGoModule rec {
+ pname = "pam_ussh";
+ version = "unstable-20210615";
+
+ src = fetchFromGitHub {
+ owner = "uber";
+ repo = "pam-ussh";
+ rev = "e9524bda90ba19d3b9eb24f49cb63a6a56a19193"; # HEAD as of 2022-03-13
+ sha256 = "0nb9hpqbghgi3zvq41kabydzyc6ffaaw9b4jkc5jrwn1klpw1xk8";
+ };
+
+ prePatch = ''
+ cp ${./go.mod} go.mod
+ '';
+ overrideModAttrs = (_: {
+ inherit prePatch;
+ });
+
+ vendorSha256 = "0hjifc3kbwmx7kjn858vi05cwwra6q19cqjfd94k726pwhk37qkw";
+
+ buildInputs = [
+ pam
+ ];
+
+ buildPhase = ''
+ runHook preBuild
+
+ if [ -z "$enableParallelBuilding" ]; then
+ export NIX_BUILD_CORES=1
+ fi
+ go build -buildmode=c-shared -o pam_ussh.so -v -p $NIX_BUILD_CORES .
+
+ runHook postBuild
+ '';
+ checkPhase = ''
+ runHook preCheck
+
+ go test -v -p $NIX_BUILD_CORES .
+
+ runHook postCheck
+ '';
+ installPhase = ''
+ runHook preInstall
+
+ mkdir -p $out/lib/security
+ cp pam_ussh.so $out/lib/security
+
+ runHook postInstall
+ '';
+
+ passthru.tests = { inherit (nixosTests) pam-ussh; };
+
+ meta = with lib; {
+ homepage = "https://github.com/uber/pam-ussh";
+ description = "PAM module to authenticate using SSH certificates";
+ license = licenses.mit;
+ platforms = platforms.linux;
+ maintainers = with maintainers; [ lukegb ];
+ };
+}
diff --git a/third_party/nixpkgs/pkgs/os-specific/linux/pam_ussh/go.mod b/third_party/nixpkgs/pkgs/os-specific/linux/pam_ussh/go.mod
new file mode 100644
index 0000000000..9adc453560
--- /dev/null
+++ b/third_party/nixpkgs/pkgs/os-specific/linux/pam_ussh/go.mod
@@ -0,0 +1,15 @@
+module github.com/uber/pam-ussh
+
+go 1.17
+
+require (
+ github.com/stretchr/testify v1.7.0
+ golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000
+)
+
+require (
+ github.com/davecgh/go-spew v1.1.0 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
+)
diff --git a/third_party/nixpkgs/pkgs/top-level/all-packages.nix b/third_party/nixpkgs/pkgs/top-level/all-packages.nix
index 7c21458c4b..548ebc5758 100644
--- a/third_party/nixpkgs/pkgs/top-level/all-packages.nix
+++ b/third_party/nixpkgs/pkgs/top-level/all-packages.nix
@@ -23046,6 +23046,8 @@ with pkgs;
pam_usb = callPackage ../os-specific/linux/pam_usb { };
+ pam_ussh = callPackage ../os-specific/linux/pam_ussh { };
+
paxctl = callPackage ../os-specific/linux/paxctl { };
paxtest = callPackage ../os-specific/linux/paxtest { };