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--