Merge pull request #255547 from Majiir/pam-modular-rules

nixos/pam: assemble rules from modular configuration

authored by Silvan Mosberger and committed by GitHub e0b3b074 23247389

+396 -359
+390 -354
nixos/modules/security/pam.nix
··· 6 6 with lib; 7 7 8 8 let 9 + 10 + mkRulesTypeOption = type: mkOption { 11 + # These options are experimental and subject to breaking changes without notice. 12 + description = lib.mdDoc '' 13 + PAM `${type}` rules for this service. 14 + 15 + Attribute keys are the name of each rule. 16 + ''; 17 + type = types.attrsOf (types.submodule ({ name, config, ... }: { 18 + options = { 19 + name = mkOption { 20 + type = types.str; 21 + description = lib.mdDoc '' 22 + Name of this rule. 23 + ''; 24 + internal = true; 25 + readOnly = true; 26 + }; 27 + enable = mkOption { 28 + type = types.bool; 29 + default = true; 30 + description = lib.mdDoc '' 31 + Whether this rule is added to the PAM service config file. 32 + ''; 33 + }; 34 + order = mkOption { 35 + type = types.int; 36 + description = lib.mdDoc '' 37 + Order of this rule in the service file. Rules are arranged in ascending order of this value. 38 + 39 + ::: {.warning} 40 + The `order` values for the built-in rules are subject to change. If you assign a constant value to this option, a system update could silently reorder your rule. You could be locked out of your system, or your system could be left wide open. When using this option, set it to a relative offset from another rule's `order` value: 41 + 42 + ```nix 43 + { 44 + security.pam.services.login.rules.auth.foo.order = 45 + config.security.pam.services.login.rules.auth.unix.order + 10; 46 + } 47 + ``` 48 + ::: 49 + ''; 50 + }; 51 + control = mkOption { 52 + type = types.str; 53 + description = lib.mdDoc '' 54 + Indicates the behavior of the PAM-API should the module fail to succeed in its authentication task. See `control` in {manpage}`pam.conf(5)` for details. 55 + ''; 56 + }; 57 + modulePath = mkOption { 58 + type = types.str; 59 + description = lib.mdDoc '' 60 + Either the full filename of the PAM to be used by the application (it begins with a '/'), or a relative pathname from the default module location. See `module-path` in {manpage}`pam.conf(5)` for details. 61 + ''; 62 + }; 63 + args = mkOption { 64 + type = types.listOf types.str; 65 + description = lib.mdDoc '' 66 + Tokens that can be used to modify the specific behavior of the given PAM. Such arguments will be documented for each individual module. See `module-arguments` in {manpage}`pam.conf(5)` for details. 67 + 68 + Escaping rules for spaces and square brackets are automatically applied. 69 + 70 + {option}`settings` are automatically added as {option}`args`. It's recommended to use the {option}`settings` option whenever possible so that arguments can be overridden. 71 + ''; 72 + }; 73 + settings = mkOption { 74 + type = with types; attrsOf (nullOr (oneOf [ bool str int pathInStore ])); 75 + default = {}; 76 + description = lib.mdDoc '' 77 + Settings to add as `module-arguments`. 78 + 79 + Boolean values render just the key if true, and nothing if false. Null values are ignored. All other values are rendered as key-value pairs. 80 + ''; 81 + }; 82 + }; 83 + config = { 84 + inherit name; 85 + # Formats an attrset of settings as args for use as `module-arguments`. 86 + args = concatLists (flip mapAttrsToList config.settings (name: value: 87 + if isBool value 88 + then optional value name 89 + else optional (value != null) "${name}=${toString value}" 90 + )); 91 + }; 92 + })); 93 + }; 94 + 9 95 parentConfig = config; 10 96 11 97 pamOpts = { config, name, ... }: let cfg = config; in let config = parentConfig; in { ··· 16 102 example = "sshd"; 17 103 type = types.str; 18 104 description = lib.mdDoc "Name of the PAM service."; 105 + }; 106 + 107 + rules = mkOption { 108 + # This option is experimental and subject to breaking changes without notice. 109 + visible = false; 110 + 111 + description = lib.mdDoc '' 112 + PAM rules for this service. 113 + 114 + ::: {.warning} 115 + This option and its suboptions are experimental and subject to breaking changes without notice. 116 + 117 + If you use this option in your system configuration, you will need to manually monitor this module for any changes. Otherwise, failure to adjust your configuration properly could lead to you being locked out of your system, or worse, your system could be left wide open to attackers. 118 + 119 + If you share configuration examples that use this option, you MUST include this warning so that users are informed. 120 + 121 + You may freely use this option within `nixpkgs`, and future changes will account for those use sites. 122 + ::: 123 + ''; 124 + type = types.submodule { 125 + options = genAttrs [ "account" "auth" "password" "session" ] mkRulesTypeOption; 126 + }; 19 127 }; 20 128 21 129 unixAuth = mkOption { ··· 470 578 setLoginUid = mkDefault cfg.startSession; 471 579 limits = mkDefault config.security.pam.loginLimits; 472 580 581 + text = let 582 + ensureUniqueOrder = type: rules: 583 + let 584 + checkPair = a: b: assert assertMsg (a.order != b.order) "security.pam.services.${name}.rules.${type}: rules '${a.name}' and '${b.name}' cannot have the same order value (${toString a.order})"; b; 585 + checked = zipListsWith checkPair rules (drop 1 rules); 586 + in take 1 rules ++ checked; 587 + # Formats a string for use in `module-arguments`. See `man pam.conf`. 588 + formatModuleArgument = token: 589 + if hasInfix " " token 590 + then "[${replaceStrings ["]"] ["\\]"] token}]" 591 + else token; 592 + formatRules = type: pipe cfg.rules.${type} [ 593 + attrValues 594 + (filter (rule: rule.enable)) 595 + (sort (a: b: a.order < b.order)) 596 + (ensureUniqueOrder type) 597 + (map (rule: concatStringsSep " " ( 598 + [ type rule.control rule.modulePath ] 599 + ++ map formatModuleArgument rule.args 600 + ++ [ "# ${rule.name} (order ${toString rule.order})" ] 601 + ))) 602 + (concatStringsSep "\n") 603 + ]; 604 + in mkDefault '' 605 + # Account management. 606 + ${formatRules "account"} 607 + 608 + # Authentication management. 609 + ${formatRules "auth"} 610 + 611 + # Password management. 612 + ${formatRules "password"} 613 + 614 + # Session management. 615 + ${formatRules "session"} 616 + ''; 617 + 473 618 # !!! TODO: move the LDAP stuff to the LDAP module, and the 474 619 # Samba stuff to the Samba module. This requires that the PAM 475 620 # module provides the right hooks. 476 - text = mkDefault 477 - ( 478 - '' 479 - # Account management. 480 - '' + 481 - optionalString use_ldap '' 482 - account sufficient ${pam_ldap}/lib/security/pam_ldap.so 483 - '' + 484 - optionalString cfg.mysqlAuth '' 485 - account sufficient ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf 486 - '' + 487 - optionalString (config.services.kanidm.enablePam) '' 488 - account sufficient ${pkgs.kanidm}/lib/pam_kanidm.so ignore_unknown_user 489 - '' + 490 - optionalString (config.services.sssd.enable && cfg.sssdStrictAccess==false) '' 491 - account sufficient ${pkgs.sssd}/lib/security/pam_sss.so 492 - '' + 493 - optionalString (config.services.sssd.enable && cfg.sssdStrictAccess) '' 494 - account [default=bad success=ok user_unknown=ignore] ${pkgs.sssd}/lib/security/pam_sss.so 495 - '' + 496 - optionalString config.security.pam.krb5.enable '' 497 - account sufficient ${pam_krb5}/lib/security/pam_krb5.so 498 - '' + 499 - optionalString cfg.googleOsLoginAccountVerification '' 500 - account [success=ok ignore=ignore default=die] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so 501 - account [success=ok default=ignore] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so 502 - '' + 503 - optionalString config.services.homed.enable '' 504 - account sufficient ${config.systemd.package}/lib/security/pam_systemd_home.so 505 - '' + 621 + rules = let 622 + autoOrderRules = flip pipe [ 623 + (imap1 (index: rule: rule // { order = mkDefault (10000 + index * 100); } )) 624 + (map (rule: nameValuePair rule.name (removeAttrs rule [ "name" ]))) 625 + listToAttrs 626 + ]; 627 + in { 628 + account = autoOrderRules [ 629 + { name = "ldap"; enable = use_ldap; control = "sufficient"; modulePath = "${pam_ldap}/lib/security/pam_ldap.so"; } 630 + { name = "mysql"; enable = cfg.mysqlAuth; control = "sufficient"; modulePath = "${pkgs.pam_mysql}/lib/security/pam_mysql.so"; settings = { 631 + config_file = "/etc/security/pam_mysql.conf"; 632 + }; } 633 + { name = "kanidm"; enable = config.services.kanidm.enablePam; control = "sufficient"; modulePath = "${pkgs.kanidm}/lib/pam_kanidm.so"; settings = { 634 + ignore_unknown_user = true; 635 + }; } 636 + { name = "sss"; enable = config.services.sssd.enable; control = if cfg.sssdStrictAccess then "[default=bad success=ok user_unknown=ignore]" else "sufficient"; modulePath = "${pkgs.sssd}/lib/security/pam_sss.so"; } 637 + { name = "krb5"; enable = config.security.pam.krb5.enable; control = "sufficient"; modulePath = "${pam_krb5}/lib/security/pam_krb5.so"; } 638 + { name = "oslogin_login"; enable = cfg.googleOsLoginAccountVerification; control = "[success=ok ignore=ignore default=die]"; modulePath = "${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so"; } 639 + { name = "oslogin_admin"; enable = cfg.googleOsLoginAccountVerification; control = "[success=ok default=ignore]"; modulePath = "${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so"; } 640 + { name = "systemd_home"; enable = config.services.homed.enable; control = "sufficient"; modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so"; } 506 641 # The required pam_unix.so module has to come after all the sufficient modules 507 642 # because otherwise, the account lookup will fail if the user does not exist 508 643 # locally, for example with MySQL- or LDAP-auth. 509 - '' 510 - account required pam_unix.so 644 + { name = "unix"; control = "required"; modulePath = "pam_unix.so"; } 645 + ]; 511 646 512 - # Authentication management. 513 - '' + 514 - optionalString cfg.googleOsLoginAuthentication '' 515 - auth [success=done perm_denied=die default=ignore] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so 516 - '' + 517 - optionalString cfg.rootOK '' 518 - auth sufficient pam_rootok.so 519 - '' + 520 - optionalString cfg.requireWheel '' 521 - auth required pam_wheel.so use_uid 522 - '' + 523 - optionalString cfg.logFailures '' 524 - auth required pam_faillock.so 525 - '' + 526 - optionalString cfg.mysqlAuth '' 527 - auth sufficient ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf 528 - '' + 529 - optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth) '' 530 - auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=${lib.concatStringsSep ":" config.services.openssh.authorizedKeysFiles} 531 - '' + 532 - (let p11 = config.security.pam.p11; in optionalString cfg.p11Auth '' 533 - auth ${p11.control} ${pkgs.pam_p11}/lib/security/pam_p11.so ${pkgs.opensc}/lib/opensc-pkcs11.so 534 - '') + 535 - (let u2f = config.security.pam.u2f; in optionalString cfg.u2fAuth ('' 536 - auth ${u2f.control} ${pkgs.pam_u2f}/lib/security/pam_u2f.so ${optionalString u2f.debug "debug"} ${optionalString (u2f.authFile != null) "authfile=${u2f.authFile}"} '' 537 - + ''${optionalString u2f.interactive "interactive"} ${optionalString u2f.cue "cue"} ${optionalString (u2f.appId != null) "appid=${u2f.appId}"} ${optionalString (u2f.origin != null) "origin=${u2f.origin}"} 538 - '')) + 539 - optionalString cfg.usbAuth '' 540 - auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so 541 - '' + 542 - (let ussh = config.security.pam.ussh; in optionalString (config.security.pam.ussh.enable && cfg.usshAuth) '' 543 - 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}"} 544 - '') + 545 - (let oath = config.security.pam.oath; in optionalString cfg.oathAuth '' 546 - auth requisite ${pkgs.oath-toolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits} 547 - '') + 548 - (let yubi = config.security.pam.yubico; in optionalString cfg.yubicoAuth '' 549 - auth ${yubi.control} ${pkgs.yubico-pam}/lib/security/pam_yubico.so mode=${toString yubi.mode} ${optionalString (yubi.challengeResponsePath != null) "chalresp_path=${yubi.challengeResponsePath}"} ${optionalString (yubi.mode == "client") "id=${toString yubi.id}"} ${optionalString yubi.debug "debug"} 550 - '') + 551 - (let dp9ik = config.security.pam.dp9ik; in optionalString dp9ik.enable '' 552 - auth ${dp9ik.control} ${pkgs.pam_dp9ik}/lib/security/pam_p9.so ${dp9ik.authserver} 553 - '') + 554 - optionalString cfg.fprintAuth '' 555 - auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so 556 - '' + 647 + auth = autoOrderRules ([ 648 + { name = "oslogin_login"; enable = cfg.googleOsLoginAuthentication; control = "[success=done perm_denied=die default=ignore]"; modulePath = "${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so"; } 649 + { name = "rootok"; enable = cfg.rootOK; control = "sufficient"; modulePath = "pam_rootok.so"; } 650 + { name = "wheel"; enable = cfg.requireWheel; control = "required"; modulePath = "pam_wheel.so"; settings = { 651 + use_uid = true; 652 + }; } 653 + { name = "faillock"; enable = cfg.logFailures; control = "required"; modulePath = "pam_faillock.so"; } 654 + { name = "mysql"; enable = cfg.mysqlAuth; control = "sufficient"; modulePath = "${pkgs.pam_mysql}/lib/security/pam_mysql.so"; settings = { 655 + config_file = "/etc/security/pam_mysql.conf"; 656 + }; } 657 + { name = "ssh_agent_auth"; enable = config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth; control = "sufficient"; modulePath = "${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so"; settings = { 658 + file = lib.concatStringsSep ":" config.services.openssh.authorizedKeysFiles; 659 + }; } 660 + (let p11 = config.security.pam.p11; in { name = "p11"; enable = cfg.p11Auth; control = p11.control; modulePath = "${pkgs.pam_p11}/lib/security/pam_p11.so"; args = [ 661 + "${pkgs.opensc}/lib/opensc-pkcs11.so" 662 + ]; }) 663 + (let u2f = config.security.pam.u2f; in { name = "u2f"; enable = cfg.u2fAuth; control = u2f.control; modulePath = "${pkgs.pam_u2f}/lib/security/pam_u2f.so"; settings = { 664 + inherit (u2f) debug interactive cue origin; 665 + authfile = u2f.authFile; 666 + appid = u2f.appId; 667 + }; }) 668 + { name = "usb"; enable = cfg.usbAuth; control = "sufficient"; modulePath = "${pkgs.pam_usb}/lib/security/pam_usb.so"; } 669 + (let ussh = config.security.pam.ussh; in { name = "ussh"; enable = config.security.pam.ussh.enable && cfg.usshAuth; control = ussh.control; modulePath = "${pkgs.pam_ussh}/lib/security/pam_ussh.so"; settings = { 670 + ca_file = ussh.caFile; 671 + authorized_principals = ussh.authorizedPrincipals; 672 + authorized_principals_file = ussh.authorizedPrincipalsFile; 673 + inherit (ussh) group; 674 + }; }) 675 + (let oath = config.security.pam.oath; in { name = "oath"; enable = cfg.oathAuth; control = "requisite"; modulePath = "${pkgs.oath-toolkit}/lib/security/pam_oath.so"; settings = { 676 + inherit (oath) window digits; 677 + usersfile = oath.usersFile; 678 + }; }) 679 + (let yubi = config.security.pam.yubico; in { name = "yubico"; enable = cfg.yubicoAuth; control = yubi.control; modulePath = "${pkgs.yubico-pam}/lib/security/pam_yubico.so"; settings = { 680 + inherit (yubi) mode debug; 681 + chalresp_path = yubi.challengeResponsePath; 682 + id = mkIf (yubi.mode == "client") yubi.id; 683 + }; }) 684 + (let dp9ik = config.security.pam.dp9ik; in { name = "p9"; enable = dp9ik.enable; control = dp9ik.control; modulePath = "${pkgs.pam_dp9ik}/lib/security/pam_p9.so"; args = [ 685 + dp9ik.authserver 686 + ]; }) 687 + { name = "fprintd"; enable = cfg.fprintAuth; control = "sufficient"; modulePath = "${pkgs.fprintd}/lib/security/pam_fprintd.so"; } 688 + ] ++ 557 689 # Modules in this block require having the password set in PAM_AUTHTOK. 558 690 # pam_unix is marked as 'sufficient' on NixOS which means nothing will run 559 691 # after it succeeds. Certain modules need to run after pam_unix ··· 562 694 # We use try_first_pass the second time to avoid prompting password twice. 563 695 # 564 696 # The same principle applies to systemd-homed 565 - (optionalString ((cfg.unixAuth || config.services.homed.enable) && 697 + (optionals ((cfg.unixAuth || config.services.homed.enable) && 566 698 (config.security.pam.enableEcryptfs 567 699 || config.security.pam.enableFscrypt 568 700 || cfg.pamMount ··· 573 705 || cfg.failDelay.enable 574 706 || cfg.duoSecurity.enable 575 707 || cfg.zfs)) 576 - ( 577 - optionalString config.services.homed.enable '' 578 - auth optional ${config.systemd.package}/lib/security/pam_systemd_home.so 579 - '' + 580 - optionalString cfg.unixAuth '' 581 - auth optional pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth 582 - '' + 583 - optionalString config.security.pam.enableEcryptfs '' 584 - auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap 585 - '' + 586 - optionalString config.security.pam.enableFscrypt '' 587 - auth optional ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so 588 - '' + 589 - optionalString cfg.zfs '' 590 - auth optional ${config.boot.zfs.package}/lib/security/pam_zfs_key.so homes=${config.security.pam.zfs.homes} 591 - '' + 592 - optionalString cfg.pamMount '' 593 - auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive 594 - '' + 595 - optionalString cfg.enableKwallet '' 596 - auth optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5 597 - '' + 598 - optionalString cfg.enableGnomeKeyring '' 599 - auth optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so 600 - '' + 601 - optionalString cfg.gnupg.enable '' 602 - auth optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so ${optionalString cfg.gnupg.storeOnly " store-only"} 603 - '' + 604 - optionalString cfg.failDelay.enable '' 605 - auth optional ${pkgs.pam}/lib/security/pam_faildelay.so delay=${toString cfg.failDelay.delay} 606 - '' + 607 - optionalString cfg.googleAuthenticator.enable '' 608 - auth required ${pkgs.google-authenticator}/lib/security/pam_google_authenticator.so no_increment_hotp 609 - '' + 610 - optionalString cfg.duoSecurity.enable '' 611 - auth required ${pkgs.duo-unix}/lib/security/pam_duo.so 612 - '' 613 - )) + 614 - optionalString config.services.homed.enable '' 615 - auth sufficient ${config.systemd.package}/lib/security/pam_systemd_home.so 616 - '' + 617 - optionalString cfg.unixAuth '' 618 - auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth try_first_pass 619 - '' + 620 - optionalString cfg.otpwAuth '' 621 - auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so 622 - '' + 623 - optionalString use_ldap '' 624 - auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass 625 - '' + 626 - optionalString config.services.kanidm.enablePam '' 627 - auth sufficient ${pkgs.kanidm}/lib/pam_kanidm.so ignore_unknown_user use_first_pass 628 - '' + 629 - optionalString config.services.sssd.enable '' 630 - auth sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_first_pass 631 - '' + 632 - optionalString config.security.pam.krb5.enable '' 633 - auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass 634 - auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass 635 - auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass 636 - '' + 637 - '' 638 - auth required pam_deny.so 708 + [ 709 + { name = "systemd_home-early"; enable = config.services.homed.enable; control = "optional"; modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so"; } 710 + { name = "unix-early"; enable = cfg.unixAuth; control = "optional"; modulePath = "pam_unix.so"; settings = { 711 + nullok = cfg.allowNullPassword; 712 + inherit (cfg) nodelay; 713 + likeauth = true; 714 + }; } 715 + { name = "ecryptfs"; enable = config.security.pam.enableEcryptfs; control = "optional"; modulePath = "${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"; settings = { 716 + unwrap = true; 717 + }; } 718 + { name = "fscrypt"; enable = config.security.pam.enableFscrypt; control = "optional"; modulePath = "${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so"; } 719 + { name = "zfs_key"; enable = cfg.zfs; control = "optional"; modulePath = "${config.boot.zfs.package}/lib/security/pam_zfs_key.so"; settings = { 720 + inherit (config.security.pam.zfs) homes; 721 + }; } 722 + { name = "mount"; enable = cfg.pamMount; control = "optional"; modulePath = "${pkgs.pam_mount}/lib/security/pam_mount.so"; settings = { 723 + disable_interactive = true; 724 + }; } 725 + { name = "kwallet5"; enable = cfg.enableKwallet; control = "optional"; modulePath = "${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so"; settings = { 726 + kwalletd = "${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5"; 727 + }; } 728 + { name = "gnome_keyring"; enable = cfg.enableGnomeKeyring; control = "optional"; modulePath = "${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so"; } 729 + { name = "gnupg"; enable = cfg.gnupg.enable; control = "optional"; modulePath = "${pkgs.pam_gnupg}/lib/security/pam_gnupg.so"; settings = { 730 + store-only = cfg.gnupg.storeOnly; 731 + }; } 732 + { name = "faildelay"; enable = cfg.failDelay.enable; control = "optional"; modulePath = "${pkgs.pam}/lib/security/pam_faildelay.so"; settings = { 733 + inherit (cfg.failDelay) delay; 734 + }; } 735 + { name = "google_authenticator"; enable = cfg.googleAuthenticator.enable; control = "required"; modulePath = "${pkgs.google-authenticator}/lib/security/pam_google_authenticator.so"; settings = { 736 + no_increment_hotp = true; 737 + }; } 738 + { name = "duo"; enable = cfg.duoSecurity.enable; control = "required"; modulePath = "${pkgs.duo-unix}/lib/security/pam_duo.so"; } 739 + ]) ++ [ 740 + { name = "systemd_home"; enable = config.services.homed.enable; control = "sufficient"; modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so"; } 741 + { name = "unix"; enable = cfg.unixAuth; control = "sufficient"; modulePath = "pam_unix.so"; settings = { 742 + nullok = cfg.allowNullPassword; 743 + inherit (cfg) nodelay; 744 + likeauth = true; 745 + try_first_pass = true; 746 + }; } 747 + { name = "otpw"; enable = cfg.otpwAuth; control = "sufficient"; modulePath = "${pkgs.otpw}/lib/security/pam_otpw.so"; } 748 + { name = "ldap"; enable = use_ldap; control = "sufficient"; modulePath = "${pam_ldap}/lib/security/pam_ldap.so"; settings = { 749 + use_first_pass = true; 750 + }; } 751 + { name = "kanidm"; enable = config.services.kanidm.enablePam; control = "sufficient"; modulePath = "${pkgs.kanidm}/lib/pam_kanidm.so"; settings = { 752 + ignore_unknown_user = true; 753 + use_first_pass = true; 754 + }; } 755 + { name = "sss"; enable = config.services.sssd.enable; control = "sufficient"; modulePath = "${pkgs.sssd}/lib/security/pam_sss.so"; settings = { 756 + use_first_pass = true; 757 + }; } 758 + { name = "krb5"; enable = config.security.pam.krb5.enable; control = "[default=ignore success=1 service_err=reset]"; modulePath = "${pam_krb5}/lib/security/pam_krb5.so"; settings = { 759 + use_first_pass = true; 760 + }; } 761 + { name = "ccreds-validate"; enable = config.security.pam.krb5.enable; control = "[default=die success=done]"; modulePath = "${pam_ccreds}/lib/security/pam_ccreds.so"; settings = { 762 + action = "validate"; 763 + use_first_pass = true; 764 + }; } 765 + { name = "ccreds-store"; enable = config.security.pam.krb5.enable; control = "sufficient"; modulePath = "${pam_ccreds}/lib/security/pam_ccreds.so"; settings = { 766 + action = "store"; 767 + use_first_pass = true; 768 + }; } 769 + { name = "deny"; control = "required"; modulePath = "pam_deny.so"; } 770 + ]); 639 771 640 - # Password management. 641 - '' + 642 - optionalString config.services.homed.enable '' 643 - password sufficient ${config.systemd.package}/lib/security/pam_systemd_home.so 644 - '' + '' 645 - password sufficient pam_unix.so nullok yescrypt 646 - '' + 647 - optionalString config.security.pam.enableEcryptfs '' 648 - password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so 649 - '' + 650 - optionalString config.security.pam.enableFscrypt '' 651 - password optional ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so 652 - '' + 653 - optionalString cfg.zfs '' 654 - password optional ${config.boot.zfs.package}/lib/security/pam_zfs_key.so homes=${config.security.pam.zfs.homes} 655 - '' + 656 - optionalString cfg.pamMount '' 657 - password optional ${pkgs.pam_mount}/lib/security/pam_mount.so 658 - '' + 659 - optionalString use_ldap '' 660 - password sufficient ${pam_ldap}/lib/security/pam_ldap.so 661 - '' + 662 - optionalString cfg.mysqlAuth '' 663 - password sufficient ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf 664 - '' + 665 - optionalString config.services.kanidm.enablePam '' 666 - password sufficient ${pkgs.kanidm}/lib/pam_kanidm.so 667 - '' + 668 - optionalString config.services.sssd.enable '' 669 - password sufficient ${pkgs.sssd}/lib/security/pam_sss.so 670 - '' + 671 - optionalString config.security.pam.krb5.enable '' 672 - password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass 673 - '' + 674 - optionalString cfg.enableGnomeKeyring '' 675 - password optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so use_authtok 676 - '' + 677 - '' 772 + password = autoOrderRules [ 773 + { name = "systemd_home"; enable = config.services.homed.enable; control = "sufficient"; modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so"; } 774 + { name = "unix"; control = "sufficient"; modulePath = "pam_unix.so"; settings = { 775 + nullok = true; 776 + yescrypt = true; 777 + }; } 778 + { name = "ecryptfs"; enable = config.security.pam.enableEcryptfs; control = "optional"; modulePath = "${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"; } 779 + { name = "fscrypt"; enable = config.security.pam.enableFscrypt; control = "optional"; modulePath = "${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so"; } 780 + { name = "zfs_key"; enable = cfg.zfs; control = "optional"; modulePath = "${config.boot.zfs.package}/lib/security/pam_zfs_key.so"; settings = { 781 + inherit (config.security.pam.zfs) homes; 782 + }; } 783 + { name = "mount"; enable = cfg.pamMount; control = "optional"; modulePath = "${pkgs.pam_mount}/lib/security/pam_mount.so"; } 784 + { name = "ldap"; enable = use_ldap; control = "sufficient"; modulePath = "${pam_ldap}/lib/security/pam_ldap.so"; } 785 + { name = "mysql"; enable = cfg.mysqlAuth; control = "sufficient"; modulePath = "${pkgs.pam_mysql}/lib/security/pam_mysql.so"; settings = { 786 + config_file = "/etc/security/pam_mysql.conf"; 787 + }; } 788 + { name = "kanidm"; enable = config.services.kanidm.enablePam; control = "sufficient"; modulePath = "${pkgs.kanidm}/lib/pam_kanidm.so"; } 789 + { name = "sss"; enable = config.services.sssd.enable; control = "sufficient"; modulePath = "${pkgs.sssd}/lib/security/pam_sss.so"; } 790 + { name = "krb5"; enable = config.security.pam.krb5.enable; control = "sufficient"; modulePath = "${pam_krb5}/lib/security/pam_krb5.so"; settings = { 791 + use_first_pass = true; 792 + }; } 793 + { name = "gnome_keyring"; enable = cfg.enableGnomeKeyring; control = "optional"; modulePath = "${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so"; settings = { 794 + use_authtok = true; 795 + }; } 796 + ]; 678 797 679 - # Session management. 680 - '' + 681 - optionalString cfg.setEnvironment '' 682 - session required pam_env.so conffile=/etc/pam/environment readenv=0 683 - '' + 684 - '' 685 - session required pam_unix.so 686 - '' + 687 - optionalString cfg.setLoginUid '' 688 - session ${if config.boot.isContainer then "optional" else "required"} pam_loginuid.so 689 - '' + 690 - optionalString cfg.ttyAudit.enable (concatStringsSep " \\\n " ([ 691 - "session required ${pkgs.pam}/lib/security/pam_tty_audit.so" 692 - ] ++ optional cfg.ttyAudit.openOnly "open_only" 693 - ++ optional (cfg.ttyAudit.enablePattern != null) "enable=${cfg.ttyAudit.enablePattern}" 694 - ++ optional (cfg.ttyAudit.disablePattern != null) "disable=${cfg.ttyAudit.disablePattern}" 695 - )) + 696 - optionalString config.services.homed.enable '' 697 - session required ${config.systemd.package}/lib/security/pam_systemd_home.so 698 - '' + 699 - optionalString cfg.makeHomeDir '' 700 - session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=${config.security.pam.makeHomeDir.skelDirectory} umask=${config.security.pam.makeHomeDir.umask} 701 - '' + 702 - optionalString cfg.updateWtmp '' 703 - session required ${pkgs.pam}/lib/security/pam_lastlog.so silent 704 - '' + 705 - optionalString config.security.pam.enableEcryptfs '' 706 - session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so 707 - '' + 708 - optionalString config.security.pam.enableFscrypt '' 709 - # Work around https://github.com/systemd/systemd/issues/8598 710 - # Skips the pam_fscrypt module for systemd-user sessions which do not have a password 711 - # anyways. 712 - # See also https://github.com/google/fscrypt/issues/95 713 - session [success=1 default=ignore] pam_succeed_if.so service = systemd-user 714 - session optional ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so 715 - '' + 716 - optionalString cfg.zfs '' 717 - session [success=1 default=ignore] pam_succeed_if.so service = systemd-user 718 - session optional ${config.boot.zfs.package}/lib/security/pam_zfs_key.so homes=${config.security.pam.zfs.homes} ${optionalString config.security.pam.zfs.noUnmount "nounmount"} 719 - '' + 720 - optionalString cfg.pamMount '' 721 - session optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive 722 - '' + 723 - optionalString use_ldap '' 724 - session optional ${pam_ldap}/lib/security/pam_ldap.so 725 - '' + 726 - optionalString cfg.mysqlAuth '' 727 - session optional ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf 728 - '' + 729 - optionalString config.services.kanidm.enablePam '' 730 - session optional ${pkgs.kanidm}/lib/pam_kanidm.so 731 - '' + 732 - optionalString config.services.sssd.enable '' 733 - session optional ${pkgs.sssd}/lib/security/pam_sss.so 734 - '' + 735 - optionalString config.security.pam.krb5.enable '' 736 - session optional ${pam_krb5}/lib/security/pam_krb5.so 737 - '' + 738 - optionalString cfg.otpwAuth '' 739 - session optional ${pkgs.otpw}/lib/security/pam_otpw.so 740 - '' + 741 - optionalString cfg.startSession '' 742 - session optional ${config.systemd.package}/lib/security/pam_systemd.so 743 - '' + 744 - optionalString cfg.forwardXAuth '' 745 - session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99 746 - '' + 747 - optionalString (cfg.limits != []) '' 748 - session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits} 749 - '' + 750 - optionalString (cfg.showMotd && (config.users.motd != null || config.users.motdFile != null)) '' 751 - session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd} 752 - '' + 753 - optionalString (cfg.enableAppArmor && config.security.apparmor.enable) '' 754 - session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug 755 - '' + 756 - optionalString (cfg.enableKwallet) '' 757 - session optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5 758 - '' + 759 - optionalString (cfg.enableGnomeKeyring) '' 760 - session optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start 761 - '' + 762 - optionalString cfg.gnupg.enable '' 763 - session optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so ${optionalString cfg.gnupg.noAutostart " no-autostart"} 764 - '' + 765 - optionalString (config.virtualisation.lxc.lxcfs.enable) '' 766 - session optional ${pkgs.lxc}/lib/security/pam_cgfs.so -c all 767 - '' 768 - ); 798 + session = autoOrderRules [ 799 + { name = "env"; enable = cfg.setEnvironment; control = "required"; modulePath = "pam_env.so"; settings = { 800 + conffile = "/etc/pam/environment"; 801 + readenv = 0; 802 + }; } 803 + { name = "unix"; control = "required"; modulePath = "pam_unix.so"; } 804 + { name = "loginuid"; enable = cfg.setLoginUid; control = if config.boot.isContainer then "optional" else "required"; modulePath = "pam_loginuid.so"; } 805 + { name = "tty_audit"; enable = cfg.ttyAudit.enable; control = "required"; modulePath = "${pkgs.pam}/lib/security/pam_tty_audit.so"; settings = { 806 + open_only = cfg.ttyAudit.openOnly; 807 + enable = cfg.ttyAudit.enablePattern; 808 + disable = cfg.ttyAudit.disablePattern; 809 + }; } 810 + { name = "systemd_home"; enable = config.services.homed.enable; control = "required"; modulePath = "${config.systemd.package}/lib/security/pam_systemd_home.so"; } 811 + { name = "mkhomedir"; enable = cfg.makeHomeDir; control = "required"; modulePath = "${pkgs.pam}/lib/security/pam_mkhomedir.so"; settings = { 812 + silent = true; 813 + skel = config.security.pam.makeHomeDir.skelDirectory; 814 + inherit (config.security.pam.makeHomeDir) umask; 815 + }; } 816 + { name = "lastlog"; enable = cfg.updateWtmp; control = "required"; modulePath = "${pkgs.pam}/lib/security/pam_lastlog.so"; settings = { 817 + silent = true; 818 + }; } 819 + { name = "ecryptfs"; enable = config.security.pam.enableEcryptfs; control = "optional"; modulePath = "${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"; } 820 + # Work around https://github.com/systemd/systemd/issues/8598 821 + # Skips the pam_fscrypt module for systemd-user sessions which do not have a password 822 + # anyways. 823 + # See also https://github.com/google/fscrypt/issues/95 824 + { name = "fscrypt-skip-systemd"; enable = config.security.pam.enableFscrypt; control = "[success=1 default=ignore]"; modulePath = "pam_succeed_if.so"; args = [ 825 + "service" "=" "systemd-user" 826 + ]; } 827 + { name = "fscrypt"; enable = config.security.pam.enableFscrypt; control = "optional"; modulePath = "${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so"; } 828 + { name = "zfs_key-skip-systemd"; enable = cfg.zfs; control = "[success=1 default=ignore]"; modulePath = "pam_succeed_if.so"; args = [ 829 + "service" "=" "systemd-user" 830 + ]; } 831 + { name = "zfs_key"; enable = cfg.zfs; control = "optional"; modulePath = "${config.boot.zfs.package}/lib/security/pam_zfs_key.so"; settings = { 832 + inherit (config.security.pam.zfs) homes; 833 + nounmount = config.security.pam.zfs.noUnmount; 834 + }; } 835 + { name = "mount"; enable = cfg.pamMount; control = "optional"; modulePath = "${pkgs.pam_mount}/lib/security/pam_mount.so"; settings = { 836 + disable_interactive = true; 837 + }; } 838 + { name = "ldap"; enable = use_ldap; control = "optional"; modulePath = "${pam_ldap}/lib/security/pam_ldap.so"; } 839 + { name = "mysql"; enable = cfg.mysqlAuth; control = "optional"; modulePath = "${pkgs.pam_mysql}/lib/security/pam_mysql.so"; settings = { 840 + config_file = "/etc/security/pam_mysql.conf"; 841 + }; } 842 + { name = "kanidm"; enable = config.services.kanidm.enablePam; control = "optional"; modulePath = "${pkgs.kanidm}/lib/pam_kanidm.so"; } 843 + { name = "sss"; enable = config.services.sssd.enable; control = "optional"; modulePath = "${pkgs.sssd}/lib/security/pam_sss.so"; } 844 + { name = "krb5"; enable = config.security.pam.krb5.enable; control = "optional"; modulePath = "${pam_krb5}/lib/security/pam_krb5.so"; } 845 + { name = "otpw"; enable = cfg.otpwAuth; control = "optional"; modulePath = "${pkgs.otpw}/lib/security/pam_otpw.so"; } 846 + { name = "systemd"; enable = cfg.startSession; control = "optional"; modulePath = "${config.systemd.package}/lib/security/pam_systemd.so"; } 847 + { name = "xauth"; enable = cfg.forwardXAuth; control = "optional"; modulePath = "pam_xauth.so"; settings = { 848 + xauthpath = "${pkgs.xorg.xauth}/bin/xauth"; 849 + systemuser = 99; 850 + }; } 851 + { name = "limits"; enable = cfg.limits != []; control = "required"; modulePath = "${pkgs.pam}/lib/security/pam_limits.so"; settings = { 852 + conf = "${makeLimitsConf cfg.limits}"; 853 + }; } 854 + { name = "motd"; enable = cfg.showMotd && (config.users.motd != null || config.users.motdFile != null); control = "optional"; modulePath = "${pkgs.pam}/lib/security/pam_motd.so"; settings = { 855 + inherit motd; 856 + }; } 857 + { name = "apparmor"; enable = cfg.enableAppArmor && config.security.apparmor.enable; control = "optional"; modulePath = "${pkgs.apparmor-pam}/lib/security/pam_apparmor.so"; settings = { 858 + order = "user,group,default"; 859 + debug = true; 860 + }; } 861 + { name = "kwallet5"; enable = cfg.enableKwallet; control = "optional"; modulePath = "${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so"; settings = { 862 + kwalletd = "${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5"; 863 + }; } 864 + { name = "gnome_keyring"; enable = cfg.enableGnomeKeyring; control = "optional"; modulePath = "${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so"; settings = { 865 + auto_start = true; 866 + }; } 867 + { name = "gnupg"; enable = cfg.gnupg.enable; control = "optional"; modulePath = "${pkgs.pam_gnupg}/lib/security/pam_gnupg.so"; settings = { 868 + no-autostart = cfg.gnupg.noAutostart; 869 + }; } 870 + { name = "cgfs"; enable = config.virtualisation.lxc.lxcfs.enable; control = "optional"; modulePath = "${pkgs.lxc}/lib/security/pam_cgfs.so"; args = [ 871 + "-c" "all" 872 + ]; } 873 + ]; 874 + }; 769 875 }; 770 876 771 877 }; ··· 840 946 in 841 947 842 948 { 949 + 950 + meta.maintainers = [ maintainers.majiir ]; 843 951 844 952 imports = [ 845 953 (mkRenamedOptionModule [ "security" "pam" "enableU2F" ] [ "security" "pam" "u2f" "enable" ]) ··· 1402 1510 fscrypt = {}; 1403 1511 }; 1404 1512 1405 - security.apparmor.includes."abstractions/pam" = let 1406 - isEnabled = test: fold or false (map test (attrValues config.security.pam.services)); 1407 - in 1513 + security.apparmor.includes."abstractions/pam" = 1408 1514 lib.concatMapStrings 1409 1515 (name: "r ${config.environment.etc."pam.d/${name}".source},\n") 1410 1516 (attrNames config.security.pam.services) + ··· 1413 1519 mr ${getLib pkgs.pam}/lib/security/pam_*.so, 1414 1520 r ${getLib pkgs.pam}/lib/security/, 1415 1521 '' + 1416 - optionalString use_ldap '' 1417 - mr ${pam_ldap}/lib/security/pam_ldap.so, 1418 - '' + 1419 - optionalString config.services.kanidm.enablePam '' 1420 - mr ${pkgs.kanidm}/lib/pam_kanidm.so, 1421 - '' + 1422 - optionalString config.services.sssd.enable '' 1423 - mr ${pkgs.sssd}/lib/security/pam_sss.so, 1424 - '' + 1425 - optionalString config.security.pam.krb5.enable '' 1426 - mr ${pam_krb5}/lib/security/pam_krb5.so, 1427 - mr ${pam_ccreds}/lib/security/pam_ccreds.so, 1428 - '' + 1429 - optionalString (isEnabled (cfg: cfg.googleOsLoginAccountVerification)) '' 1430 - mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so, 1431 - mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so, 1432 - '' + 1433 - optionalString (isEnabled (cfg: cfg.googleOsLoginAuthentication)) '' 1434 - mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so, 1435 - '' + 1436 - optionalString (config.security.pam.enableSSHAgentAuth 1437 - && isEnabled (cfg: cfg.sshAgentAuth)) '' 1438 - mr ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so, 1439 - '' + 1440 - optionalString (isEnabled (cfg: cfg.fprintAuth)) '' 1441 - mr ${pkgs.fprintd}/lib/security/pam_fprintd.so, 1442 - '' + 1443 - optionalString (isEnabled (cfg: cfg.u2fAuth)) '' 1444 - mr ${pkgs.pam_u2f}/lib/security/pam_u2f.so, 1445 - '' + 1446 - optionalString (isEnabled (cfg: cfg.usbAuth)) '' 1447 - mr ${pkgs.pam_usb}/lib/security/pam_usb.so, 1448 - '' + 1449 - optionalString (isEnabled (cfg: cfg.usshAuth)) '' 1450 - mr ${pkgs.pam_ussh}/lib/security/pam_ussh.so, 1451 - '' + 1452 - optionalString (isEnabled (cfg: cfg.oathAuth)) '' 1453 - "mr ${pkgs.oath-toolkit}/lib/security/pam_oath.so, 1454 - '' + 1455 - optionalString (isEnabled (cfg: cfg.mysqlAuth)) '' 1456 - mr ${pkgs.pam_mysql}/lib/security/pam_mysql.so, 1457 - '' + 1458 - optionalString (isEnabled (cfg: cfg.yubicoAuth)) '' 1459 - mr ${pkgs.yubico-pam}/lib/security/pam_yubico.so, 1460 - '' + 1461 - optionalString (isEnabled (cfg: cfg.duoSecurity.enable)) '' 1462 - mr ${pkgs.duo-unix}/lib/security/pam_duo.so, 1463 - '' + 1464 - optionalString (isEnabled (cfg: cfg.otpwAuth)) '' 1465 - mr ${pkgs.otpw}/lib/security/pam_otpw.so, 1466 - '' + 1467 - optionalString config.security.pam.enableEcryptfs '' 1468 - mr ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so, 1469 - '' + 1470 - optionalString config.security.pam.enableFscrypt '' 1471 - mr ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so, 1472 - '' + 1473 - optionalString (isEnabled (cfg: cfg.pamMount)) '' 1474 - mr ${pkgs.pam_mount}/lib/security/pam_mount.so, 1475 - '' + 1476 - optionalString (isEnabled (cfg: cfg.enableGnomeKeyring)) '' 1477 - mr ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so, 1478 - '' + 1479 - optionalString (isEnabled (cfg: cfg.startSession)) '' 1480 - mr ${config.systemd.package}/lib/security/pam_systemd.so, 1481 - '' + 1482 - optionalString (isEnabled (cfg: cfg.enableAppArmor) 1483 - && config.security.apparmor.enable) '' 1484 - mr ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so, 1485 - '' + 1486 - optionalString (isEnabled (cfg: cfg.enableKwallet)) '' 1487 - mr ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so, 1488 - '' + 1489 - optionalString config.virtualisation.lxc.lxcfs.enable '' 1490 - mr ${pkgs.lxc}/lib/security/pam_cgfs.so, 1491 - '' + 1492 - optionalString (isEnabled (cfg: cfg.zfs)) '' 1493 - mr ${config.boot.zfs.package}/lib/security/pam_zfs_key.so, 1494 - '' + 1495 - optionalString config.services.homed.enable '' 1496 - mr ${config.systemd.package}/lib/security/pam_systemd_home.so 1497 - ''; 1522 + (with lib; pipe config.security.pam.services [ 1523 + attrValues 1524 + (catAttrs "rules") 1525 + (concatMap attrValues) 1526 + (concatMap attrValues) 1527 + (filter (rule: rule.enable)) 1528 + (catAttrs "modulePath") 1529 + (filter (hasPrefix "/")) 1530 + unique 1531 + (map (module: "mr ${module},")) 1532 + concatLines 1533 + ]); 1498 1534 }; 1499 1535 1500 1536 }
+1 -1
nixos/tests/pam/pam-u2f.nix
··· 20 20 '' 21 21 machine.wait_for_unit("multi-user.target") 22 22 machine.succeed( 23 - 'egrep "auth required .*/lib/security/pam_u2f.so.*debug.*interactive.*cue.*origin=nixos-test" /etc/pam.d/ -R' 23 + 'egrep "auth required .*/lib/security/pam_u2f.so.*cue.*debug.*interactive.*origin=nixos-test" /etc/pam.d/ -R' 24 24 ) 25 25 ''; 26 26 })
+5 -4
nixos/tests/pam/test_chfn.py
··· 6 6 "auth required pam_deny.so", 7 7 "auth sufficient @@pam_ccreds@@/lib/security/pam_ccreds.so action=store use_first_pass", 8 8 "auth sufficient pam_rootok.so", 9 - "auth sufficient pam_unix.so likeauth try_first_pass", 9 + "auth sufficient pam_unix.so likeauth try_first_pass", 10 10 "password sufficient @@pam_krb5@@/lib/security/pam_krb5.so use_first_pass", 11 11 "password sufficient pam_unix.so nullok yescrypt", 12 12 "session optional @@pam_krb5@@/lib/security/pam_krb5.so", ··· 15 15 } 16 16 actual_lines = set(machine.succeed("cat /etc/pam.d/chfn").splitlines()) 17 17 18 - missing_lines = expected_lines - actual_lines 19 - extra_lines = actual_lines - expected_lines 20 - non_functional_lines = set([line for line in extra_lines if (line == "" or line.startswith("#"))]) 18 + stripped_lines = set([line.split("#")[0].rstrip() for line in actual_lines]) 19 + missing_lines = expected_lines - stripped_lines 20 + extra_lines = stripped_lines - expected_lines 21 + non_functional_lines = set([line for line in extra_lines if line == ""]) 21 22 unexpected_functional_lines = extra_lines - non_functional_lines 22 23 23 24 with subtest("All expected lines are in the file"):