Hi, I’m trying to setup a nixos-container with nginx + PAM authentication. I have succeeded with a dirty hack, and I’m wondering if there is a better way.
By default nginx runs as the nginx user.
By default, /etc/shadow is 0600 and owned by root:root
Despite setting security.pam.services.nginx = {};
and setting ''auth_pam_service_name "nginx";'' in the extraConfig of nginx,
nginx will always return Authentication failed when trying to login.
Then, I’ve installed ‘pamtester’ to find out what is going on.
It seems that when not using root, it is impossible to access the /etc/shadow file. But I’m confused, because I thought the unix_chkpwd utility would take care of this.
Anyway, there are multiple ugly solutions to this problem.
run nginx as root
chmod 0640 /etc/shadow
and create a group ‘shadow’ and chgrp shadow /etc/shadow and add nginx user to group shadow
This seems impossible with Nix, because the group and mode of /etc/shadow seems hardcoded by some Perl script.
why can’t nginx access /etc/shadow despite the presence of unix_chkpwd utility
Is there a better way than running nginx as root?
I have updated the WIKI, Nginx - NixOS Wiki
Please check if the information is correct. I still think giving root access to nginx is probably not the correct solution, but I’m not an expert on PAM
If you look at the source for unix_chkpwd (linux-pam/unix_chkpwd.c at 48f44125fac8873237ade9e94942f82a8e6d6e1d · linux-pam/linux-pam · GitHub) you see a check whether it’s being executed as root. In the case of nginx unix_chkpwd is called by the nginx user in which case it forbids authentication as another user (thus pam auth with nginx would only work for the nginx user). I think this is generally reasonable/desirable behavior for 99% of use cases (ex. screen locking, etc.). IMO running nginx as root is unacceptable security-wise, and chgrp-ing /etc/shadow is the “correct” way to go. This is consistent with the suggestion here https://github.com/sto/ngx_http_auth_pam_module#examples :
if you want to use the pam_unix.so module to autenticate users you need to let the web server user to read the /etc/shadow file if that does not scare you (on Debian like systems you can add the www-data user to the shadow group).
Unfortunately the script still creates (hardcodes) the permission of /etc/shadow to 0600
so despite adding nginx to the shadow group, it cannot access /etc/shadow, so the problem and workaround in the OP remains in 20.09
On top of that, it seems unix_chkpwd has issues:
Nov 01 22:31:55 server [2748]: pam_unix(nginx:auth): unix_chkpwd abnormal exit: 134
Nov 01 22:31:55 server [2748]: pam_unix(nginx:auth): authentication failure; logname= uid=60 euid=60 tty= ruser= rhost=12.123.123.12 user=kvtb
Nov 01 22:31:55 server systemd-coredump[2752]: [🡕] Process 2750 (unix_chkpwd) of user 60 dumped core.
Nov 01 22:31:56 server nginx[2748]: 2020/11/01 22:31:55 [error] 2748#2748: *1 PAM: user 'kvtb' - not authenticated:
Authentication failure, client: 12.123.123.12, server: mydomain.com, request: "GET /privatearea/ HTTP/2.0", host: "mydomain.com"
It could be that systemd has something to do with this.
I’ve spent a few hours today to see if I can find the cause and solve the problem.
When I run nginx directly from the command line, it does not crash when accessing a location with auth_pam
But the exact same configuration but started with systemctl will crash the nginx work processes.
I don’t know enough about systemd internals to debug this any further
Maybe you could try to adapt some of the work in that thread to your config and see if you have some success. If you can’t make any progress with that I can try to find some time to look at it.
It looks like the following works. It could be that even less options are required, so this is the maximum number of option overrides to make it work for PAM authentication: