Add allow_alter_system GUC.
authorRobert Haas <[email protected]>
Fri, 29 Mar 2024 12:44:45 +0000 (08:44 -0400)
committerRobert Haas <[email protected]>
Fri, 29 Mar 2024 12:45:11 +0000 (08:45 -0400)
This is marked PGC_SIGHUP, so it can only be set in a configuration
file, not anywhere else; and it is also marked GUC_DISALLOW_IN_AUTO_FILE,
so it can't be set using ALTER SYSTEM. When set to false, the
ALTER SYSTEM command is disallowed.

There was considerable concern that this would be misinterpreted as
a security feature, which it is not, because a determined superuser
has various ways of bypassing it. Hence, a lot of work has gone into
wordsmithing the documentation, in the hopes of avoiding any such
confusion.

Jelte Fennemia-Nio and Gabriele Bartolini, with wording suggestions
for the documentation from many others.

Discussion: http://postgr.es/m/CA%2BVUV5rEKt2%2BCdC_KUaPoihMu%2Bi5ChT4WVNTr4CD5-xXZUfuQw%40mail.gmail.com

doc/src/sgml/config.sgml
doc/src/sgml/ref/alter_system.sgml
src/backend/utils/misc/guc.c
src/backend/utils/misc/guc_tables.c
src/backend/utils/misc/postgresql.conf.sample
src/include/utils/guc.h

index 5468637e2ef3dbcca5cfaf539c881714f707f0e0..f65c17e5ae4891ef575604ac4d5937708c98a910 100644 (file)
@@ -199,7 +199,8 @@ shared_buffers = 128MB
     <para>
      External tools may also
      modify <filename>postgresql.auto.conf</filename>.  It is not
-     recommended to do this while the server is running, since a
+     recommended to do this while the server is running unless <xref
+     linkend="guc-allow-alter-system"/> is set to <literal>off</literal>, since a
      concurrent <command>ALTER SYSTEM</command> command could overwrite
      such changes.  Such tools might simply append new settings to the end,
      or they might choose to remove duplicate settings and/or comments
@@ -10767,6 +10768,54 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-allow-alter-system" xreflabel="allow_alter_system">
+      <term><varname>allow_alter_system</varname> (<type>boolean</type>)
+      <indexterm>
+       <primary><varname>allow_alter_system</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        When <literal>allow_alter_system</literal> is set to
+        <literal>off</literal>, an error is returned if the <command>ALTER
+        SYSTEM</command> command is executed. This parameter can only be set in
+        the <filename>postgresql.conf</filename> file or on the server command
+        line. The default value is <literal>on</literal>.
+       </para>
+
+       <para>
+        Note that this setting must not be regarded as a security feature. It
+        only disables the <literal>ALTER SYSTEM</literal> command. It does not
+        prevent a superuser from changing the configuration using other SQL
+        commands. A superuser has many ways of executing shell commands at
+        the operating system level, and can therefore modify
+        <literal>postgresql.auto.conf</literal> regardless of the value of
+        this setting.
+       </para>
+
+       <para>
+        Turning this setting off is intended for environments where the
+        configuration of <productname>PostgreSQL</productname> is managed by
+        some external tool.
+        In such environments, a well intentioned superuser might
+        <emphasis>mistakenly</emphasis> use <command>ALTER SYSTEM</command>
+        to change the configuration instead of using the external tool.
+        This might result in unintended behavior, such as the external tool
+        overwriting the change at some later point in time when it updates the
+        configuration.
+        Setting this parameter to <literal>off</literal> can
+        help avoid such mistakes.
+       </para>
+
+       <para>
+        This parameter only controls the use of <command>ALTER SYSTEM</command>.
+        The settings stored in <filename>postgresql.auto.conf</filename>
+        take effect even if <literal>allow_alter_system</literal> is set to
+        <literal>off</literal>.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
     </sect2>
    </sect1>
index bea5714ba1aab8f85f9fcbead5d834586b4d01d5..1bde66d6ad2d31603b7b7fb2f26aecc4ad3139bc 100644 (file)
@@ -104,6 +104,7 @@ ALTER SYSTEM RESET ALL
 
   <para>
    This command can't be used to set <xref linkend="guc-data-directory"/>,
+   <xref linkend="guc-allow-alter-system"/>,
    nor parameters that are not allowed in <filename>postgresql.conf</filename>
    (e.g., <link linkend="runtime-config-preset">preset options</link>).
   </para>
@@ -111,6 +112,13 @@ 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 by setting
+   <xref linkend="guc-allow-alter-system"/> to <literal>off</literal>, but this
+   is not a security mechanism (as explained in detail in the documentation for
+   this parameter).
+  </para>
  </refsect1>
 
  <refsect1>
index 391866145eefae341346ed3aad1d5c7c4fb5314e..f51b3e0b507ec00a8f8e2bb3bd146eb3316994c0 100644 (file)
@@ -4563,6 +4563,11 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
     */
    name = altersysstmt->setstmt->name;
 
+   if (!AllowAlterSystem)
+       ereport(ERROR,
+               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                errmsg("ALTER SYSTEM is not allowed in this environment")));
+
    switch (altersysstmt->setstmt->kind)
    {
        case VAR_SET_VALUE:
index abd9029451fe70c6fa7bf4e8f69c31b966849018..92fcd5fa4d50a92b04069f19525263d1bc847e6f 100644 (file)
@@ -494,6 +494,7 @@ extern const struct config_enum_entry dynamic_shared_memory_options[];
 /*
  * GUC option variables that are exported from this module
  */
+bool       AllowAlterSystem = true;
 bool       log_duration = false;
 bool       Debug_print_plan = false;
 bool       Debug_print_parse = false;
@@ -1040,6 +1041,22 @@ struct config_bool ConfigureNamesBool[] =
        false,
        NULL, NULL, NULL
    },
+   {
+       /*
+        * This setting itself cannot be set by ALTER SYSTEM to avoid an
+        * operator turning this setting off by using ALTER SYSTEM, without a
+        * way to turn it back on.
+        */
+       {"allow_alter_system", PGC_SIGHUP, COMPAT_OPTIONS_OTHER,
+           gettext_noop("Allows running the ALTER SYSTEM command."),
+           gettext_noop("Can be set to off for environments where global configuration "
+                        "changes should be made using a different method."),
+           GUC_DISALLOW_IN_AUTO_FILE
+       },
+       &AllowAlterSystem,
+       true,
+       NULL, NULL, NULL
+   },
    {
        {"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
            gettext_noop("Enables advertising the server via Bonjour."),
index 2244ee52f79ae68453862e9ea133412f68e69347..adcc0257f9153c6f317d8dadd3ee56b7c95a974f 100644 (file)
 # - Other Platforms and Clients -
 
 #transform_null_equals = off
+#allow_alter_system = on
 
 
 #------------------------------------------------------------------------------
index 3712aba09b0451b0a972efb39c614f012174ad35..8d1fe04078a49b842bf2267f0236ea845c74842f 100644 (file)
@@ -254,6 +254,7 @@ extern PGDLLIMPORT bool log_btree_build_stats;
 extern PGDLLIMPORT bool check_function_bodies;
 extern PGDLLIMPORT bool current_role_is_superuser;
 
+extern PGDLLIMPORT bool AllowAlterSystem;
 extern PGDLLIMPORT bool log_duration;
 extern PGDLLIMPORT int log_parameter_max_length;
 extern PGDLLIMPORT int log_parameter_max_length_on_error;