-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nixos/pam: rework of the entire module #105319
Conversation
Will it be possible to change the order of modules? For example: SSSD won't work unless it comes before Unix |
Yep! That's something I forgot to add as an example. For example:
Might have to |
324293c
to
1556605
Compare
Some explanation regarding this. Due to the way the
Each PAM pipeline (auth, account, password, session) is a big
Which means "hey, I don't want any of those defaults for the account pipeline, here is my custom pipeline for auth, and leave the default for the two other pipelines". Which is great! We want that kind of customization (i.e. service can choose which pipeline they want to override). However, where it falls short is for a user who wants to override the order, for example:
This overrides the whole
and that's it. No wonder it fails. Now, the solution I see:
Shortcoming of this: requires even more logic then there already is in the modules code, for each pipeline they would have to do something like About the EDIT: formatting, typos |
Here is a patch that gives said error. I have no idea why this is happening. Any help would be welcomed and much appreciated! https://bin.lama-corp.space/raw/1k5M1WoUC6_H8MaqGOggc EDIT: @infinisil found the problem and I was able to implement |
I wonder if all the orders should be mkDefaulted... |
security.pam.services.lightdm.enableKwallet = true; | ||
security.pam.services.sddm.enableKwallet = true; | ||
security.pam.services.kde = { modules.unix.allowNullPassword = true; }; | ||
security.pam.modules.kwallet.enable = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make sure this is really what we want.
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
…module Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/reworking-the-nixos-pam-module-a-walk-through/10334/1 |
Haven't done more than glance at these changes yet, but it seems likely it will at least partially, if not fully, address #95017. Locally I've been using my own override that does what appears to be similar to In that issue there's also the error |
Also, I'll add a quick comment about PAM activation by default when krb5 is enabled, tell me what you think is best. |
mkSvcConfigCondition = svcCfg: cfg.enable && svcCfg.modules.${pamModName}.enable; | ||
|
||
mkModuleOptions = global: { | ||
enable = mkOption { | ||
type = types.bool; | ||
default = if global then true else pamModCfg.enable; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mkSvcConfigCondition = svcCfg: cfg.enable && svcCfg.modules.${pamModName}.enable; | |
mkModuleOptions = global: { | |
enable = mkOption { | |
type = types.bool; | |
default = if global then true else pamModCfg.enable; | |
mkSvcConfigCondition = svcCfg: svcCfg.modules.${pamModName}.enable; | |
mkModuleOptions = global: { | |
enable = mkOption { | |
type = types.bool; | |
default = if global then cfg.enable else pamModCfg.enable; |
Should we do this instead?
I'll try to have a more detailed review of this tomorrow and Monday, it's a big PR! I've read through the descriptions and the proposals look sensible. I'll try and review the implementation in a bit more detail tomorrow and Monday. Is the idea of Perhaps renaming I also want to discuss the use of
This makes the dependencies between modules clear. Whereas an ordering to achieve the same dependencies might be:
This defines an order that satisfies the dependencies, but doesn't make clear which parts of the relationship are important. I'd like to see the conversations on the other PR resolved before merging this:
|
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
I'm currently stumbling in the dark with PAM, slowly making some sense of some things in #119710 , if we can do anything to improve the debugging experience, that would be cool. As a small note, I'm currently waiting for a large rebuild, but the |
The PAM control for this entry. It can be either on of the | ||
historical basic control keywords, of a set of result-actions pairs. | ||
''; | ||
apply = value: if isString value then value else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use apply
, it leaks the module implementation to the outside, since config.the.option
, accessible from all modules, will have this function applied already. This also makes it difficult for other modules to reuse this option's value. In this case parsing would be needed.
You can achieve this with a let in
binding instead.
Same for all the other uses of apply
Is this pr still active? |
This PR is way too huge to be merged as is. However, it exposes the ideas I had for refactoring the PAM module. We had a discussion with @Pamplemousse a while ago about how to break it down into smaller, more reviewable PRs. Hit us up if you want to discuss it! |
Well you still deserve a huge thank you for the huge effort behind the bold PR, thank you! |
@rissson, thanks for the massive contribution. Hopefully at some point we can get this reworked and merged in more manageable steps. Since you expressed above not wanting to merge this as is, I hope you don't mind if I go ahead and close it for now. |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/what-do-you-want-from-pam-security-pam-in-nixos/33265/2 |
Did anyone rework pam yet? |
@nyabinary Some work was done with #255547! |
Hi all!
First, I know this PR looks scary, because it is. But I couldn't see another way of making this module better without starting from scratch.
Here is my solution to the current PAM problem in NixOS. The problem is described extensively in #90640 and all related issues and PRs. It basically boils down to the PAM module not being managed by module system, and thus integrates badly with other modules, resulting in PAM services being hardcoded by other modules (yes, I am looking at you display managers 👀, but you had no other choice :/).
Origin, requirements and blockers
This PR builds on top of #105098, which is a step forward, but still has some flaws regarding ordering and the ability to easily override something as a user. See my comments over there for what I think needs improving, and is basically the idea that started my work on this.
We also need #97023 to be able to use
mkRenamedOptionModule
inside submodules. This isn't a blocker for review, see below.Design
I'll start with how the PAM module can be interacted with. It is now divided into top level options:
Under the hood, each module does... nothing! Actually, the toplevel
modules
configuration option only exists to provide default options to the modules defined in each service. And thus, the modules in the services do the work, meaning they will add entries to the relevant PAM types (account
,auth
,password
,session
) depending on the options that are set in it. To see how this is rigged, have a look insidenixos/modules/security/pam/modules
. I guess the best explanation of how this all works at this point is with examples.Interacting with the PAM module
Creating a new service with the defaults
A service overriding something in the modules
Changing a module option for all services
Changing a module option for one service
Creating a custom service, using none of the defaults
This will be especially useful for display managers.
This will result in
/etc/pam.d/myService
containing:Changing the order in which the entries appear in the file
Looking at the orders table below, if we want to make
krb5
come beforeldap
and afterunix
in theaccount
type for thelogin
service, we can do something like this:Include/substack
If we look at the
lightdm
PAM service onmaster
, we can see it looks like this:To do the same with this PAM module, we can do the following:
Which will generate the same PAM service file (modulo the order of the types (i.e.
account
will come beforeauth
) and whitespace).Ordering of the PAM modules
This used to be done using
types.orderOf
(see #97392) and comparing theorder
value of each PAM entry, and then @roberth suggested to me that it could actually be done just by usingbuiltins.sort
. The lower that value, the higher the entry ends up in the file.To avoid more breaking changes than necessary \s, I decided to keep the old order of PAM modules. More seriously, the goal is to leave users who don't interact with the PAM module alone, the interface might change, but they won't see it as they will get the same result.
Here's that table:
The chosen values are complitely arbitrary, except that they conserve the current order of modules. They might seem excessive, I might have been over enthused, but at least they give people and us a lot of room to move stuff around.
Some other improvements / stuff that changed
nixos/modules/security/pam
and each PAM module has its own file undermodules/
, except for the PAM modules that have been moved to their related NixOS modulefprintd
PAM module now usesservices.fprintd.package
instead of hardcodingpkgs.fprintd
mkRenamedOptionModule
fprintd
apparmor
duosec
gnome-keyring
ldap
krb5
lxcfs
New and renamed PAM modules options
No new PAM modules or options have been added, as it is not the goal of this PR. However, due to the way this module is implemented, new options have appeared nonetheless, as modules are now configurable globally and per-service.
New options
security.pam.modules.apparmor.enable
security.pam.modules.duosec.enable
security.pam.modules.forwardXAuth
security.pam.modules.fprintd.enable
security.pam.modules.gnome-keyring.enable
security.pam.modules.gnupg.*
security.pam.modules.googleAuthenticator.enable
security.pam.modules.googleOsLogin.*
security.pam.modules.krb5.enable
security.pam.modules.kwallet.enable
security.pam.modules.logFailures
security.pam.modules.lxcfs.enable
security.pam.modules.makeHomeDir.enable
security.pam.modules.motd.*
security.pam.modules.requireWheel
security.pam.modules.rootOK
security.pam.modules.setEnvironment
security.pam.modules.setLoginUid
security.pam.modules.sssd.*
security.pam.modules.startSession
security.pam.modules.unix.*
security.pam.services.<name>.account
security.pam.services.<name>.auth
security.pam.services.<name>.password
security.pam.services.<name>.session
security.pam.services.<name>.excludeDefaults
security.pam.services.<name>.modules.ecryptfs.enable
security.pam.services.<name>.modules.krb5
security.pam.services.<name>.modules.ldap.enable
security.pam.services.<name>.modules.limits
security.pam.services.<name>.modules.lxcfs.enable
security.pam.services.<name>.modules.makeHomeDir.skelDirectory
security.pam.services.<name>.modules.motd.motdFile
security.pam.services.<name>.modules.oath
(exceptenable
)security.pam.services.<name>.modules.p11
(exceptenable
)security.pam.services.<name>.modules.sssd.enable
security.pam.services.<name>.modules.u2f
(exceptenable
)security.pam.services.<name>.modules.unix.debug
security.pam.services.<name>.modules.yubico
(exceptenable
)Renamed options
security.pam.enableEcryptfs
->security.pam.modules.ecryptfs.enable
users.ldap.loginPam
->security.pam.modules.ldap.enable
security.pam.loginLimits
->security.pam.modules.limits
: type changed, no possibility ofmkRenamedOptionModule
security.pam.makeHomeDir.skelDirectory
->security.pam.modules.makeHomeDir.skelDirectory
security.pam.oath
->security.pam.modules.oath
security.pam.enableOTPW
->security.pam.modules.otpw.enable
security.pam.p11
->security.pam.modules.p11
security.pam.mount
->security.pam.modules.pam_mount
security.pam.enableSSHAgentAuth
->security.pam.modules.sshAgent.enable
security.pam.services.<name>.sssdStrictAccess
->security.pam.services.<name>.modules.sssd.strictAccess
security.pam.u2f
->security.pam.modules.u2f
security.pam.usb.enable
->security.pam.modules.usb.enable
security.pam.yubico
->security.pam.modules.yubico
security.pam.services.<name>.enableAppArmor
->security.pam.services.<name>.apparmor.enable
security.pam.services.<name>.duoSecurity.enable
->security.pam.services.<name>.modules.duosec.enable
security.pam.services.<name>.forwardXAuth
->security.pam.services.<name>.modules.forwardXAuth
security.pam.services.<name>.fprintAuth
->security.pam.services.<name>.modules.fprintd.enable
security.pam.services.<name>.enableGnomeKeyring
->security.pam.services.<name>.modules.gnome-keyring.enable
security.pam.services.<name>.gnupg
->security.pam.services.<name>.modules.gnupg
security.pam.services.<name>.googleAuthenticator.enable
->security.pam.services.<name>.modules.googleAuthenticator.enable
security.pam.services.<name>.googleOsLoginAccountVerification
->security.pam.services.<name>.modules.googleOsLogin.enableAccountVerification
security.pam.services.<name>.googleOsLoginAuthentication
->security.pam.services.<name>.modules.googleOsLogin.enableAuthentication
security.pam.services.<name>.enableKwallet
->security.pam.services.<name>.modules.kwallet.enable
security.pam.services.<name>.logFailures
->security.pam.services.<name>.modules.logFailures
security.pam.services.<name>.makeHomeDir
->security.pam.services.<name>.modules.makeHomeDir.enable
security.pam.services.<name>.showMotd
->security.pam.services.<name>.modules.motd.enable
security.pam.services.<name>.oathAuth
->security.pam.services.<name>.modules.oath.enable
security.pam.services.<name>.otpwAuth
->security.pam.services.<name>.modules.otpw.enable
security.pam.services.<name>.p11Auth
->security.pam.services.<name>.modules.p11.enable
security.pam.services.<name>.pamMount
->security.pam.services.<name>.modules.pam_mount.enable
security.pam.services.<name>.requireWheel
->security.pam.services.<name>.modules.requireWheel
security.pam.services.<name>.rootOK
->security.pam.services.<name>.modules.rootOK
security.pam.services.<name>.setEnvironment
->security.pam.services.<name>.modules.setEnvironment
security.pam.services.<name>.setLoginUid
->security.pam.services.<name>.modules.setLoginUid
security.pam.services.<name>.sshAgentAuth
->security.pam.services.<name>.modules.sshAgent.enable
security.pam.services.<name>.startSession
->security.pam.services.<name>.modules.startSession
security.pam.services.<name>.u2fAuth
->security.pam.services.<name>.u2fAuth
security.pam.services.<name>.unixAuth
->security.pam.services.<name>.modules.unix.enableAuth
security.pam.services.<name>.allowNullPassword
->security.pam.services.<name>.modules.unix.allowNullPassword
security.pam.services.<name>.nodelay
->security.pam.services.<name>.modules.unix.nodelay
security.pam.services.<name>.updateWtmp
->security.pam.services.<name>.modules.updateWtmp
security.pam.services.<name>.usbAuth
->security.pam.services.<name>.modules.usb.enable
security.pam.services.<name>.yubicoAuth
->security.pam.services.<name>.modules.yubico.enable
TODO
nixos/modules/security/pam/modules/*
for examplesnixos/modules/security/pam/modules
with a function that does thesubmodule
part of the work. See nixos/pam: rework of the entire module #105319 (comment)mkDefault
all the entries ordersmkRenamedOptionModule
imports, where relevant and possible. The list is available above, and we need [Reverted] Module-builtin assertions, disabling assertions and submodule assertions #97023 to be able tomkRenamedOptionModule
inside submodules. This isn't so much a blocker for review, as you can base that review on the list provided above.Services migration
To remove the
text = mkDefault [...]
in thepamServiceSubmodule
, we have to migrate a bunch of modules that are still using the old interface. If this PR is accepted, I will create an issue with the following list and ping the respective maintainers of the modules so they can migrate, and I'll be happy to give them a hand.services/x11/desktop-managers/gnome3.nix
services/x11/display-managers/sddm.nix
services/x11/display-managers/gdm.nix
services/x11/display-managers/lightdm.nix
services/networking/vsftpd.nix
Documentation
I still need to write some documentation for this, mainly release notes, and the PAM section of the manual. Most of this is just formatting and expanding the description of the PR above.
Here's a list of TODOs for the documentation:
III. Administration
nixos/doc/manual/development/writing-modules.xml
with the new path to the PAM moduleTesting
How to test this
If you are using flakes, change your
nixpkgs
input togithub:rissson/nixpkgs/nixos-pam
and thennix flake update --update-input nixpkgs && nixos-rebuild --flake .#myHost build-vm
.If you're not, you can do something along the lines of
nixos-rebuild -I 'nixpkgs=https://github.com/rissson/nixpkgs/archive/nixos-pam.tar.gz build-vm
. I haven't tested this.Then you can execute the commands it gives you to start the VM and try this out.
To make it a bit easier to report your finding, I made a small snippet you can copy paste when commenting on this PR (you can remove everything you didn't tick for a more concise output):
I'll start:
cue = true; control = "sufficient";
/etc/passwd
from a TTY. You won't test anything if you try this from a display manager, as it probably doesn't use the new PAM module. Works for root, and for a user.pam-u2f.nix
krb5
openssh.nix
ecryptfs.nix
lightdm.nix
pam-oath-login.nix
CC.ing people
People part of the original conversation about reworking this module
@flokli @Rudi9719 @kwohlfahrt
People who previously worked or reviewed some related stuff
@Mic92 @aanderse
People working on the blockers for this PR
@infinisil for
mkRenamedOptionModule
inside submodules