I'm running a publicly accessible transactional HTTPS API based system that's running on nginx. API passwords are being passed in GET/POST data (via HTTPS), and of course, when GET is used, each API user's password is being written to the access_log as it's part of the query string. A typical access looks something like this:
https://example.com/api/test.php?username=api1&password=pass2&action=moveleft
Obviously, I need to mask the password in the nginx logs so they can be shared with engineers, support staff etc and to comply with password storage policies.
It would be easy to define a custom log format and remove the GET data completely, however it's useful to have this for debugging and other than the password contains nothing sensitive.
Ideas I've come up with so far are:
1. Write the access log to a named pipe (mknod p) and have a filter process that's reading from that pipe, filtering out the password and replacing it with "xxxxxx". Simple on the nginx side, but it's a headache to have another process running, and it would need to be restarted when the logs are rotated.
2. Define a custom log format that includes a different variable in place of $request, and set that variable with a sanitized version of $request within the nginx config
Option #2 is obviously the cleaner approach, but I'm having a hard time coming up with a regex that will transform the URL above to https://example.com/api/test.php?username=api1&password=xxxxxx&action=moveleft
Any ideas? I'm trying something like this, however the location isn't matching the URL and it's falling through to the default.
location /api/test.php?(.*)(&password=[^&]+)(.*) {
set $sanitizedrequest $1&password=xxxxxx$3;
access_log /tmp/password.log nopassword;
try_files $uri $uri/;
}
I suppose this could be done more easily with lua or Perl filters, but I'm hoping that it's possible to extract/replace the parameter with a standard nginx regexp.
Suggestions anyone?
Thanks,
Toby.