-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
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/acme: 20.03 -> 20.09 regression with opensmtpd #101389
Comments
Merely a workaround but you could probably copy them to another directory after each run. This isn't pretty but would at least unblock you - if this is a blocker at all. In the long run we might want to consider supporting this and maybe OpenSMTPD can be taugtht to not enforce the uid 0 rule. Removing the code that does that specific check seems rather trivial: https://github.com/OpenSMTPD/OpenSMTPD/blob/a6a39cb0cb6ee72d194f84d6763997df7e0c0bf3/usr.sbin/smtpd/ssl.c#L117-L121. I wonder what they threat model looked like. Is their assumption having files as another uid is less/more safe? |
Thanks, I will try this!
Presumably, having a file as another uid is less safe, otherwise it wouldn't make sense to enforce that rule. One reason might be that if a file has 600 or 400 permissions and is owned by root, then it can only be read by root. If it is owned by another uid, then it can be read by root and that uid. But I don't know if this is the actual reason for the rule. |
The reason for enforcing the acme user is twofold:
Copying them to another directory would be the best option here. The real thing you're fighting with regards to adding chown to postRun is the
It might be possible to do some adaptation in the service scripts so that all the chown commands use $USER instead of acme. That would mean you could then override all the systemd service users by hand (via `systemd.services..serviceConfig.User`) and get what you need. However I don't see this solving any issues that a copy command in postRun doesn't solve, and is also more complex to use.
|
I'd also propose copying them to another directory for now, outside of the acme module. Once systemd 247 has landed, this should probably be revisited. It adds Then, files will be made readable by the process that runs the service:
This will probably be In the more long-term, it might be a good idea to go into discussions with upstream of running opensmtpd, as a less-privileged user, and provide the necessary capabilities to bind on low ports, like we do with |
I can confirm that copying to another directory seems to work for me. Thanks! |
I'm running into the same issue with PostgreSQL (sanitized):
We do already run PostgreSQL as the user |
I added some pre-start code to do the "copy certs to a new directory" and it looks like PostgreSQL also cares about the permissions:
Handling it in my pre-start code but something to keep in mind when developing a better solution. |
I marked this as stale due to inactivity. → More info |
Did not verify (yet) whether this still breaks. |
Totally forgot about this actually. It's been so long that @flokli's comment about using LoadCredential can and should be tested as a solution, as it's something that would work to fix the mentioned Postgres issues too. I have to fix some bugs with the postfix tests too, was planning to do it this weekend and will do this at the same time if no one is in a rush for it. |
For both opensmtp and Postgresql using LoadCredential is a viable solution. Shown below is a minimal opensmtpd config which loads: { pkgs, config, ... }:
let
mailDomain = "example.com";
certDir = config.security.acme.certs."${mailDomain}".directory;
in {
services.opensmtpd = {
enable = true;
setSendmail = false;
serverConfiguration = ''
pki ${mailDomain} cert "cert.pem"
pki ${mailDomain} key "key.pem"
listen on localhost tls pki ${mailDomain}
action act1 relay host smtp://127.0.0.1:10027
match for local action act1
'';
};
systemd.services.opensmtpd.requires = ["acme-finished-${mailDomain}.target"];
systemd.services.opensmtpd.serviceConfig.RuntimeDirectory = "opensmtpd";
systemd.services.opensmtpd.serviceConfig.WorkingDirectory = "/var/run/opensmtpd";
systemd.services.opensmtpd.serviceConfig.LoadCredential = [
"cert.pem:${certDir}/cert.pem"
"key.pem:${certDir}/key.pem"
];
systemd.services.opensmtpd.preStart = ''
ln -s $CREDENTIALS_DIRECTORY/cert.pem .
ln -s $CREDENTIALS_DIRECTORY/key.pem .
'';
security.acme.certs."${mailDomain}".postRun = ''
systemctl restart opensmtpd
'';
} This results in cert.pem and key.pem having the correct permissions for opensmtpd to start up, and from testing they are correctly updated when the service is restarted. The last few lines (from LoadCredential down) are almost identical for Postgresql. There may be a way to avoid the symlinks and RuntimeDirectory change if there is a way to use environment variables in the smtpd.conf, or if the $CREDENTIALS_DIRECTORY can be predicted (it seems to be /run/credentials/$servicename, but I dont know hot reliable that is). The only catch I can see with this right now is that LoadCredential doesn't appear to support service reloads. This is a problem for the likes of Postgres which accepts a SIGHUP for a configuration reload from disk (and thus refreshing certs) without dropping connections. That said, some users may be fine with simply restarting the service for cert renewals. This feature is very new to Systemd and I can't find much discussion on it beyond the RFE so if someone knows if reloading/refreshing the files created by LoadCredential is possible please let me know! This does not stop us adding a useACMEHost-like option to opensmtpd right now though. :) |
A bit of research into whether CREDENTIALS_DIRECTORY will always be in /run/credentials/$servicename led me to this section of the systemd source, where an assumption is being made that With that, the above opensmtpd configuration can be greatly simplified:
Now we don't need to set Runtime/WorkingDirectory or add preStart scripts. This is remarkably subtle to add to existing services where specific permissions are required for the cert files. |
I marked this as stale due to inactivity. → More info |
The issue with |
I'll opened a new issue |
Describe the bug
When upgrading from 20.03 to 20.09, opensmtpd stopped working (apparently) due to ownership changes in #91121:
As you can see, opensmtpd seems to require the certificates to be owned by root.
I tried adding
chown root fullchain.pem key.pem
tosecurity.acme.certs.postRun
but it seems that the ownership resets toacme
when rebooting.To Reproduce
Expected behavior
opensmtpd should start without errors.
Notify maintainers
@m1cr0man @lheckemann @mweinelt @flokli
Metadata
The text was updated successfully, but these errors were encountered: