-
-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Use structured settings for PAM configuration #105098
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
base: master
Are you sure you want to change the base?
Conversation
Coalesce lines where possible, to reduce the number of screens of options
This is a more structured form, that will allow easier editing later.
ping @Rudi9719 @flokli who were part of the original discussion I think this is already a huge step forward, i.e. we now have some structure for entries! Though I'm not too fond of the structure used (a list) to store those entries. I would have imagined something like this:
But this stops working when you want to use the same module several times, like
But I want to change that to invert the order, for whatever reason, how would I go about it? Overriding order in sets is easy, as we just have to change an A solution to that would be to use sets like this:
and then we could do something like |
Also, you said that your current changes keep the external interface, but we shouldn't feel blocked by this. It isn't used widely in nixpkgs, and people tweaking it in their config would either be happy with an improvement of the pam situation, or they're already overriding the whole module like I do. Either way, it'll probably end up in the release notes anyway. |
@rissson your suggestions are good 👍 The |
Agreed - I think we can do better here, I just wasn't sure enough on how to begin. In fact, the current implementation wouldn't necessarily solve my original issue ;) Note the proposed My only question is how we should assign orderings to our default values - should we leave a gap (say 100) between each default entry? Or should we group them into blocks with the same priority? Perhaps certain rules should generally move together, and a more tree-like structure is called for (see Regarding structuring the attributes as I also plan to improve support for |
Just so you know @kwohlfahrt, I started building something with |
nixos/modules/security/pam.nix
Outdated
|
||
{ | ||
makePAMService = name: service: let | ||
argumentToString = value: if hasInfix " " value then "[${escape [ "]" ] value}]" else value; |
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.
Why do we need the escape here?
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.
Nevermind, I RTFMed
Note, if you wish to include spaces in an argument, you should surround that argument with square brackets.
When using this convention, you can include
[' characters inside the string, and if you wish to include a
]' character inside the string that will survive the argument parsing, you should use `]'. In other words: [..[..]..] --> ..[..]..
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.
Maybe it should be up to the user to escape any ]
in a single argument that contains spaces. I'm guessing we will miss something here and it might break stuff for people. Let's not do backend stuff like this, users getting to this level of configuration already know about this or will find out from the manpage like I did.
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.
I soooo wish I could think of a way to make this more Nixy than a list of strings. For example, if I want to override the umask in the mkHomeDir
module, I'd have to override the whole list, and I wouldn't be able to do something like mkHomeDir.args.umask = "0027";
(random value, use at your own risk). Anyone else has a take on this?
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 not do backend stuff like this, users getting to this level of configuration already know about this or will find out from the manpage like I did.
I disagree pretty strongly with this take, because accidentally adding an argument with spaces doesn't result in an error, it results in a silently different configuration (with that argument treated as multiple separate arguments). You clearly have been configuring PAM modules, and weren't aware of the need to escape spaces. If you had added an argument that contained spaces, it would have silently been accepted but then treated as multiple separate arguments, which could have resulted in an insecure configuration.
I'm also unable to think of a situation in which case us doing the escaping would cause trouble, apart from perhaps double-escaping. But I think people are more likely to read the nix option docs, where we can note that we do this.
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.
I soooo wish I could think of a way to make this more Nixy than a list of strings.
I agree here, but there are lots of options that are just a single string... 🤷 It'd be nice if they had to be key-value pairs.
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.
Ah, I have a thought. We can use types.attrsOf (types.either types.str types.bool)
. Then, if the value is bool
, we add the key if it is true
, omit the key if it is false
. If the value is str
, we use key=value
syntax. Could this work?
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.
I can't see how that would work. Could you give an example?
attrsOf (nullOr str)
might be better. It would look like this, assuming we have a render
function outputting the result from a single argument (name, value pair):
>>> render { name = "debug"; value = null; }
"debug"
>>> render { name = "umask"; value = "0027"; }
"umask=0027"
Usage:
args = {
debug = null;
umask = "0027";
};
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.
I missed this comment, I was thinking as follows:
args = {
debug = true;
umask = "0027";
}
which would render as "debug umask=0027"
. The render
function would check whether the attr value is a string, in which case i renders as "key=value"
or a boolean, in which case it renders "key"
if the value is true
, otherwise ""
. The advantage of this is it allows removing a key, by doing { args.debug = mkForce false; }
, I'm not sure theres a nice way of unsetting a key from an attrset?
nixos/modules/security/pam.nix
Outdated
{ | ||
makePAMService = name: service: let | ||
argumentToString = value: if hasInfix " " value then "[${escape [ "]" ] value}]" else value; | ||
controlToString = value: |
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.
It would be nice to use the apply arg to mkOption
to achieve this
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.
Something like this:
control = mkOption {
type = controlType;
apply = value: if isString value then value else
concatStringsSep " " (mapAttrsToList (n: v: "${n}=${toString v}") value);
};
args = mkOption {
default = [];
apply = value: concatStringsSep " " (map toString value);
};
EDIT: it didn't work before
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.
{ control = "required"; path = "pam_deny.so"; }]; | ||
in listToAttrs (map (t: nameValuePair t rules) [ "auth" "account" "password" "session" ]); | ||
|
||
# Most of these should be moved to specific modules. |
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.
I wonder where those would end up...
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.
I think the original intent was that the kerberos rules would live in their respective packages (e.g. kerberos, LDAP, etc).
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.
Indeed.
Oops, sorry for the merge conflicts :P I'm interested to see what you come up with, the downside to using
I think combined with the include/substack support I just added, this could be promising? |
I still have to figure out how to integrate the include/substack functionality of PAM in my implementation. I wonder if it is relevant to have it in NixOS. Maybe let's table that discussion for later? We won't lose any functionality anyway... |
I just included the
I think include and substack should just be another control type, without enforcing anything. What if someone wants to do:
|
Passing a string path is supported, it just also supports passing more entries, in which case they will be written to a file and that will be included. They use the same attribute, so you can |
That's nice. But that means there would be two ways of using include/substack, and I don't think we want that. Also |
My example wasn't clear, the directive is still explicitly required:
This way I think it looks quite similar to what you were proposing (except I think supporting nested rules via nix expressions is useful, because |
What about creating another PAM service that you then use in your substack?
Yes, that has to be supported, of course. |
I'm not sure I follow here. The substack entries could refer to another services rules like this, but I'm not sure that's what you mean...
The actual file containing the rules will be a store path, not a service path in |
What I meant is that your
|
You could, but that would be relying on a NixOS implementation detail. Nothing is stopping us from migrating to having all service configs together in Not suggesting we do that, but that seems like a fragile configuration, that just so happens to work because of the details of the current implementation (and should not be encouraged, but I don't see any way to prevent it). |
I marked this as stale due to inactivity. → More info |
I'd still love to see this getting in :-) |
No better time than in a few weeks, once 21.11 is released. |
Sorry to bump, but is there anything that can be done to help? |
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/4 |
Motivation for this change
Originally, this was brought on by the lack of support for the
crypt
option topam_ldap
, with no easy way of changing it. #90640 then provided motivation for a more thorough rework. So far, this PR keep the external interface, but replacessecurity.pam.services.<name>.text
with.entries
, consisting of a list of structured entries.I'm opening the PR now for discussion, because this is a large change and @rissson was interested in working together.
TODO
mkRenamedOptionModule
where appropriateThings done
sandbox
innix.conf
on non-NixOS linux)nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
./result/bin/
)nix path-info -S
before and after)