diff --git a/pkg/docker/gunicorn_config.py b/pkg/docker/gunicorn_config.py index ac7afe08175..dbe591cb8b0 100644 --- a/pkg/docker/gunicorn_config.py +++ b/pkg/docker/gunicorn_config.py @@ -5,6 +5,14 @@ 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, diff --git a/web/config.py b/web/config.py index c8ab16233bb..29b3d028e03 100644 --- a/web/config.py +++ b/web/config.py @@ -301,6 +301,9 @@ 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 ########################################################################## diff --git a/web/pgadmin/__init__.py b/web/pgadmin/__init__.py index 171f02ed53f..1474445571b 100644 --- a/web/pgadmin/__init__.py +++ b/web/pgadmin/__init__.py @@ -863,6 +863,15 @@ def before_request(): @app.after_request def after_request(response): + if config.LOG_AUTHENTICATED_USER: + if current_user.is_authenticated and current_user.username: + # Encode as latin-1 to avoid gunicorn 500s for unicode names + safe = current_user.username.encode( + 'latin-1', 'replace').decode('latin-1') + 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 \