From fbc6bb367796a30bf857cbc4ef9b9097fa4d97e2 Mon Sep 17 00:00:00 2001
From: Gabriele Bartolini <gabriele.bartolini@enterprisedb.com>
Date: Fri, 8 Sep 2023 20:25:36 +0200
Subject: [PATCH] Add `enable_alter_system` GUC

Introduce the `enable_alter_system` GUC (by default set to `true`)
to be configured as an option at startup of the postmaster.

Signed-off-by: Gabriele Bartolini <gabriele.bartolini@enterprisedb.com>
---
 doc/src/sgml/ref/alter_system.sgml  |  6 ++++++
 doc/src/sgml/ref/pg_ctl-ref.sgml    |  9 +++++++++
 src/backend/utils/misc/guc.c        |  8 ++++++++
 src/backend/utils/misc/guc_tables.c | 10 ++++++++++
 src/include/utils/guc_tables.h      |  3 +++
 5 files changed, 36 insertions(+)

diff --git a/doc/src/sgml/ref/alter_system.sgml b/doc/src/sgml/ref/alter_system.sgml
index bea5714ba1..3e727d08da 100644
--- a/doc/src/sgml/ref/alter_system.sgml
+++ b/doc/src/sgml/ref/alter_system.sgml
@@ -111,6 +111,12 @@ ALTER SYSTEM RESET ALL
   <para>
    See <xref linkend="config-setting"/> for other ways to set the parameters.
   </para>
+
+  <para>
+   <literal>ALTER SYSTEM</literal> can be disabled at startup by passing
+   <literal>enable_alter_system=off</literal> to the <command>postgres</command>
+   command.
+  </para>
  </refsect1>
 
  <refsect1>
diff --git a/doc/src/sgml/ref/pg_ctl-ref.sgml b/doc/src/sgml/ref/pg_ctl-ref.sgml
index 46906966eb..f6d573084f 100644
--- a/doc/src/sgml/ref/pg_ctl-ref.sgml
+++ b/doc/src/sgml/ref/pg_ctl-ref.sgml
@@ -645,6 +645,15 @@ PostgreSQL documentation
 <screen>
 <prompt>$</prompt> <userinput>pg_ctl -o "-F -p 5433" start</userinput>
 </screen></para>
+
+   <para>
+    To start the server and disable <command>ALTER SYSTEM</command>,
+    waiting until the server is accepting connections:
+<screen>
+<prompt>$</prompt> <userinput>pg_ctl start -o "-c enable_alter_system=off"</userinput>
+</screen>
+   </para>
+
   </refsect2>
 
   <refsect2 id="r2-app-pgctl-4">
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 8f65ef3d89..e1cd6f6f57 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -4544,6 +4544,14 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
 	 */
 	name = altersysstmt->setstmt->name;
 
+	if (! EnableAlterSystem)
+	{
+
+		ereport(ERROR,
+			(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				errmsg("permission denied to run ALTER SYSTEM")));
+	}
+
 	switch (altersysstmt->setstmt->kind)
 	{
 		case VAR_SET_VALUE:
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 7fe58518d7..2710b7d8e0 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -492,6 +492,7 @@ extern const struct config_enum_entry dynamic_shared_memory_options[];
 /*
  * GUC option variables that are exported from this module
  */
+bool		EnableAlterSystem = true;
 bool		log_duration = false;
 bool		Debug_print_plan = false;
 bool		Debug_print_parse = false;
@@ -1085,6 +1086,15 @@ struct config_bool ConfigureNamesBool[] =
 		false,
 		NULL, NULL, NULL
 	},
+	{
+		{"enable_alter_system", PGC_POSTMASTER, UNGROUPED,
+			gettext_noop("Enable ALTER SYSTEM command"),
+			NULL
+		},
+		&EnableAlterSystem,
+		true,
+		NULL, NULL, NULL
+	},
 	{
 		{"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Enables advertising the server via Bonjour."),
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
index 0a2e274ebb..b20eb58fd6 100644
--- a/src/include/utils/guc_tables.h
+++ b/src/include/utils/guc_tables.h
@@ -320,4 +320,7 @@ extern char *config_enum_get_options(struct config_enum *record,
 									 const char *suffix,
 									 const char *separator);
 
+/* GUC reference to enable/disable alter system */
+extern PGDLLIMPORT bool EnableAlterSystem;
+
 #endif							/* GUC_TABLES_H */
-- 
2.43.0

