nixos/pam: refactor U2F, docs about u2f_keys path (#54756)

* 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ż <tomasz.czyz@gmail.com>
Co-authored-by: Arda Xi <arda@ardaxi.com>
This commit is contained in:
Wael Nasreddine 2019-01-29 08:45:26 -08:00 committed by GitHub
parent 74d1850c0e
commit f072cfe1eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 125 additions and 11 deletions

View file

@ -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")

View file

@ -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
<filename>~/.config/Yubico/u2f_keys</filename> are able to log in
with the associated U2F key.
<filename>$XDG_CONFIG_HOME/Yubico/u2f_keys</filename> (or
<filename>$HOME/.config/Yubico/u2f_keys</filename> if XDG variable is
not set) are able to log in with the associated U2F key. Path can be
changed using <option>security.pam.u2f.authFile</option> 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 (<literal>pam-u2f</literal>) module.
If set, users listed in
<filename>$XDG_CONFIG_HOME/Yubico/u2f_keys</filename> (or
<filename>$HOME/.config/Yubico/u2f_keys</filename> if XDG variable is
not set) are able to log in with the associated U2F key. The path can
be changed using <option>security.pam.u2f.authFile</option> option.
File format is:
<literal>username:first_keyHandle,first_public_key: second_keyHandle,second_public_key</literal>
This file can be generated using <command>pamu2fcfg</command> command.
More information can be found <link
xlink:href="https://developers.yubico.com/pam-u2f/">here</link>.
'';
};
authFile = mkOption {
default = null;
type = with types; nullOr path;
description = ''
By default <literal>pam-u2f</literal> module reads the keys from
<filename>$XDG_CONFIG_HOME/Yubico/u2f_keys</filename> (or
<filename>$HOME/.config/Yubico/u2f_keys</filename> if XDG variable is
not set).
If you want to change auth file locations or centralize database (for
example use <filename>/etc/u2f-mappings</filename>) you can set this
option.
File format is:
<literal>username:first_keyHandle,first_public_key: second_keyHandle,second_public_key</literal>
This file can be generated using <command>pamu2fcfg</command> command.
More information can be found <link
xlink:href="https://developers.yubico.com/pam-u2f/">here</link>.
'';
};
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
<citerefentry>
<refentrytitle>pam.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry>
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 doesnt have a tactile trigger.
'';
};
cue = mkOption {
default = false;
type = types.bool;
description = ''
By default <literal>pam-u2f</literal> 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 <literal>true</literal>,
<literal>cue</literal> option is added to <literal>pam-u2f</literal>
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" ];

View file

@ -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 {};

23
nixos/tests/pam-u2f.nix Normal file
View file

@ -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');
'';
})