From f072cfe1ebff79efaa409258a38646a62c94dbff Mon Sep 17 00:00:00 2001 From: Wael Nasreddine Date: Tue, 29 Jan 2019 08:45:26 -0800 Subject: nixos/pam: refactor U2F, docs about u2f_keys path (#54756) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * change enableU2F option to u2f.* set * add few u2f options (not all) to customize pam-u2f module * document default u2f_keys locations Co-authored-by: Tomasz Czyż Co-authored-by: Arda Xi --- nixos/modules/rename.nix | 3 ++ nixos/modules/security/pam.nix | 109 ++++++++++++++++++++++++++++++++++++----- nixos/tests/all-tests.nix | 1 + nixos/tests/pam-u2f.nix | 23 +++++++++ 4 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 nixos/tests/pam-u2f.nix (limited to 'nixos') diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index dc0a175d5bb8..24ab963f718a 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -69,6 +69,9 @@ with lib; (mkRemovedOptionModule [ "security" "setuidOwners" ] "Use security.wrappers instead") (mkRemovedOptionModule [ "security" "setuidPrograms" ] "Use security.wrappers instead") + # PAM + (mkRenamedOptionModule [ "security" "pam" "enableU2F" ] [ "security" "pam" "u2f" "enable" ]) + (mkRemovedOptionModule [ "services" "rmilter" "bindInetSockets" ] "Use services.rmilter.bindSocket.* instead") (mkRemovedOptionModule [ "services" "rmilter" "bindUnixSockets" ] "Use services.rmilter.bindSocket.* instead") diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index b1a0eff98c20..4631ba848a76 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -37,12 +37,14 @@ let }; u2fAuth = mkOption { - default = config.security.pam.enableU2F; + default = config.security.pam.u2f.enable; type = types.bool; description = '' If set, users listed in - ~/.config/Yubico/u2f_keys are able to log in - with the associated U2F key. + $XDG_CONFIG_HOME/Yubico/u2f_keys (or + $HOME/.config/Yubico/u2f_keys if XDG variable is + not set) are able to log in with the associated U2F key. Path can be + changed using option. ''; }; @@ -320,8 +322,8 @@ let "auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys:~/.ssh/authorized_keys2:/etc/ssh/authorized_keys.d/%u"} ${optionalString cfg.fprintAuth "auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so"} - ${optionalString cfg.u2fAuth - "auth sufficient ${pkgs.pam_u2f}/lib/security/pam_u2f.so"} + ${let u2f = config.security.pam.u2f; in optionalString cfg.u2fAuth + "auth ${u2f.control} ${pkgs.pam_u2f}/lib/security/pam_u2f.so ${optionalString u2f.debug "debug"} ${optionalString (u2f.authFile != null) "authfile=${u2f.authFile}"} ${optionalString u2f.interactive "interactive"} ${optionalString u2f.cue "cue"}"} ${optionalString cfg.usbAuth "auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so"} ${let oath = config.security.pam.oath; in optionalString cfg.oathAuth @@ -527,11 +529,96 @@ in ''; }; - security.pam.enableU2F = mkOption { - default = false; - description = '' - Enable the U2F PAM module. - ''; + security.pam.u2f = { + enable = mkOption { + default = false; + type = types.bool; + description = '' + Enables U2F PAM (pam-u2f) module. + + If set, users listed in + $XDG_CONFIG_HOME/Yubico/u2f_keys (or + $HOME/.config/Yubico/u2f_keys if XDG variable is + not set) are able to log in with the associated U2F key. The path can + be changed using option. + + File format is: + username:first_keyHandle,first_public_key: second_keyHandle,second_public_key + This file can be generated using pamu2fcfg command. + + More information can be found here. + ''; + }; + + authFile = mkOption { + default = null; + type = with types; nullOr path; + description = '' + By default pam-u2f module reads the keys from + $XDG_CONFIG_HOME/Yubico/u2f_keys (or + $HOME/.config/Yubico/u2f_keys if XDG variable is + not set). + + If you want to change auth file locations or centralize database (for + example use /etc/u2f-mappings) you can set this + option. + + File format is: + username:first_keyHandle,first_public_key: second_keyHandle,second_public_key + This file can be generated using pamu2fcfg command. + + More information can be found here. + ''; + }; + + 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 U2F device instead of regular password, use "sufficient". + + Read + + pam.conf + 5 + + for better understanding of this option. + ''; + }; + + debug = mkOption { + default = false; + type = types.bool; + description = '' + Debug output to stderr. + ''; + }; + + interactive = mkOption { + default = false; + type = types.bool; + description = '' + Set to prompt a message and wait before testing the presence of a U2F device. + Recommended if your device doesn’t have a tactile trigger. + ''; + }; + + cue = mkOption { + default = false; + type = types.bool; + description = '' + By default pam-u2f module does not inform user + that he needs to use the u2f device, it just waits without a prompt. + + If you set this option to true, + cue option is added to pam-u2f + module and reminder message will be displayed. + ''; + }; }; security.pam.enableEcryptfs = mkOption { @@ -563,7 +650,7 @@ in ++ optionals config.krb5.enable [pam_krb5 pam_ccreds] ++ optionals config.security.pam.enableOTPW [ pkgs.otpw ] ++ optionals config.security.pam.oath.enable [ pkgs.oathToolkit ] - ++ optionals config.security.pam.enableU2F [ pkgs.pam_u2f ]; + ++ optionals config.security.pam.u2f.enable [ pkgs.pam_u2f ]; boot.supportedFilesystems = optionals config.security.pam.enableEcryptfs [ "ecryptfs" ]; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 7bc2f3076f1e..88edef8e7520 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -162,6 +162,7 @@ in osquery = handleTest ./osquery.nix {}; ostree = handleTest ./ostree.nix {}; pam-oath-login = handleTest ./pam-oath-login.nix {}; + pam-u2f = handleTest ./pam-u2f.nix {}; peerflix = handleTest ./peerflix.nix {}; pgjwt = handleTest ./pgjwt.nix {}; pgmanage = handleTest ./pgmanage.nix {}; diff --git a/nixos/tests/pam-u2f.nix b/nixos/tests/pam-u2f.nix new file mode 100644 index 000000000000..1052a2f3b916 --- /dev/null +++ b/nixos/tests/pam-u2f.nix @@ -0,0 +1,23 @@ +import ./make-test.nix ({ ... }: + +{ + name = "pam-u2f"; + + machine = + { ... }: + { + security.pam.u2f = { + control = "required"; + cue = true; + debug = true; + enable = true; + interactive = true; + }; + }; + + testScript = + '' + $machine->waitForUnit('multi-user.target'); + $machine->succeed('egrep "auth required .*/lib/security/pam_u2f.so.*debug.*interactive.*cue" /etc/pam.d/ -R'); + ''; +}) -- cgit v1.2.3