From edf6671affeb57bbd6f829c7d8600c91705f4882 Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown Date: Sun, 13 Mar 2022 17:33:59 +0000 Subject: [PATCH] 3p/nixpkgs: add pr164025 --- .../from_md/release-notes/rl-2205.section.xml | 9 + .../manual/release-notes/rl-2205.section.md | 2 + .../nixpkgs/nixos/modules/security/pam.nix | 109 +++++ .../nixpkgs/nixos/modules/security/sudo.nix | 2 +- third_party/nixpkgs/nixos/tests/all-tests.nix | 1 + .../nixpkgs/nixos/tests/pam/pam-ussh.nix | 70 +++ third_party/nixpkgs/patches/pr164025.patch | 433 ++++++++++++++++++ third_party/nixpkgs/patches/series | 1 + .../os-specific/linux/pam_ussh/default.nix | 67 +++ .../pkgs/os-specific/linux/pam_ussh/go.mod | 15 + .../nixpkgs/pkgs/top-level/all-packages.nix | 2 + 11 files changed, 710 insertions(+), 1 deletion(-) create mode 100644 third_party/nixpkgs/nixos/tests/pam/pam-ussh.nix create mode 100644 third_party/nixpkgs/patches/pr164025.patch create mode 100644 third_party/nixpkgs/pkgs/os-specific/linux/pam_ussh/default.nix create mode 100644 third_party/nixpkgs/pkgs/os-specific/linux/pam_ussh/go.mod 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 { };