-
-
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/systemd: make services with DynamicUser depend on nscd #105354
Conversation
otherwise their username does not resolve to their uid Fixes NixOS#105353
I think this qualifies it for adding a
I don't think adding a dependency to nscd for all services started with On the other hand, services not making use of Let's add |
Ah. I think I saw this behavior in other places too and I was always wondering why. |
This might be true but it is also a bit of a foot gun. This is not what you would expect looking at the code. |
Hm? Not sure I understand what you mean is the footgun here :-) The fact we need to pipe all non-glibc nss calls via nscd should have been somewhat better documented as part of #86940, #87016 and #86010. I agree it's annoying, but nscd is the somewhat stable interface. Feel free to carry that discussion over here: #55276 If this service requires being able to resolve dynamic users on startup, it needs to add I'm against pulling in nscd for all other service that have Services might perfectly fine work without being able to resolve their own username, and DynamicUser itself also happily is able to allocate temporary user ids without |
I mean it is not easy to see if a service needs to resolve its own username at startup or not. It might be in binary itself and not just in startup code. And since its a race condition during upgrade when restarting both nscd and the service it also won't be a problem when testing a single service. |
Note that also from the docs of
I don't think this is the case at the moment so this is really an us bug. I suggest starting nscd during early boot (WantedBy=sysinit.target , Default dependencies=no) . DynamicUsers are system users and per systemds contract they should be resolvable as soon as sysinit.target is reached which is currently not the case. This basically has the same effect as what this PR is doing but a bit more elegantly. I'm thus in favor of this PR- with some tweaks. nss-lookup.target really is meant for things like ldap and friends. And specifically only for non-system users. When you have a named DynamicUser in a Systemd service it should immediately be usable .that's the contract Systemd provides and that we break. |
I think this problem also appears when nscd is restarted. So we would need not to restart it.
|
We could mark it "never restart" just like Another option would be to make |
Let's move nscd earlier into boot then. We still need to restart it whenever our enabled nss modules are updated, because the Not picking up changes there is probably worse than an eventual blip while restarting nscd. |
@Mic92 if |
I see. That might work. |
I did some experiments with this approach diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix
index d720f254b81..5703fd04421 100644
--- a/nixos/modules/services/system/nscd.nix
+++ b/nixos/modules/services/system/nscd.nix
@@ -79,6 +79,16 @@ in
"${nscd}/sbin/nscd --invalidate hosts"
];
};
+
+ # Services with DynamicUser=true require nscd to be fully started to
+ # resolve their own username. We add a dependency of sysinit.target to nscd to ensure
+ # these units are started after nscd is fully started.
+ unitConfig.DefaultDependencies = false;
+ wantedBy = [ "sysinit.target" "nss-lookup.target" "nss-user-lookup.target" ];
+ before = [ "sysinit.target" "shutdown.target" ];
+ conflicts = [ "shutdown.target" ];
+ wants = [ "local-fs.target" ];
+ after = [ "local-fs.target" ];
};
}; It looks like it does not fully solve the problem because once sysinit.target is started, restarting sslh and nscd together will happen in any order. sslh only depends on sysinit.target but it is already up. So I'm afraid we need a direct dependency from services to nscd without mediation through a target unit. |
I think the problem is that |
The way I expected For now; perhaps we should make sure in our activation script that I don't know which of the two options is best. I'm ok with adding the direct dependency to all services but I'd prefer if our activation script would understand the entire dependency graph but that's probably too much to ask for now. inplace system activation is just a bit buggy and racey in its current shape =( |
I very much prefer making systemd aware of the specificities of our setup by adding explicit dependencies on nscd to working around systemd by hacking the activation script. |
What is actually the security advantage of |
Not managing UIDs does not work. UID ownership is sticky. Say you deploy The alternative is managing a list of global UIDs and make sure you never reuse any of them but that's also not nice (but is how we coped in NixOS before this feature)
From the manpage:
|
I think this PR is good to merge. But I still think it's a good idea to move We could add that patch in a separate PR or add it to this PR as well. I'm ok with either. |
NixOS actually has |
How about starting nscd before the rest? Nscd will be ready after diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index b82d69b3bb8..a41fa70b62c 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -349,6 +349,7 @@ sub filterUnits {
my @unitsToStopFiltered = filterUnits(\%unitsToStop);
my @unitsToStartFiltered = filterUnits(\%unitsToStart);
+my $startNscd = delete $unitsToStart{nscd.service};
# Show dry-run actions.
if ($action eq "dry-activate") {
@@ -359,6 +360,7 @@ sub filterUnits {
print STDERR "would restart systemd\n" if $restartSystemd;
print STDERR "would restart the following units: ", join(", ", sort(keys %unitsToRestart)), "\n"
if scalar(keys %unitsToRestart) > 0;
+ print STDERR "would start nscd\n" if $startNscd;
print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n"
if scalar @unitsToStartFiltered;
print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n"
@@ -434,6 +436,13 @@ sub filterUnits {
unlink($restartListFile);
}
+
+# Services depending on DynamicUser needs nscd to resolve users/groups
+if $startNscd {
+ print STDERR "starting the nscd\n";
+ system("@systemd@/bin/systemctl", "start", "nscd.service") == 0 or $res = 4;
+}
+
# Start all active targets, as well as changed units we stopped above.
# The latter is necessary because some may not be dependencies of the
# targets (i.e., they were manually started). FIXME: detect units |
This is what I proposed originally and personally I think combined with making
But @flokli and @symphorien seem to disagree it's the right approach. I still think it's the better approach though. The direct dependency on I'm ok with making this change to |
@symphorien I think your solution fixes services that directly depend on their own dynamic user. However it seems that we also need the same users for other services i.e. the firewall service: #106127 |
|
oh I had not seen this PR does also hack nixos-rebuild. Fine then. Again I would prefer making systemd aware of dependencies rather than working around it, because then bare systemctl restart would work, but do as you wish. |
Let's close this in favor of #106336. |
otherwise their username does not resolve to their uid
Fixes #105353
Things done
Tested with the sslh nixos test
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)