mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2026-08-17 16:34:44 -05:00
feat: include authenticated user identity in HTTP access log (#9991)
Set an X-Remote-User response header containing the authenticated username
on every request when the LOG_AUTHENTICATED_USER config option is enabled
(disabled by default). This allows the HTTP access log to be configured to
include user identity via standard log format directives
(%({x-remote-user}o)s in gunicorn, %{X-Remote-User}o in Apache) without
requiring any changes to pgAdmin's session or authentication behaviour. The
default gunicorn access log format is updated to surface the header.
The username is sanitised to a header-safe value: it is transliterated to
Latin-1 (HTTP headers are Latin-1 only) and any non-printable characters,
including CR/LF, are stripped, so unusual usernames cannot cause a 500 on
every response.
This commit is contained in:
committed by
Dave Page
parent
888a053231
commit
0c6740f146
@@ -5,6 +5,14 @@ from config import JSON_LOGGER, CONSOLE_LOG_LEVEL, CONSOLE_LOG_FORMAT_JSON
|
||||
|
||||
gunicorn.SERVER_SOFTWARE = "Python"
|
||||
|
||||
# Include the authenticated user identity in the access log.
|
||||
# %({x-remote-user}o)s reads the X-Remote-User response header set by pgAdmin
|
||||
# for authenticated requests; unauthenticated requests log '-'.
|
||||
access_log_format = (
|
||||
'%(h)s %(l)s %({x-remote-user}o)s %(t)s "%(r)s" %(s)s %(b)s '
|
||||
'"%(f)s" "%(a)s"'
|
||||
)
|
||||
|
||||
if JSON_LOGGER:
|
||||
logconfig_dict = {
|
||||
"version": 1,
|
||||
|
||||
@@ -301,6 +301,9 @@ else:
|
||||
LOG_ROTATION_SIZE = 10 # In MBs
|
||||
LOG_ROTATION_AGE = 1440 # In minutes
|
||||
LOG_ROTATION_MAX_LOG_FILES = 90 # Maximum number of backups to retain
|
||||
# Include the authenticated username in the X-Remote-User response header so
|
||||
# it can be captured in the HTTP access log. Disabled by default.
|
||||
LOG_AUTHENTICATED_USER = False
|
||||
##########################################################################
|
||||
# Server Connection Driver Settings
|
||||
##########################################################################
|
||||
|
||||
@@ -873,6 +873,20 @@ def create_app(app_name=None):
|
||||
|
||||
@app.after_request
|
||||
def after_request(response):
|
||||
if config.LOG_AUTHENTICATED_USER:
|
||||
if current_user.is_authenticated and current_user.username:
|
||||
# HTTP headers are latin-1 only, so transliterate anything
|
||||
# outside that range to avoid gunicorn 500s for unicode names.
|
||||
safe = current_user.username.encode(
|
||||
'latin-1', 'replace').decode('latin-1')
|
||||
# CR/LF and other control chars are valid latin-1 but Werkzeug
|
||||
# rejects them in header values (would 500 every request for
|
||||
# that user), so drop any non-printable characters too.
|
||||
safe = ''.join(c for c in safe if c.isprintable())
|
||||
response.headers['X-Remote-User'] = safe
|
||||
else:
|
||||
response.headers.pop('X-Remote-User', None)
|
||||
|
||||
if 'key' in request.args:
|
||||
domain = dict()
|
||||
if config.COOKIE_DEFAULT_DOMAIN and \
|
||||
|
||||
Reference in New Issue
Block a user