Proposal: Save user's original authenticated identity for logging - Mailing list pgsql-hackers
From | Jacob Champion |
---|---|
Subject | Proposal: Save user's original authenticated identity for logging |
Date | |
Msg-id | c55788dd1773c521c862e8e0dddb367df51222be.camel@vmware.com Whole thread Raw |
Responses |
Re: Proposal: Save user's original authenticated identity for logging
Re: Proposal: Save user's original authenticated identity for logging |
List | pgsql-hackers |
Hello all, First, the context: recently I've been digging into the use of third- party authentication systems with Postgres. One sticking point is the need to have a Postgres role corresponding to the third-party user identity, which becomes less manageable at scale. I've been trying to come up with ways to make that less painful, and to start peeling off smaller feature requests. = Problem = For auth methods that allow pg_ident mapping, there's a way around the one-role-per-user problem, which is to have all users that match some pattern map to a single role. For Kerberos, you might specify that all user principals under @EXAMPLE.COM are allowed to connect as some generic user role, and that everyone matching */admin@EXAMPLE.COM is additionally allowed to connect as an admin role. Unfortunately, once you've been assigned a role, Postgres either makes the original identity difficult to retrieve, or forgets who you were entirely: - for GSS, the original principal is saved in the Port struct, and you need to either pull it out of pg_stat_gssapi, or enable log_connections and piece the log line together with later log entries; - for LDAP, the bind DN is discarded entirely; - for TLS client certs, the DN has to be pulled from pg_stat_ssl or the sslinfo extension (and it's truncated to 64 characters, so good luck if you have a particularly verbose PKI tree); - for peer auth, the username of the peereid is discarded; - etc. = Proposal = I propose that every auth method should store the string it uses to identify a user -- what I'll call an "authenticated identity" -- into one central location in Port, after authentication succeeds but before any pg_ident authorization occurs. This field can then be exposed in log_line_prefix. (It could additionally be exposed through a catalog table or SQL function, if that were deemed useful.) This would let a DBA more easily audit user activity when using more complicated pg_ident setups. Attached is a proof of concept that implements this for a handful of auth methods: - ldap uses the final bind DN as its authenticated identity - gss uses the user principal - cert uses the client's Subject DN - scram-sha-256 just uses the Postgres username With this patch, the authenticated identity can be inserted into log_line_prefix using the placeholder %Z. = Implementation Notes = - Client certificates can be combined with other authentication methods using the clientcert option, but that doesn't provide an authenticated identity in my proposal. *Only* the cert auth method populates the authenticated identity from a client certificate. This keeps the patch from having to deal with two simultaneous identity sources. - The trust auth method has an authenticated identity of NULL, logged as [unknown]. I kept this property even when clientcert=verify-full is in use (which would otherwise be identical to the cert auth method), to hammer home that 1) trust is not an authentication method and 2) the clientcert option does not provide an authenticated identity. Whether this is a useful property, or just overly pedantic, is probably something that could be debated. - The cert method's Subject DN string formatting needs the same considerations that are currently under discussion in Andrew's DN patch [1]. - I'm not crazy about the testing method -- it leads to a lot of log file proliferation in the tests -- but I wanted to make sure that we had test coverage for the log lines themselves. The ability to correctly audit user behavior depends on us logging the correct identity after authentication, but not a moment before. Would this be generally useful for those of you using pg_ident in production? Have I missed something that already provides this functionality? Thanks, --Jacob [1] https://www.postgresql.org/message-id/flat/92e70110-9273-d93c-5913-0bccb6562740@dunslane.net
Attachment
pgsql-hackers by date: