Update the createuser utility for the ROLEs world. Alvaro Herrera

This commit is contained in:
Tom Lane 2005-08-14 20:16:03 +00:00
parent e36de18191
commit 8ae0d476a9
2 changed files with 243 additions and 108 deletions

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/createuser.sgml,v 1.41 2005/05/29 03:32:18 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/createuser.sgml,v 1.42 2005/08/14 20:16:02 tgl Exp $
PostgreSQL documentation
-->
@ -32,24 +32,24 @@ PostgreSQL documentation
<title>Description</title>
<para>
<application>createuser</application> creates a
new <productname>PostgreSQL</productname> user.
Only superusers (users with <literal>usesuper</literal> set in
the <literal>pg_shadow</literal> table) can create
new <productname>PostgreSQL</productname> users,
so <application>createuser</application> must be
invoked by someone who can connect as a <productname>PostgreSQL</productname>
superuser.
new <productname>PostgreSQL</productname> user (or more precisely, a role).
Only superusers and users with <literal>CREATEROLE</> privilege can create
new users, so <application>createuser</application> must be
invoked by someone who can connect as a superuser or a user with
<literal>CREATEROLE</> privilege.
</para>
<para>
Being a superuser also implies the ability to bypass access permission
If you wish to create a new superuser, you must connect as a
superuser, not merely with <literal>CREATEROLE</> privilege.
Being a superuser implies the ability to bypass all access permission
checks within the database, so superuserdom should not be granted lightly.
</para>
<para>
<application>createuser</application> is a wrapper around the
<acronym>SQL</acronym> command <xref linkend="SQL-CREATEUSER"
endterm="SQL-CREATEUSER-title">.
<acronym>SQL</acronym> command <xref linkend="SQL-CREATEROLE"
endterm="SQL-CREATEROLE-title">.
There is no effective difference between creating users via
this utility and via other methods for accessing the server.
</para>
@ -70,32 +70,28 @@ PostgreSQL documentation
<para>
Specifies the name of the <productname>PostgreSQL</productname> user
to be created.
This name must be unique among all users of this
This name must be different from all existing roles in this
<productname>PostgreSQL</productname> installation.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-a</></term>
<term><option>--adduser</></term>
<term><option>-s</></term>
<term><option>--superuser</></term>
<listitem>
<para>
The new user is allowed to create other users.
(Note: Actually, this makes the new user a <emphasis>superuser</>.
The option is poorly named.)
The new user will be a superuser.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-A</></term>
<term><option>--no-adduser</></term>
<term><option>-S</></term>
<term><option>--no-superuser</></term>
<listitem>
<para>
The new user is not allowed to create other users (i.e.,
the new user is a regular user, not a superuser).
This is the default.
The new user will not be a superuser.
</para>
</listitem>
</varlistentry>
@ -105,7 +101,7 @@ PostgreSQL documentation
<term><option>--createdb</></term>
<listitem>
<para>
The new user is allowed to create databases.
The new user will be allowed to create databases.
</para>
</listitem>
</varlistentry>
@ -115,52 +111,86 @@ PostgreSQL documentation
<term><option>--no-createdb</></term>
<listitem>
<para>
The new user is not allowed to create databases.
This is the default.
The new user will not be allowed to create databases.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-e</></term>
<term><option>--echo</></term>
<term><option>-r</></term>
<term><option>--createrole</></term>
<listitem>
<para>
Echo the commands that <application>createuser</application> generates
and sends to the server.
The new user will be allowed to create new roles (that is,
this user will have <literal>CREATEROLE</> privilege).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-E</></term>
<term><option>--encrypted</></term>
<term><option>-R</></term>
<term><option>--no-createrole</></term>
<listitem>
<para>
Encrypts the user's password stored in the database. If not
specified, the default password behavior is used.
The new user will not be allowed to create new roles.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-i <replaceable class="parameter">number</replaceable></></term>
<term><option>--sysid <replaceable class="parameter">number</replaceable></></term>
<term><option>-l</></term>
<term><option>--login</></term>
<listitem>
<para>
Allows you to pick a non-default user ID for the new user. This is not
necessary, but some people like it.
The new user will be allowed to log in (that is, the user name
can be used as the initial session user identifier).
This is the default.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-N</></term>
<term><option>--unencrypted</></term>
<term><option>-L</></term>
<term><option>--no-login</></term>
<listitem>
<para>
Does not encrypt the user's password stored in the database. If
not specified, the default password behavior is used.
The new user will not be allowed to log in.
(A role without login privilege is still useful as a means of
managing database permissions.)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-i</></term>
<term><option>--inherit</></term>
<listitem>
<para>
The new role will automatically inherit privileges of roles
it is a member of.
This is the default.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-I</></term>
<term><option>--no-inherit</></term>
<listitem>
<para>
The new role will not automatically inherit privileges of roles
it is a member of.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-c <replaceable class="parameter">number</replaceable></></term>
<term><option>--conn-limit <replaceable class="parameter">number</replaceable></></term>
<listitem>
<para>
Set a maximum number of connections for the new user.
The default is to set no limit.
</para>
</listitem>
</varlistentry>
@ -177,6 +207,39 @@ PostgreSQL documentation
</listitem>
</varlistentry>
<varlistentry>
<term><option>-E</></term>
<term><option>--encrypted</></term>
<listitem>
<para>
Encrypts the user's password stored in the database. If not
specified, the default password behavior is used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-N</></term>
<term><option>--unencrypted</></term>
<listitem>
<para>
Does not encrypt the user's password stored in the database. If
not specified, the default password behavior is used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-e</></term>
<term><option>--echo</></term>
<listitem>
<para>
Echo the commands that <application>createuser</application> generates
and sends to the server.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-q</></term>
<term><option>--quiet</></term>
@ -204,10 +267,10 @@ PostgreSQL documentation
<term><option>--host <replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the
server
is running. If the value begins with a slash, it is used
as the directory for the Unix domain socket.
Specifies the host name of the machine on which the
server
is running. If the value begins with a slash, it is used
as the directory for the Unix domain socket.
</para>
</listitem>
</varlistentry>
@ -217,9 +280,9 @@ PostgreSQL documentation
<term><option>--port <replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or local Unix domain socket file
extension on which the server
is listening for connections.
Specifies the TCP port or local Unix domain socket file
extension on which the server
is listening for connections.
</para>
</listitem>
</varlistentry>
@ -272,8 +335,8 @@ PostgreSQL documentation
<title>Diagnostics</title>
<para>
In case of difficulty, see <xref linkend="SQL-CREATEUSER"
endterm="sql-createuser-title"> and <xref linkend="APP-PSQL"> for
In case of difficulty, see <xref linkend="SQL-CREATEROLE"
endterm="sql-createrole-title"> and <xref linkend="APP-PSQL"> for
discussions of potential problems and error messages.
The database server must be running at the
targeted host. Also, any default connection settings and environment
@ -292,8 +355,9 @@ PostgreSQL documentation
server:
<screen>
<prompt>$ </prompt><userinput>createuser joe</userinput>
<computeroutput>Shall the new user be allowed to create databases? (y/n) </computeroutput><userinput>n</userinput>
<computeroutput>Shall the new user be allowed to create more new users? (y/n) </computeroutput><userinput>n</userinput>
<computeroutput>Shall the new role be a superuser? (y/n) </computeroutput><userinput>n</userinput>
<computeroutput>Shall the new role be allowed to create databases? (y/n) </computeroutput><userinput>n</userinput>
<computeroutput>Shall the new role be allowed to create more new roles? (y/n) </computeroutput><userinput>n</userinput>
<computeroutput>CREATE USER</computeroutput>
</screen>
</para>
@ -303,9 +367,9 @@ PostgreSQL documentation
server on host <literal>eden</>, port 5000, avoiding the prompts and
taking a look at the underlying command:
<screen>
<prompt>$ </prompt><userinput>createuser -h eden -p 5000 -D -A -e joe</userinput>
<computeroutput>CREATE USER joe NOCREATEDB NOCREATEUSER;</computeroutput>
<computeroutput>CREATE USER</computeroutput>
<prompt>$ </prompt><userinput>createuser -h eden -p 5000 -S -D -R -e joe</userinput>
<computeroutput>CREATE ROLE joe NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN;</computeroutput>
<computeroutput>CREATE ROLE</computeroutput>
</screen>
</para>
@ -313,11 +377,11 @@ PostgreSQL documentation
To create the user <literal>joe</literal> as a superuser,
and assign a password immediately:
<screen>
<prompt>$ </prompt><userinput>createuser -P -d -a -e joe</userinput>
<computeroutput>Enter password for new user: </computeroutput><userinput>xyzzy</userinput>
<prompt>$ </prompt><userinput>createuser -P -s -e joe</userinput>
<computeroutput>Enter password for new role: </computeroutput><userinput>xyzzy</userinput>
<computeroutput>Enter it again: </computeroutput><userinput>xyzzy</userinput>
<computeroutput>CREATE USER joe PASSWORD 'xyzzy' CREATEDB CREATEUSER;</computeroutput>
<computeroutput>CREATE USER</computeroutput>
<computeroutput>CREATE ROLE joe PASSWORD 'xyzzy' SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN;</computeroutput>
<computeroutput>CREATE ROLE</computeroutput>
</screen>
In the above example, the new password isn't actually echoed when typed,
but we show what was typed for clarity. However the password
@ -333,7 +397,7 @@ PostgreSQL documentation
<simplelist type="inline">
<member><xref linkend="app-dropuser"></member>
<member><xref linkend="sql-createuser" endterm="sql-createuser-title"></member>
<member><xref linkend="sql-createrole" endterm="sql-createrole-title"></member>
<member>Environment Variables (<xref linkend="libpq-envars">)</member>
</simplelist>
</refsect1>

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.17 2005/06/21 04:02:33 tgl Exp $
* $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.18 2005/08/14 20:16:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -30,9 +30,18 @@ main(int argc, char *argv[])
{"quiet", no_argument, NULL, 'q'},
{"createdb", no_argument, NULL, 'd'},
{"no-createdb", no_argument, NULL, 'D'},
{"superuser", no_argument, NULL, 's'},
{"no-superuser", no_argument, NULL, 'S'},
{"createrole", no_argument, NULL, 'r'},
{"no-createrole", no_argument, NULL, 'R'},
{"inherit", no_argument, NULL, 'i'},
{"no-inherit", no_argument, NULL, 'I'},
{"login", no_argument, NULL, 'l'},
{"no-login", no_argument, NULL, 'L'},
/* adduser is obsolete, undocumented spelling of superuser */
{"adduser", no_argument, NULL, 'a'},
{"no-adduser", no_argument, NULL, 'A'},
{"sysid", required_argument, NULL, 'i'},
{"conn-limit", required_argument, NULL, 'c'},
{"pwprompt", no_argument, NULL, 'P'},
{"encrypted", no_argument, NULL, 'E'},
{"unencrypted", no_argument, NULL, 'N'},
@ -51,8 +60,11 @@ main(int argc, char *argv[])
bool echo = false;
bool quiet = false;
int createdb = 0;
int adduser = 0;
char *sysid = NULL;
int superuser = 0;
int createrole = 0;
int inherit = 0;
int login = 0;
char *conn_limit = NULL;
bool pwprompt = false;
int encrypted = 0; /* 0 uses server default */
char *newpassword = NULL;
@ -67,7 +79,8 @@ main(int argc, char *argv[])
handle_help_version_opts(argc, argv, "createuser", help);
while ((c = getopt_long(argc, argv, "h:p:U:WeqaAdDi:PEN", long_options, &optindex)) != -1)
while ((c = getopt_long(argc, argv, "h:p:U:WeqdDsSaArRiIlLc:PEN",
long_options, &optindex)) != -1)
{
switch (c)
{
@ -89,20 +102,40 @@ main(int argc, char *argv[])
case 'q':
quiet = true;
break;
case 'a':
adduser = +1;
break;
case 'A':
adduser = -1;
break;
case 'd':
createdb = +1;
break;
case 'D':
createdb = -1;
break;
case 's':
case 'a':
superuser = +1;
break;
case 'S':
case 'A':
superuser = -1;
break;
case 'r':
createrole = +1;
break;
case 'R':
createrole = -1;
break;
case 'i':
sysid = optarg;
inherit = +1;
break;
case 'I':
inherit = -1;
break;
case 'l':
login = +1;
break;
case 'L':
login = -1;
break;
case 'c':
conn_limit = optarg;
break;
case 'P':
pwprompt = true;
@ -133,26 +166,15 @@ main(int argc, char *argv[])
exit(1);
}
if (sysid)
{
char *endptr;
if (strtol(sysid, &endptr, 10) <= 0 || *endptr != '\0')
{
fprintf(stderr, _("%s: user ID must be a positive number\n"), progname);
exit(1);
}
}
if (newuser == NULL)
newuser = simple_prompt("Enter name of user to add: ", 128, true);
newuser = simple_prompt("Enter name of role to add: ", 128, true);
if (pwprompt)
{
char *pw1,
*pw2;
pw1 = simple_prompt("Enter password for new user: ", 100, false);
pw1 = simple_prompt("Enter password for new role: ", 100, false);
pw2 = simple_prompt("Enter it again: ", 100, false);
if (strcmp(pw1, pw2) != 0)
{
@ -163,33 +185,61 @@ main(int argc, char *argv[])
free(pw2);
}
if (superuser == 0)
{
char *reply;
reply = simple_prompt("Shall the new role be a superuser? (y/n) ", 1, true);
if (check_yesno_response(reply) == 1)
superuser = +1;
else
superuser = -1;
}
if (superuser == +1)
{
/* Not much point in trying to restrict a superuser */
createdb = +1;
createrole = +1;
}
if (createdb == 0)
{
char *reply;
reply = simple_prompt("Shall the new user be allowed to create databases? (y/n) ", 1, true);
reply = simple_prompt("Shall the new role be allowed to create databases? (y/n) ", 1, true);
if (check_yesno_response(reply) == 1)
createdb = +1;
else
createdb = -1;
}
if (adduser == 0)
if (createrole == 0)
{
char *reply;
reply = simple_prompt("Shall the new user be allowed to create more new users? (y/n) ", 1, true);
reply = simple_prompt("Shall the new role be allowed to create more new roles? (y/n) ", 1, true);
if (check_yesno_response(reply) == 1)
adduser = +1;
createrole = +1;
else
adduser = -1;
createrole = -1;
}
if (inherit == 0)
{
/* silently default to YES */
inherit = +1;
}
if (login == 0)
{
/* silently default to YES */
login = +1;
}
initPQExpBuffer(&sql);
printfPQExpBuffer(&sql, "CREATE USER %s", fmtId(newuser));
if (sysid)
appendPQExpBuffer(&sql, " SYSID %s", sysid);
printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser));
if (newpassword)
{
if (encrypted == +1)
@ -199,14 +249,28 @@ main(int argc, char *argv[])
appendPQExpBuffer(&sql, " PASSWORD ");
appendStringLiteral(&sql, newpassword, false);
}
if (superuser == +1)
appendPQExpBuffer(&sql, " SUPERUSER");
if (superuser == -1)
appendPQExpBuffer(&sql, " NOSUPERUSER");
if (createdb == +1)
appendPQExpBuffer(&sql, " CREATEDB");
if (createdb == -1)
appendPQExpBuffer(&sql, " NOCREATEDB");
if (adduser == +1)
appendPQExpBuffer(&sql, " CREATEUSER");
if (adduser == -1)
appendPQExpBuffer(&sql, " NOCREATEUSER");
if (createrole == +1)
appendPQExpBuffer(&sql, " CREATEROLE");
if (createrole == -1)
appendPQExpBuffer(&sql, " NOCREATEROLE");
if (inherit == +1)
appendPQExpBuffer(&sql, " INHERIT");
if (inherit == -1)
appendPQExpBuffer(&sql, " NOINHERIT");
if (login == +1)
appendPQExpBuffer(&sql, " LOGIN");
if (login == -1)
appendPQExpBuffer(&sql, " NOLOGIN");
if (conn_limit != NULL)
appendPQExpBuffer(&sql, " CONNECTION LIMIT %s", conn_limit);
appendPQExpBuffer(&sql, ";\n");
conn = connectDatabase("postgres", host, port, username, password, progname);
@ -217,7 +281,7 @@ main(int argc, char *argv[])
if (PQresultStatus(result) != PGRES_COMMAND_OK)
{
fprintf(stderr, _("%s: creation of new user failed: %s"),
fprintf(stderr, _("%s: creation of new role failed: %s"),
progname, PQerrorMessage(conn));
PQfinish(conn);
exit(1);
@ -226,7 +290,7 @@ main(int argc, char *argv[])
PQfinish(conn);
if (!quiet)
{
puts("CREATE USER");
puts("CREATE ROLE");
fflush(stdout);
}
exit(0);
@ -236,18 +300,25 @@ main(int argc, char *argv[])
static void
help(const char *progname)
{
printf(_("%s creates a new PostgreSQL user.\n\n"), progname);
printf(_("%s creates a new PostgreSQL role.\n\n"), progname);
printf(_("Usage:\n"));
printf(_(" %s [OPTION]... [USERNAME]\n"), progname);
printf(_("\nOptions:\n"));
printf(_(" -a, --adduser user can add new users\n"));
printf(_(" -A, --no-adduser user cannot add new users\n"));
printf(_(" -d, --createdb user can create new databases\n"));
printf(_(" -D, --no-createdb user cannot create databases\n"));
printf(_(" -P, --pwprompt assign a password to new user\n"));
printf(_(" -s, --superuser role will be superuser\n"));
printf(_(" -S, --no-superuser role will not be superuser\n"));
printf(_(" -d, --createdb role can create new databases\n"));
printf(_(" -D, --no-createdb role cannot create databases\n"));
printf(_(" -r, --createrole role can create new roles\n"));
printf(_(" -R, --no-createrole role cannot create roles\n"));
printf(_(" -l, --login role can login (default)\n"));
printf(_(" -L, --no-login role cannot login\n"));
printf(_(" -i, --inherit role inherits permissions of roles\n"));
printf(_(" it is a member of (default)\n"));
printf(_(" -I, --no-inherit role does not inherit permissions\n"));
printf(_(" -c, --conn-limit=N max connections for role (default: no limit)\n"));
printf(_(" -P, --pwprompt assign a password to new role\n"));
printf(_(" -E, --encrypted encrypt stored password\n"));
printf(_(" -N, --unencrypted do not encrypt stored password\n"));
printf(_(" -i, --sysid=SYSID select sysid for new user\n"));
printf(_(" -e, --echo show the commands being sent to the server\n"));
printf(_(" -q, --quiet don't write any messages\n"));
printf(_(" --help show this help, then exit\n"));
@ -257,7 +328,7 @@ help(const char *progname)
printf(_(" -p, --port=PORT database server port\n"));
printf(_(" -U, --username=USERNAME user name to connect as (not the one to create)\n"));
printf(_(" -W, --password prompt for password to connect\n"));
printf(_("\nIf one of -a, -A, -d, -D, and USERNAME is not specified, you will\n"
"be prompted interactively.\n"));
printf(_("\nIf one of -s, -S, -d, -D, -r, -R and USERNAME is not specified,\n"
"you will be prompted interactively.\n"));
printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
}