From 5acd643aff5a12b8ee2ca3365532f5773c1b02a8 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Mon, 26 Apr 2021 11:25:17 +0900
Subject: [PATCH v1] Add authenticated data to pg_stat_activity

---
 src/include/catalog/pg_proc.dat               |  6 +--
 src/include/utils/backend_status.h            | 16 ++++---
 src/backend/catalog/system_views.sql          |  1 +
 src/backend/utils/activity/backend_status.c   | 45 +++++++++++++------
 src/backend/utils/adt/pgstatfuncs.c           | 21 +++++++--
 src/backend/utils/misc/guc.c                  | 11 +++++
 src/backend/utils/misc/postgresql.conf.sample |  1 +
 src/test/ldap/t/001_auth.pl                   |  4 +-
 src/test/regress/expected/rules.out           |  9 ++--
 src/test/ssl/t/001_ssltests.pl                |  8 ++--
 doc/src/sgml/config.sgml                      | 18 ++++++++
 doc/src/sgml/monitoring.sgml                  | 10 +++++
 12 files changed, 117 insertions(+), 33 deletions(-)

diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index db1abc149c..7217e017a2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5279,9 +5279,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,text}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,authenticated_id}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 0cbcc9c943..d2381f07dd 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -145,13 +145,16 @@ typedef struct PgBackendStatus
 	char	   *st_appname;
 
 	/*
-	 * Current command string; MUST be null-terminated. Note that this string
-	 * possibly is truncated in the middle of a multi-byte character. As
-	 * activity strings are stored more frequently than read, that allows to
-	 * move the cost of correct truncation to the display side. Use
-	 * pgstat_clip_activity() to truncate correctly.
+	 * Current command string and authenticated ID string; MUST be
+	 * null-terminated.  Note that those strings possibly are truncated in
+	 * the middle of a multi-byte character.  As activity strings are
+	 * stored more frequently than read, that allows to move the cost of
+	 * correct truncation to the display side.  Authenticated ID strings
+	 * are stored once at backend startup but the cost is minimal.
+	 * Use pgstat_clip_string() to truncate both of them correctly.
 	 */
 	char	   *st_activity_raw;
+	char	   *st_authn_id;
 
 	/*
 	 * Command progress reporting.  Any command which wishes can advertise
@@ -267,6 +270,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int pgstat_track_activity_authn_size;
 
 
 /* ----------
@@ -315,7 +319,7 @@ extern uint64 pgstat_get_my_query_id(void);
 extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
-extern char *pgstat_clip_activity(const char *raw_activity);
+extern char *pgstat_clip_string(const char *raw_activity, int max_size);
 
 
 #endif /* BACKEND_STATUS_H */
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 70e578894f..ef251daf17 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -821,6 +821,7 @@ CREATE VIEW pg_stat_activity AS
             S.usesysid,
             U.rolname AS usename,
             S.application_name,
+            S.authenticated_id,
             S.client_addr,
             S.client_hostname,
             S.client_port,
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index a368101103..a0f5fc98fd 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -44,6 +44,7 @@
  */
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
+int			pgstat_track_activity_authn_size = 128;
 
 
 /* exposed so that progress.c can access it */
@@ -95,7 +96,9 @@ BackendStatusShmemSize(void)
 					mul_size(NAMEDATALEN, NumBackendStatSlots));
 	/* BackendActivityBuffer: */
 	size = add_size(size,
-					mul_size(pgstat_track_activity_query_size, NumBackendStatSlots));
+					mul_size(pgstat_track_activity_query_size +
+							 pgstat_track_activity_authn_size,
+							 NumBackendStatSlots));
 #ifdef USE_SSL
 	/* BackendSslStatusBuffer: */
 	size = add_size(size,
@@ -171,7 +174,8 @@ CreateSharedBackendStatus(void)
 	}
 
 	/* Create or attach to the shared activity buffer */
-	BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size,
+	BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size +
+										 pgstat_track_activity_authn_size,
 										 NumBackendStatSlots);
 	BackendActivityBuffer = (char *)
 		ShmemInitStruct("Backend Activity Buffer",
@@ -182,12 +186,14 @@ CreateSharedBackendStatus(void)
 	{
 		MemSet(BackendActivityBuffer, 0, BackendActivityBufferSize);
 
-		/* Initialize st_activity pointers. */
+		/* Initialize st_activity and st_authn_id pointers. */
 		buffer = BackendActivityBuffer;
 		for (i = 0; i < NumBackendStatSlots; i++)
 		{
 			BackendStatusArray[i].st_activity_raw = buffer;
 			buffer += pgstat_track_activity_query_size;
+			BackendStatusArray[i].st_authn_id = buffer;
+			buffer += pgstat_track_activity_authn_size;
 		}
 	}
 
@@ -432,10 +438,22 @@ pgstat_bestart(void)
 	else
 		lbeentry.st_clienthostname[0] = '\0';
 	lbeentry.st_activity_raw[0] = '\0';
+	if (MyProcPort && MyProcPort->authn_id)
+	{
+		/* Compute the length of the field to store */
+		int		len = Min(strlen(MyProcPort->authn_id),
+						  pgstat_track_activity_authn_size - 1);
+
+		memcpy(lbeentry.st_authn_id, MyProcPort->authn_id, len);
+		lbeentry.st_authn_id[len] = '\0';
+	}
+	else
+		lbeentry.st_authn_id[0] = '\0';
 	/* Also make sure the last byte in each string area is always 0 */
 	lbeentry.st_appname[NAMEDATALEN - 1] = '\0';
 	lbeentry.st_clienthostname[NAMEDATALEN - 1] = '\0';
 	lbeentry.st_activity_raw[pgstat_track_activity_query_size - 1] = '\0';
+	lbeentry.st_authn_id[pgstat_track_activity_authn_size - 1] = '\0';
 
 #ifdef USE_SSL
 	memcpy(lbeentry.st_sslstatus, &lsslstatus, sizeof(PgBackendSSLStatus));
@@ -936,7 +954,8 @@ pgstat_get_backend_current_activity(int pid, bool checkUser)
 			else
 			{
 				/* this'll leak a bit of memory, but that seems acceptable */
-				return pgstat_clip_activity(beentry->st_activity_raw);
+				return pgstat_clip_string(beentry->st_activity_raw,
+										  pgstat_track_activity_query_size);
 			}
 		}
 
@@ -1102,7 +1121,7 @@ pgstat_fetch_stat_numbackends(void)
 }
 
 /*
- * Convert a potentially unsafely truncated activity string (see
+ * Convert a potentially unsafely truncated activity or authn ID string (see
  * PgBackendStatus.st_activity_raw's documentation) into a correctly truncated
  * one.
  *
@@ -1110,9 +1129,9 @@ pgstat_fetch_stat_numbackends(void)
  * freed.
  */
 char *
-pgstat_clip_activity(const char *raw_activity)
+pgstat_clip_string(const char *raw_string, int max_size)
 {
-	char	   *activity;
+	char	   *string;
 	int			rawlen;
 	int			cliplen;
 
@@ -1124,10 +1143,10 @@ pgstat_clip_activity(const char *raw_activity)
 	 * underlying buffer is guaranteed to be pgstat_track_activity_query_size
 	 * large.
 	 */
-	activity = pnstrdup(raw_activity, pgstat_track_activity_query_size - 1);
+	string = pnstrdup(raw_string, max_size - 1);
 
 	/* now double-guaranteed to be NUL terminated */
-	rawlen = strlen(activity);
+	rawlen = strlen(string);
 
 	/*
 	 * All supported server-encodings make it possible to determine the length
@@ -1137,10 +1156,10 @@ pgstat_clip_activity(const char *raw_activity)
 	 * even if the string earlier was truncated in the middle of a multi-byte
 	 * character.
 	 */
-	cliplen = pg_mbcliplen(activity, rawlen,
-						   pgstat_track_activity_query_size - 1);
+	cliplen = pg_mbcliplen(string, rawlen,
+						   max_size - 1);
 
-	activity[cliplen] = '\0';
+	string[cliplen] = '\0';
 
-	return activity;
+	return string;
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 87f02d572e..e4215c46c4 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -569,7 +569,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -703,10 +703,23 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 					break;
 			}
 
-			clipped_activity = pgstat_clip_activity(beentry->st_activity_raw);
+			clipped_activity = pgstat_clip_string(beentry->st_activity_raw,
+												  pgstat_track_activity_query_size);
 			values[5] = CStringGetTextDatum(clipped_activity);
 			pfree(clipped_activity);
 
+			if (beentry->st_authn_id)
+			{
+				char	   *clipped_authn_id;
+
+				clipped_authn_id = pgstat_clip_string(beentry->st_authn_id,
+													  pgstat_track_activity_authn_size);
+				values[30] = CStringGetTextDatum(clipped_authn_id);
+				pfree(clipped_authn_id);
+			}
+			else
+				nulls[30] = true;
+
 			/* leader_pid */
 			nulls[28] = true;
 
@@ -946,6 +959,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 			nulls[27] = true;
 			nulls[28] = true;
 			nulls[29] = true;
+			nulls[30] = true;
 		}
 
 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
@@ -1026,7 +1040,8 @@ pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
 	else
 		activity = beentry->st_activity_raw;
 
-	clipped_activity = pgstat_clip_activity(activity);
+	clipped_activity = pgstat_clip_string(activity,
+										  pgstat_track_activity_query_size);
 	ret = cstring_to_text(activity);
 	pfree(clipped_activity);
 
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index b130874bdc..def2c21fb8 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3516,6 +3516,17 @@ static struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"track_activity_authn_size", PGC_POSTMASTER, RESOURCES_MEM,
+			gettext_noop("Sets the size reserved for pg_stat_activity.authenticated_id, in bytes."),
+			NULL,
+			GUC_UNIT_BYTE
+		},
+		&pgstat_track_activity_authn_size,
+		128, 100, 1048576,
+		NULL, NULL, NULL
+	},
+
 	{
 		{"gin_pending_list_limit", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the maximum size of the pending list for GIN index."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 0f7f49b949..762a9d67c4 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -602,6 +602,7 @@
 #track_wal_io_timing = off
 #track_functions = none			# none, pl, all
 #track_activity_query_size = 1024	# (change requires restart)
+#track_activity_authn_size = 128	# (change requires restart)
 #stats_temp_directory = 'pg_stat_tmp'
 
 
diff --git a/src/test/ldap/t/001_auth.pl b/src/test/ldap/t/001_auth.pl
index ec4721234b..17edc33776 100644
--- a/src/test/ldap/t/001_auth.pl
+++ b/src/test/ldap/t/001_auth.pl
@@ -6,7 +6,7 @@ use Test::More;
 
 if ($ENV{with_ldap} eq 'yes')
 {
-	plan tests => 28;
+	plan tests => 29;
 }
 else
 {
@@ -199,6 +199,8 @@ $ENV{"PGPASSWORD"} = 'secret1';
 test_access(
 	$node, 'test1', 0,
 	'simple bind authentication succeeds',
+	sql => 'SELECT authenticated_id FROM pg_stat_activity WHERE pid = pg_backend_pid()',
+	expected_stdout => qr/uid=test1,dc=example,dc=net/,
 	log_like => [
 		qr/connection authenticated: identity="uid=test1,dc=example,dc=net" method=ldap/
 	],);
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 6dff5439e0..0a5ae0bc35 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1750,6 +1750,7 @@ pg_stat_activity| SELECT s.datid,
     s.usesysid,
     u.rolname AS usename,
     s.application_name,
+    s.authenticated_id,
     s.client_addr,
     s.client_hostname,
     s.client_port,
@@ -1765,7 +1766,7 @@ pg_stat_activity| SELECT s.datid,
     s.query_id,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, authenticated_id)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1877,7 +1878,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, authenticated_id)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_prefetch_recovery| SELECT s.stats_reset,
     s.prefetch,
@@ -2058,7 +2059,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, authenticated_id)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2090,7 +2091,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, authenticated_id)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl
index cc797a5c98..9a6dec7c26 100644
--- a/src/test/ssl/t/001_ssltests.pl
+++ b/src/test/ssl/t/001_ssltests.pl
@@ -17,7 +17,7 @@ if ($ENV{with_ssl} ne 'openssl')
 }
 else
 {
-	plan tests => 110;
+	plan tests => 111;
 }
 
 #### Some configuration
@@ -256,7 +256,6 @@ $node->connect_ok(
 	"host name matching with X.509 Subject Alternative Names 2");
 $node->connect_ok("$common_connstr host=foo.wildcard.pg-ssltest.test",
 	"host name matching with X.509 Subject Alternative Names wildcard");
-
 $node->connect_fails(
 	"$common_connstr host=wronghost.alt-name.pg-ssltest.test",
 	"host name not matching with X.509 Subject Alternative Names",
@@ -446,10 +445,13 @@ $node->connect_ok(
 # same thing but using explicit CN
 $dn_connstr = "$common_connstr dbname=certdb_cn";
 
+# The full DN should still be used as the authenticated identity, within the
+# backend logs and pg_stat_activity.
 $node->connect_ok(
 	"$dn_connstr user=ssltestuser sslcert=ssl/client-dn.crt sslkey=ssl/client-dn_tmp.key",
 	"certificate authorization succeeds with CN mapping",
-	# the full DN should still be used as the authenticated identity
+	sql => 'SELECT authenticated_id FROM pg_stat_activity WHERE pid = pg_backend_pid()',
+	expected_stdout => qr/CN=ssltestuser-dn,OU=Testing,OU=Engineering,O=PGDG/,
 	log_like => [
 		qr/connection authenticated: identity="CN=ssltestuser-dn,OU=Testing,OU=Engineering,O=PGDG" method=cert/
 	],);
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index cf75d913ce..51d040ea9c 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -7596,6 +7596,24 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-track-activity-authn-size" xreflabel="track_activity_authn_size">
+      <term><varname>track_activity_authn_size</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>track_activity_authn_size</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+       Specifies the amount of memory reserved to store the text of the
+       currently executing command for each active session, for the
+       <structname>pg_stat_activity</structname>.<structfield>authenticated_id</structfield> field.
+       If this value is specified without units, it is taken as bytes.
+       The default value is 128 bytes.
+       This parameter can only be set at server start.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-track-counts" xreflabel="track_counts">
       <term><varname>track_counts</varname> (<type>boolean</type>)
       <indexterm>
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 886e626be8..dda95cd860 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -756,6 +756,16 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
       </para></entry>
      </row>
 
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>authenticated_id</structfield> <type>text</type>
+      </para>
+      <para>
+       Name of the authenticated ID used for this backend login at
+       authentication
+      </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>client_addr</structfield> <type>inet</type>
-- 
2.31.1

