On Fri, Jan 17, 2020 at 08:47:49PM +0100, David Fetter wrote:
> On Wed, Jan 08, 2020 at 02:53:47AM +0000, tsunakawa.ta...@fujitsu.com wrote:
> > From: David Fetter <da...@fetter.org>
> > > > But I see two problems with the proposed approach: (1) initdb
> > > > doesn't support setting up SSL, so the only thing you can achieve
> > > > here is to reject all TCP/IP connections, until you have set up SSL.
> > > 
> > > I don't believe any special setup is needed to require TLS for the
> > > connection, which is what this patch handles in a straightforward way.
> > 
> > I think this feature can be useful because it's common to reject remote 
> > non-TLS connections.  Eliminating the need to script for pg_hba.conf is 
> > welcome.  Setting GUC parameters just after initdb is relatively easy, 
> > because we can simply add lines at the end of postgresql.conf.  But 
> > pg_hba.conf is not because the first matching entry is effective.
> > 
> > In terms of rejecting non-secure remote connections, should 
> > hostgssenc/hostnogssenc also be handled similarly?
> 
> Yes, and they are in the enclosed patch.
> 
> > > > (2) The default pg_hba.conf only covers localhost connections.
> > > 
> > > As of this patch, it can be asked to cover all connections.
> > 
> > +      <term><option>--auth-hostssl=<replaceable 
> > class="parameter">authmethod</replaceable></option></term>
> > +      <listitem>
> > +       <para>
> > +        This option specifies the authentication method for users via
> > fg
> > +        TLS connections used in <filename>pg_hba.conf</filename>
> > +        (<literal>hostssl</literal> lines).
> > +       </para>
> >     +      </listitem>
> > 
> > The relationship between --auth/--auth-local/--auth-host and 
> > --auth-hostssl/--auth-hostnossl is confusing.  The former is for local 
> > connections, and the latter is for remote ones.  Can we just add "remote" 
> > in the above documentation?
> 
> Done.
> 
> > Plus, you're adding the first option to initdb that handles remote 
> > connections.  As the following execution shows, it doesn't warn about using 
> > "trust" for remote connections.
> > 
> > 
> > $ initdb --auth=md5 --pwprompt --auth-hostssl=trust --auth-hostnossl=trust
> > ...
> > syncing data to disk ... ok
> > 
> > Success. You can now start the database server using:
> > 
> >     pg_ctl -D /tuna/pg2 -l logfile start
> > 
> > 
> > 
> > I think we should emit a warning message like the following existing one:
> > 
> > --------------------------------------------------
> > initdb: warning: enabling "trust" authentication for local connections
> > You can change this by editing pg_hba.conf or using the option -A, or
> > --auth-local and --auth-host, the next time you run initdb.
> > -
> > initdb: warning: enabling "trust" authentication 
> 
> Done.
> 
> Best,
> David.

This time, with the patch attached.

Best,
David.
-- 
David Fetter <david(at)fetter(dot)org> http://fetter.org/
Phone: +1 415 235 3778

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
>From 9dbe5b8a0e4a452367d3e86792111c2950c7b379 Mon Sep 17 00:00:00 2001
From: David Fetter <david.fet...@onelogin.com>
Date: Wed, 11 Dec 2019 18:55:03 -0800
Subject: [PATCH v3] Enable setting pg_hba.conf permissions from initdb
To: hackers
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.24.1"

This is a multi-part message in MIME format.
--------------2.24.1
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit


The new optional arguments are --auth-hostssl, --auth-hostnossl,
--auth-hostgssenc, and --auth-hostnogssenc.

diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml
index da5c8f5307..4126880bcb 100644
--- a/doc/src/sgml/ref/initdb.sgml
+++ b/doc/src/sgml/ref/initdb.sgml
@@ -154,6 +154,50 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>--auth-hostssl=<replaceable class="parameter">authmethod</replaceable></option></term>
+      <listitem>
+       <para>
+        This option specifies the authentication method for users via
+        TLS remote connections used in <filename>pg_hba.conf</filename>
+        (<literal>hostssl</literal> lines).
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--auth-hostnossl=<replaceable class="parameter">authmethod</replaceable></option></term>
+      <listitem>
+       <para>
+        This option specifies the authentication method for users via
+        non-TLS remote connections used in <filename>pg_hba.conf</filename>
+        (<literal>hostnossl</literal> lines).
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--auth-hostgssenc=<replaceable class="parameter">authmethod</replaceable></option></term>
+      <listitem>
+       <para>
+        This option specifies the authentication method for users via
+        encrypted GSSAPI remote connections used in <filename>pg_hba.conf</filename>
+        (<literal>hostgssenc</literal> lines).
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--auth-hostnogssenc=<replaceable class="parameter">authmethod</replaceable></option></term>
+      <listitem>
+       <para>
+        This option specifies the authentication method for users via
+        remote connections not using encrypted GSSAPI in <filename>pg_hba.conf</filename>
+        (<literal>hostnogssenc</literal> lines).
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>--auth-local=<replaceable class="parameter">authmethod</replaceable></option></term>
       <listitem>
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index c853e36232..7d5189dd8f 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -87,3 +87,15 @@ host    all             all             ::1/128                 @authmethodhost@
 @remove-line-for-nolocal@local   replication     all                                     @authmethodlocal@
 host    replication     all             127.0.0.1/32            @authmethodhost@
 host    replication     all             ::1/128                 @authmethodhost@
+
+# hostnossl all           all             0.0.0.0/0               @authmethodhostnossl@
+# hostnossl all           all             ::/0                    @authmethodhostnossl@
+
+# hostssl all             all             0.0.0.0/0               @authmethodhostssl@
+# hostssl all             all             ::/0                    @authmethodhostssl@
+
+# hostnogssenc all           all             0.0.0.0/0               @authmethodhostnogssenc@
+# hostnogssenc all           all             ::/0                    @authmethodhostnogssenc@
+
+# hostgssenc all             all             0.0.0.0/0               @authmethodhostgssenc@
+# hostgssenc all             all             ::/0                    @authmethodhostgssenc@
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index ec6d0bdf8e..982b1ba0b8 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -136,6 +136,10 @@ static char *pwfilename = NULL;
 static char *superuser_password = NULL;
 static const char *authmethodhost = NULL;
 static const char *authmethodlocal = NULL;
+static const char *authmethodhostssl = NULL;
+static const char *authmethodhostnossl = NULL;
+static const char *authmethodhostgssenc = NULL;
+static const char *authmethodhostnogssenc = NULL;
 static bool debug = false;
 static bool noclean = false;
 static bool do_sync = true;
@@ -181,10 +185,12 @@ static const char *default_timezone = NULL;
  * Warning messages for authentication methods
  */
 #define AUTHTRUST_WARNING \
-"# CAUTION: Configuring the system for local \"trust\" authentication\n" \
-"# allows any local user to connect as any PostgreSQL user, including\n" \
-"# the database superuser.  If you do not trust all your local users,\n" \
-"# use another authentication method.\n"
+"# CAUTION: Configuring the system for \"trust\" authentication\n" \
+"# allows any user who can reach the databse on the route specified\n" \
+"# to connect as any PostgreSQL user, including the database\n" \
+"# superuser.  If you do not trust all the users who could\n" \
+"# reach the database on the route specified, use a more restrictive\n" \
+"# authentication method.\n"
 static bool authwarning = false;
 
 /*
@@ -438,7 +444,6 @@ replace_token(char **lines, const char *token, const char *replacement)
  *
  * a sort of poor man's grep -v
  */
-#ifndef HAVE_UNIX_SOCKETS
 static char **
 filter_lines_with_token(char **lines, const char *token)
 {
@@ -461,7 +466,6 @@ filter_lines_with_token(char **lines, const char *token)
 
 	return result;
 }
-#endif
 
 /*
  * get the lines from a text file
@@ -1322,9 +1326,97 @@ setup_config(void)
 							  "@authmethodlocal@",
 							  authmethodlocal);
 
+	authwarning = (
+			strcmp(authmethodlocal, "trust") == 0 ||
+			strcmp(authmethodhost, "trust") == 0 ||
+			(authmethodhostssl != NULL &&
+			 strcmp(authmethodhostssl, "trust") == 0) ||
+			(authmethodhostnossl != NULL &&
+			 strcmp(authmethodhostnossl, "trust") == 0) ||
+			(authmethodhostgssenc != NULL &&
+			 strcmp(authmethodhostgssenc, "trust") == 0) ||
+			(authmethodhostnogssenc != NULL &&
+			 strcmp(authmethodhostnogssenc, "trust")) == 0);
+
 	conflines = replace_token(conflines,
 							  "@authcomment@",
-							  (strcmp(authmethodlocal, "trust") == 0 || strcmp(authmethodhost, "trust") == 0) ? AUTHTRUST_WARNING : "");
+							   authwarning ? AUTHTRUST_WARNING : "");
+
+	if (authmethodhostssl != NULL)
+	{
+		conflines = replace_token(conflines,
+								  "# hostssl all             all             0.0.0.0/0               @authmethodhostssl@",
+								  "hostssl all             all             0.0.0.0/0               @authmethodhostssl@");
+#ifdef HAVE_IPV6
+		conflines = replace_token(conflines,
+								  "# hostssl all             all             ::/0                    @authmethodhostssl@",
+								  "hostssl all             all             ::/0                    @authmethodhostssl@");
+#endif
+		conflines = replace_token(conflines,
+								  "@authmethodhostssl@",
+								  authmethodhostssl);
+	}
+	else
+	{
+		conflines = filter_lines_with_token(conflines, "@authmethodhostssl@");
+	}
+
+	if (authmethodhostnossl != NULL)
+	{
+		conflines = replace_token(conflines,
+								  "# hostnossl all           all             0.0.0.0/0               @authmethodhostnossl@",
+								  "hostnossl all           all             0.0.0.0/0               @authmethodhostnossl@");
+#ifdef HAVE_IPV6
+		conflines = replace_token(conflines,
+								  "# hostnossl all           all             ::/0                    @authmethodhostnossl@",
+								  "hostnossl all           all             ::/0                    @authmethodhostnossl@");
+#endif
+		conflines = replace_token(conflines,
+								  "@authmethodhostnossl@",
+								  authmethodhostnossl);
+	}
+	else
+	{
+		conflines = filter_lines_with_token(conflines, "@authmethodhostnossl@");
+	}
+
+	if (authmethodhostgssenc != NULL)
+	{
+		conflines = replace_token(conflines,
+								  "# hostgssenc all             all             0.0.0.0/0               @authmethodhostgssenc@",
+								  "hostgssenc all             all             0.0.0.0/0               @authmethodhostgssenc@");
+#ifdef HAVE_IPV6
+		conflines = replace_token(conflines,
+								  "# hostgssenc all             all             ::/0                    @authmethodhostgssenc@",
+								  "hostgssenc all             all             ::/0                    @authmethodhostgssenc@");
+#endif
+		conflines = replace_token(conflines,
+								  "@authmethodhostgssenc@",
+								  authmethodhostgssenc);
+	}
+	else
+	{
+		conflines = filter_lines_with_token(conflines, "@authmethodhostgssenc@");
+	}
+
+	if (authmethodhostnogssenc != NULL)
+	{
+		conflines = replace_token(conflines,
+								  "# hostnogssenc all           all             0.0.0.0/0               @authmethodhostnogssenc@",
+								  "hostnogssenc all           all             0.0.0.0/0               @authmethodhostnogssenc@");
+#ifdef HAVE_IPV6
+		conflines = replace_token(conflines,
+								  "# hostnogssenc all           all             ::/0                    @authmethodhostnogssenc@",
+								  "hostnogssenc all           all             ::/0                    @authmethodhostnogssenc@");
+#endif
+		conflines = replace_token(conflines,
+								  "@authmethodhostnogssenc@",
+								  authmethodhostnogssenc);
+	}
+	else
+	{
+		conflines = filter_lines_with_token(conflines, "@authmethodhostnogssenc@");
+	}
 
 	snprintf(path, sizeof(path), "%s/pg_hba.conf", pg_data);
 
@@ -2327,36 +2419,40 @@ usage(const char *progname)
 	printf(_("Usage:\n"));
 	printf(_("  %s [OPTION]... [DATADIR]\n"), progname);
 	printf(_("\nOptions:\n"));
-	printf(_("  -A, --auth=METHOD         default authentication method for local connections\n"));
-	printf(_("      --auth-host=METHOD    default authentication method for local TCP/IP connections\n"));
-	printf(_("      --auth-local=METHOD   default authentication method for local-socket connections\n"));
-	printf(_(" [-D, --pgdata=]DATADIR     location for this database cluster\n"));
-	printf(_("  -E, --encoding=ENCODING   set default encoding for new databases\n"));
-	printf(_("  -g, --allow-group-access  allow group read/execute on data directory\n"));
-	printf(_("      --locale=LOCALE       set default locale for new databases\n"));
+	printf(_("  -A, --auth=METHOD              default authentication method for local connections\n"));
+	printf(_("      --auth-host=METHOD         default authentication method for local TCP/IP connections\n"));
+	printf(_("      --auth-local=METHOD        default authentication method for local-socket connections\n"));
+	printf(_("      --auth-hostssl=METHOD      default authentication method for TLS connections\n"));
+	printf(_("      --auth-hostnossl=METHOD    default authentication method for non-TLS connections\n"));
+	printf(_("      --auth-hostgssenc=METHOD   default authentication method for encrypted GSSAPI connections\n"));
+	printf(_("      --auth-hostnogssenc=METHOD default authentication method for connections not using encrypted GSSAPI\n"));
+	printf(_(" [-D, --pgdata=]DATADIR          location for this database cluster\n"));
+	printf(_("  -E, --encoding=ENCODING        set default encoding for new databases\n"));
+	printf(_("  -g, --allow-group-access       allow group read/execute on data directory\n"));
+	printf(_("      --locale=LOCALE            set default locale for new databases\n"));
 	printf(_("      --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n"
 			 "      --lc-monetary=, --lc-numeric=, --lc-time=LOCALE\n"
-			 "                            set default locale in the respective category for\n"
-			 "                            new databases (default taken from environment)\n"));
-	printf(_("      --no-locale           equivalent to --locale=C\n"));
-	printf(_("      --pwfile=FILE         read password for the new superuser from file\n"));
+			 "                                 set default locale in the respective category for\n"
+			 "                                 new databases (default taken from environment)\n"));
+	printf(_("      --no-locale                equivalent to --locale=C\n"));
+	printf(_("      --pwfile=FILE              read password for the new superuser from file\n"));
 	printf(_("  -T, --text-search-config=CFG\n"
-			 "                            default text search configuration\n"));
-	printf(_("  -U, --username=NAME       database superuser name\n"));
-	printf(_("  -W, --pwprompt            prompt for a password for the new superuser\n"));
-	printf(_("  -X, --waldir=WALDIR       location for the write-ahead log directory\n"));
-	printf(_("      --wal-segsize=SIZE    size of WAL segments, in megabytes\n"));
+			 "                                 default text search configuration\n"));
+	printf(_("  -U, --username=NAME            database superuser name\n"));
+	printf(_("  -W, --pwprompt                 prompt for a password for the new superuser\n"));
+	printf(_("  -X, --waldir=WALDIR            location for the write-ahead log directory\n"));
+	printf(_("      --wal-segsize=SIZE         size of WAL segments, in megabytes\n"));
 	printf(_("\nLess commonly used options:\n"));
-	printf(_("  -d, --debug               generate lots of debugging output\n"));
-	printf(_("  -k, --data-checksums      use data page checksums\n"));
-	printf(_("  -L DIRECTORY              where to find the input files\n"));
-	printf(_("  -n, --no-clean            do not clean up after errors\n"));
-	printf(_("  -N, --no-sync             do not wait for changes to be written safely to disk\n"));
-	printf(_("  -s, --show                show internal settings\n"));
-	printf(_("  -S, --sync-only           only sync data directory\n"));
+	printf(_("  -d, --debug                    generate lots of debugging output\n"));
+	printf(_("  -k, --data-checksums           use data page checksums\n"));
+	printf(_("  -L DIRECTORY                   where to find the input files\n"));
+	printf(_("  -n, --no-clean                 do not clean up after errors\n"));
+	printf(_("  -N, --no-sync                  do not wait for changes to be written safely to disk\n"));
+	printf(_("  -s, --show                     show internal settings\n"));
+	printf(_("  -S, --sync-only                only sync data directory\n"));
 	printf(_("\nOther options:\n"));
-	printf(_("  -V, --version             output version information, then exit\n"));
-	printf(_("  -?, --help                show this help, then exit\n"));
+	printf(_("  -V, --version                  output version information, then exit\n"));
+	printf(_("  -?, --help                     show this help, then exit\n"));
 	printf(_("\nIf the data directory is not specified, the environment variable PGDATA\n"
 			 "is used.\n"));
 	printf(_("\nReport bugs to <pgsql-b...@lists.postgresql.org>.\n"));
@@ -3010,6 +3106,10 @@ main(int argc, char *argv[])
 		{"auth", required_argument, NULL, 'A'},
 		{"auth-local", required_argument, NULL, 10},
 		{"auth-host", required_argument, NULL, 11},
+		{"auth-hostssl", required_argument, NULL, 13},
+		{"auth-hostnossl", required_argument, NULL, 14},
+		{"auth-hostgssenc", required_argument, NULL, 15},
+		{"auth-hostnogssenc", required_argument, NULL, 16},
 		{"pwprompt", no_argument, NULL, 'W'},
 		{"pwfile", required_argument, NULL, 9},
 		{"username", required_argument, NULL, 'U'},
@@ -3090,6 +3190,18 @@ main(int argc, char *argv[])
 			case 11:
 				authmethodhost = pg_strdup(optarg);
 				break;
+			case 13:
+				authmethodhostssl = pg_strdup(optarg);
+				break;
+			case 14:
+				authmethodhostnossl = pg_strdup(optarg);
+				break;
+			case 15:
+				authmethodhostgssenc = pg_strdup(optarg);
+				break;
+			case 16:
+				authmethodhostnogssenc = pg_strdup(optarg);
+				break;
 			case 'D':
 				pg_data = pg_strdup(optarg);
 				break;
@@ -3224,6 +3336,14 @@ main(int argc, char *argv[])
 
 	check_authmethod_valid(authmethodlocal, auth_methods_local, "local");
 	check_authmethod_valid(authmethodhost, auth_methods_host, "host");
+	if (authmethodhostssl != NULL)
+		check_authmethod_valid(authmethodhostssl, auth_methods_host, "hostssl");
+	if (authmethodhostnossl != NULL)
+		check_authmethod_valid(authmethodhostnossl, auth_methods_host, "hostnossl");
+	if (authmethodhostgssenc != NULL)
+		check_authmethod_valid(authmethodhostgssenc, auth_methods_host, "hostgssenc");
+	if (authmethodhostnogssenc != NULL)
+		check_authmethod_valid(authmethodhostnogssenc, auth_methods_host, "hostnogssenc");
 
 	check_need_password(authmethodlocal, authmethodhost);
 
@@ -3306,9 +3426,9 @@ main(int argc, char *argv[])
 	if (authwarning)
 	{
 		printf("\n");
-		pg_log_warning("enabling \"trust\" authentication for local connections");
+		pg_log_warning("enabling \"trust\" authentication");
 		fprintf(stderr, _("You can change this by editing pg_hba.conf or using the option -A, or\n"
-						  "--auth-local and --auth-host, the next time you run initdb.\n"));
+						  "the various options that start with --auth, the next time you run initdb.\n"));
 	}
 
 	/*

--------------2.24.1--


Reply via email to