From: | Stephen Frost <sfrost(at)snowman(dot)net> |
---|---|
To: | Adam Brightwell <adam(dot)brightwell(at)crunchydatasolutions(dot)com> |
Cc: | Andres Freund <andres(at)anarazel(dot)de>, PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org> |
Subject: | Re: Role Attribute Bitmask Catalog Representation |
Date: | 2014-12-05 18:37:59 |
Message-ID: | 20141205183759.GU25679@tamriel.snowman.net |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Adam,
* Adam Brightwell (adam(dot)brightwell(at)crunchydatasolutions(dot)com) wrote:
> I have attached an updated patch that incorporates the feedback and
> recommendations provided.
Thanks. Comments below.
> diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
> --- 56,62 ----
>
> backupidstr = text_to_cstring(backupid);
>
> ! if (!superuser() && !check_role_attribute(GetUserId(), ROLE_ATTR_REPLICATION))
> ereport(ERROR,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> errmsg("must be superuser or replication role to run a backup")));
The point of has_role_attribute() was to avoid the need to explicitly
say "!superuser()" everywhere. The idea with check_role_attribute() is
that we want to present the user (in places like pg_roles) with the
values that are *actually* set.
In other words, the above should just be:
if (!has_role_attribute(GetUserId(), ROLE_ATTR_REPLICATION))
> --- 84,90 ----
> {
> XLogRecPtr stoppoint;
>
> ! if (!superuser() && !check_role_attribute(GetUserId(), ROLE_ATTR_REPLICATION))
> ereport(ERROR,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> (errmsg("must be superuser or replication role to run a backup"))));
Ditto here.
> diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
> --- 5031,5081 ----
> }
>
> /*
> ! * has_role_attribute
> ! * Check if the role has the specified role has a specific role attribute.
> ! * This function will always return true for roles with superuser privileges
> ! * unless the attribute being checked is CATUPDATE.
> *
> ! * roleid - the oid of the role to check.
> ! * attribute - the attribute to check.
> */
> bool
> ! has_role_attribute(Oid roleid, RoleAttr attribute)
> {
> ! /*
> ! * Superusers bypass all permission checking except in the case of CATUPDATE.
> ! */
> ! if (!(attribute & ROLE_ATTR_CATUPDATE) && superuser_arg(roleid))
> return true;
>
> ! return check_role_attribute(roleid, attribute);
> }
>
> + /*
> + * check_role_attribute
> + * Check if the role with the specified id has been assigned a specific
> + * role attribute. This function does not allow any superuser bypass.
I don't think we need to say that it doesn't "allow" superuser bypass.
Instead, I'd comment that has_role_attribute() should be used for
permissions checks while check_role_attribute is for checking what the
value in the rolattr bitmap is and isn't for doing permissions checks
directly.
> diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
> *************** CreateRole(CreateRoleStmt *stmt)
> *** 82,93 ****
> bool encrypt_password = Password_encryption; /* encrypt password? */
> char encrypted_password[MD5_PASSWD_LEN + 1];
> bool issuper = false; /* Make the user a superuser? */
> ! bool inherit = true; /* Auto inherit privileges? */
> 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? */
> bool bypassrls = false; /* Is this a row security enabled 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 */
> --- 74,86 ----
> bool encrypt_password = Password_encryption; /* encrypt password? */
> char encrypted_password[MD5_PASSWD_LEN + 1];
> bool issuper = false; /* Make the user a superuser? */
> ! bool inherit = true; /* Auto inherit privileges? */
> 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? */
> bool bypassrls = false; /* Is this a row security enabled role? */
> + RoleAttr attributes = ROLE_ATTR_NONE; /* role attributes, initialized to none. */
> 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 */
Please clean up the whitespace changes- there's no need for the
'inherit' line to change..
> diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
> *************** XLogRead(char *buf, TimeLineID tli, XLog
> *** 205,211 ****
> static void
> check_permissions(void)
> {
> ! if (!superuser() && !has_rolreplication(GetUserId()))
> ereport(ERROR,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> (errmsg("must be superuser or replication role to use replication slots"))));
> --- 207,213 ----
> static void
> check_permissions(void)
> {
> ! if (!superuser() && !check_role_attribute(GetUserId(), ROLE_ATTR_REPLICATION))
> ereport(ERROR,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> (errmsg("must be superuser or replication role to use replication slots"))));
Another case which should be using has_role_attribute()
> diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c
> --- 17,34 ----
> #include "miscadmin.h"
>
> #include "access/htup_details.h"
> + #include "catalog/pg_authid.h"
> #include "replication/slot.h"
> #include "replication/logical.h"
> #include "replication/logicalfuncs.h"
> + #include "utils/acl.h"
> #include "utils/builtins.h"
> #include "utils/pg_lsn.h"
>
> static void
> check_permissions(void)
> {
> ! if (!superuser() && !check_role_attribute(GetUserId(), ROLE_ATTR_REPLICATION))
> ereport(ERROR,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> (errmsg("must be superuser or replication role to use replication slots"))));
Also here.
> diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
> *************** pg_role_aclcheck(Oid role_oid, Oid rolei
> *** 4602,4607 ****
> --- 4603,4773 ----
> return ACLCHECK_NO_PRIV;
> }
>
> + /*
> + * pg_has_role_attribute_id_attr
I'm trying to figure out what the point of the trailing "_attr" in the
function name is..? Doesn't seem necessary to have that for these
functions and it'd look a bit cleaner without it, imv.
> diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
> new file mode 100644
> index c348034..be0e1cc
> *** a/src/backend/utils/init/postinit.c
> --- b/src/backend/utils/init/postinit.c
> *************** InitPostgres(const char *in_dbname, Oid
> *** 762,768 ****
> {
> Assert(!bootstrap);
>
> ! if (!superuser() && !has_rolreplication(GetUserId()))
> ereport(FATAL,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> errmsg("must be superuser or replication role to start walsender")));
> --- 762,768 ----
> {
> Assert(!bootstrap);
>
> ! if (!superuser() && !check_role_attribute(GetUserId(), ROLE_ATTR_REPLICATION))
> ereport(FATAL,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> errmsg("must be superuser or replication role to start walsender")));
Also here.
> ! #define ROLE_ATTR_ALL 255 /* or (1 << N_ROLE_ATTRIBUTES) - 1 */
I'd say "equals" or something rather than "or" since that kind of
implies that it's an laternative, but we can't do that as discussed in
the comment (which I like).
> ! /* role attribute check routines */
> ! extern bool has_role_attribute(Oid roleid, RoleAttr attribute);
> ! extern bool check_role_attribute(Oid roleid, RoleAttr attribute);
With all the 'has_role_attribute(GetUserId(), ROLEATTR_BLAH)' cases, I'd
suggest doing the same as 'superuser()' and also provide a simpler
version: 'have_role_attribute(ROLEATTR_BLAH)' which handles doing the
GetUserId() itself. That'd simplify quite a few of the above calls.
I'm pretty happy with the rest of it.
Thanks!
Stephen
From | Date | Subject | |
---|---|---|---|
Next Message | Jim Nasby | 2014-12-05 18:57:34 | Re: Parallel Seq Scan |
Previous Message | Robert Haas | 2014-12-05 18:37:12 | Re: INSERT ... ON CONFLICT {UPDATE | IGNORE} |