mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Add REPLICATION privilege for ROLEs
This privilege is required to do Streaming Replication, instead of superuser, making it possible to set up a SR slave that doesn't have write permissions on the master. Superuser privileges do NOT override this check, so in order to use the default superuser account for replication it must be explicitly granted the REPLICATION permissions. This is backwards incompatible change, in the interest of higher default security.
This commit is contained in:
@ -94,6 +94,7 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
bool createrole = false; /* Can this user create roles? */
|
||||
bool createdb = false; /* Can the user create databases? */
|
||||
bool canlogin = false; /* Can this user login? */
|
||||
bool isreplication = false; /* Is this a replication role? */
|
||||
int connlimit = -1; /* maximum connections allowed */
|
||||
List *addroleto = NIL; /* roles to make this a member of */
|
||||
List *rolemembers = NIL; /* roles to be members of this role */
|
||||
@ -107,6 +108,7 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
DefElem *dcreaterole = NULL;
|
||||
DefElem *dcreatedb = NULL;
|
||||
DefElem *dcanlogin = NULL;
|
||||
DefElem *disreplication = NULL;
|
||||
DefElem *dconnlimit = NULL;
|
||||
DefElem *daddroleto = NULL;
|
||||
DefElem *drolemembers = NULL;
|
||||
@ -190,6 +192,14 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
errmsg("conflicting or redundant options")));
|
||||
dcanlogin = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "isreplication") == 0)
|
||||
{
|
||||
if (disreplication)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
disreplication = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "connectionlimit") == 0)
|
||||
{
|
||||
if (dconnlimit)
|
||||
@ -247,6 +257,8 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
createdb = intVal(dcreatedb->arg) != 0;
|
||||
if (dcanlogin)
|
||||
canlogin = intVal(dcanlogin->arg) != 0;
|
||||
if (disreplication)
|
||||
isreplication = intVal(disreplication->arg) != 0;
|
||||
if (dconnlimit)
|
||||
{
|
||||
connlimit = intVal(dconnlimit->arg);
|
||||
@ -272,6 +284,13 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to create superusers")));
|
||||
}
|
||||
else if (isreplication)
|
||||
{
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to create replication users")));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!have_createrole_privilege())
|
||||
@ -341,6 +360,7 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
/* superuser gets catupdate right by default */
|
||||
new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper);
|
||||
new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
|
||||
new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication);
|
||||
new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
|
||||
|
||||
if (password)
|
||||
@ -439,6 +459,7 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
int createrole = -1; /* Can this user create roles? */
|
||||
int createdb = -1; /* Can the user create databases? */
|
||||
int canlogin = -1; /* Can this user login? */
|
||||
int isreplication = -1; /* Is this a replication role? */
|
||||
int connlimit = -1; /* maximum connections allowed */
|
||||
List *rolemembers = NIL; /* roles to be added/removed */
|
||||
char *validUntil = NULL; /* time the login is valid until */
|
||||
@ -450,6 +471,7 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
DefElem *dcreaterole = NULL;
|
||||
DefElem *dcreatedb = NULL;
|
||||
DefElem *dcanlogin = NULL;
|
||||
DefElem *disreplication = NULL;
|
||||
DefElem *dconnlimit = NULL;
|
||||
DefElem *drolemembers = NULL;
|
||||
DefElem *dvalidUntil = NULL;
|
||||
@ -514,6 +536,14 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
errmsg("conflicting or redundant options")));
|
||||
dcanlogin = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "isreplication") == 0)
|
||||
{
|
||||
if (disreplication)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
disreplication = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "connectionlimit") == 0)
|
||||
{
|
||||
if (dconnlimit)
|
||||
@ -556,6 +586,8 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
createdb = intVal(dcreatedb->arg);
|
||||
if (dcanlogin)
|
||||
canlogin = intVal(dcanlogin->arg);
|
||||
if (disreplication)
|
||||
isreplication = intVal(disreplication->arg);
|
||||
if (dconnlimit)
|
||||
{
|
||||
connlimit = intVal(dconnlimit->arg);
|
||||
@ -594,12 +626,20 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to alter superusers")));
|
||||
}
|
||||
else if (((Form_pg_authid) GETSTRUCT(tuple))->rolreplication || isreplication >= 0)
|
||||
{
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to alter replication users")));
|
||||
}
|
||||
else if (!have_createrole_privilege())
|
||||
{
|
||||
if (!(inherit < 0 &&
|
||||
createrole < 0 &&
|
||||
createdb < 0 &&
|
||||
canlogin < 0 &&
|
||||
isreplication < 0 &&
|
||||
!dconnlimit &&
|
||||
!rolemembers &&
|
||||
!validUntil &&
|
||||
@ -685,6 +725,12 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
|
||||
}
|
||||
|
||||
if (isreplication >= 0)
|
||||
{
|
||||
new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication > 0);
|
||||
new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
|
||||
}
|
||||
|
||||
if (dconnlimit)
|
||||
{
|
||||
new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
|
||||
|
Reference in New Issue
Block a user