Thread: Role Inheritance Without Explicit Naming?

Role Inheritance Without Explicit Naming?

From
François Beausoleil
Date:
Hi all,

I have four roles involved:

meetphil - the database owner, should not login
mpwebui - the role the web application logs in as, should have very limited privileges, but should be able to SET ROLE
toa user that has the correct privileges, should login 
mpusers - the main group for regular users, the group on which I'll grant default privileges, should not login
francois - one of the roles that has the right to do stuff, should login

I've gist'd everything here: https://gist.github.com/francois/9318054 (also appended at the end of this email).

In a fresh cluster, I create my users:

$ psql -U meetphil -d meetphil
psql (9.1.5)
Type "help" for help.

meetphil=> \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 colette   |                                                | {mpusers}
 francois  |                                                | {mpusers}
 meetphil  |                                                | {}
 mpusers   | Cannot login                                   | {}
 mpwebui   | No inheritance                                 | {mpusers}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 rene      |                                                | {mpusers}

After the users, I create my database and ALTER DEFAULT PRIVILEGES. When the database owner creates objects, the
correctprivileges are granted: 

meetphil=> \ddp
                Default access privileges
  Owner   | Schema |   Type   |     Access privileges
----------+--------+----------+---------------------------
 meetphil |        | function | =X/meetphil              +
          |        |          | meetphil=X/meetphil      +
          |        |          | mpusers=X/meetphil
 meetphil |        | sequence | meetphil=rwU/meetphil    +
          |        |          | mpusers=rwU/meetphil
 meetphil |        | table    | meetphil=arwdDxt/meetphil+
          |        |          | mpusers=arwdxt/meetphil
(3 rows)

Then, I create my schema, including parties, a simple table:

meetphil=> \dp parties
                                Access privileges
 Schema |  Name   | Type  |     Access privileges     | Column access privileges
--------+---------+-------+---------------------------+--------------------------
 public | parties | table | meetphil=arwdDxt/meetphil+|
        |         |       | mpusers=arwdxt/meetphil   |
(1 row)

When I login as francois, I can create a row in the parties table:

$ psql -U francois -d meetphil
psql (9.1.5)
Type "help" for help.

meetphil=> INSERT INTO parties(party_id) VALUES(default) RETURNING party_id;
 party_id
----------
        1
(1 row)

INSERT 0 1

On the other hand, when I login as mpwebui, I cannot SET ROLE TO francois:

$ psql -U mpwebui -d meetphil
psql (9.1.5)
Type "help" for help.

meetphil=> SET ROLE TO francois;
ERROR:  permission denied to set role "francois"

mpwebui also cannot insert into tables, which is the desired state:

meetphil=> INSERT INTO parties(party_id) VALUES(default) RETURNING party_id;
ERROR:  permission denied for relation parties

By changing how I create my regular users, I can login as mpwebui, then set role to francois and insert to the parties
table:

CREATE ROLE francois WITH LOGIN INHERIT IN ROLE mpusers ROLE mpwebui;

This results in the following \du:

                                        List of roles
 Role name |                   Attributes                   |            Member of
-----------+------------------------------------------------+---------------------------------
 colette   |                                                | {mpusers}
 francois  |                                                | {mpusers}
 meetphil  |                                                | {}
 mpusers   | Cannot login                                   | {}
 mpwebui   | No inheritance                                 | {mpusers,francois,rene,colette}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 rene      |                                                | {mpusers}

Note how mpwebui is now a member of francois, rene and colette. I expected mpwebui to inherit francois through mpusers.
CanI enable mpwebui to SET ROLE to francois without naming francois explicitely in mpwebui? 

I've found https://wiki.postgresql.org/images/d/d1/Managing_rights_in_postgresql.pdf which talks a bit about
inheritance,but I believe I have the same setup, but I must be wrong. 

I feel I'm pretty close, but the answer eludes me. It must be something basic. Can anyone spot it?

Thanks!
François Beausoleil

-- In a fresh cluster, login as postgres:
-- psql -U postgres -d postgres

-- The owner of all database objects
-- This user can and will change the database schema
CREATE ROLE meetphil WITH NOSUPERUSER NOCREATEDB NOCREATEROLE LOGIN;

-- The group which all regular users will be part of
CREATE ROLE mpusers WITH NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN;

-- The user which the web application connects as
-- Has limited rights by itself
CREATE ROLE mpwebui WITH NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT LOGIN IN ROLE mpusers;

-- The regular people
CREATE ROLE francois WITH LOGIN INHERIT IN ROLE mpusers;
CREATE ROLE rene WITH LOGIN INHERIT IN ROLE mpusers;
CREATE ROLE colette WITH LOGIN INHERIT IN ROLE mpusers;

-- Create the application database itself
CREATE DATABASE meetphil WITH
    owner = meetphil
    template = template0
    encoding = 'UTF-8'
    lc_ctype = 'en_US.UTF-8'
    lc_collate = 'en_US.UTF-8';

-- Grant privileges
GRANT CONNECT, TEMPORARY ON DATABASE meetphil TO mpwebui, mpusers;

\connect meetphil

ALTER DEFAULT PRIVILEGES FOR ROLE meetphil
  GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES, TRIGGER
  ON TABLES
  TO mpusers;

ALTER DEFAULT PRIVILEGES FOR ROLE meetphil
  GRANT EXECUTE
  ON FUNCTIONS
  TO mpusers;

ALTER DEFAULT PRIVILEGES FOR ROLE meetphil
  GRANT SELECT, UPDATE, USAGE
  ON SEQUENCES
  TO mpusers;

-- Execute as user meetphil, in database meetphil
-- psql -U meetphil -d meetphil
SET client_min_messages TO warning;

CREATE TABLE parties(
    party_id serial not null primary key
);

CREATE TABLE party_names(
    party_id int not null references parties
  , surname text not null
  , rest_of_name text
  , valid_starting_on date not null default current_date

  , unique(party_id, valid_starting_on, surname, rest_of_name)
  , constraint surname_not_empty check(length(trim(surname)) > 0)
  , constraint surname_is_trimmed check(trim(surname) = surname)
  , constraint rest_of_name_is_trimmed check((rest_of_name is not null and trim(rest_of_name) = rest_of_name) or
rest_of_nameis null ) 
);

-- Execute as mpwebui in the meetphil database
-- psql -U mpwebui -d meetphil
SET ROLE TO francois;

-- Results in:
-- ERROR:  permission denied to set role "francois"

-- I'd like to run this, as user francois
-- INSERT INTO parties(party_id) VALUES (default) RETURNING party_id;



Attachment

Re: Role Inheritance Without Explicit Naming?

From
Adrian Klaver
Date:
On 03/02/2014 08:48 PM, François Beausoleil wrote:
> Hi all,
>
> I have four roles involved:
>
> meetphil - the database owner, should not login
> mpwebui - the role the web application logs in as, should have very limited privileges, but should be able to SET
ROLEto a user that has the correct privileges, should login 
> mpusers - the main group for regular users, the group on which I'll grant default privileges, should not login
> francois - one of the roles that has the right to do stuff, should login
>
> I've gist'd everything here: https://gist.github.com/francois/9318054 (also appended at the end of this email).
>
> In a fresh cluster, I create my users:
>
> $ psql -U meetphil -d meetphil
> psql (9.1.5)
> Type "help" for help.
>
> meetphil=> \du
>                               List of roles
>   Role name |                   Attributes                   | Member of
> -----------+------------------------------------------------+-----------
>   colette   |                                                | {mpusers}
>   francois  |                                                | {mpusers}
>   meetphil  |                                                | {}
>   mpusers   | Cannot login                                   | {}
>   mpwebui   | No inheritance                                 | {mpusers}
>   postgres  | Superuser, Create role, Create DB, Replication | {}
>   rene      |                                                | {mpusers}
>


If I am following correctly what you want is something like this:


            ------   mpusers  < ----
            |                       |
      \|/                      |
         francois                 mpwebui


In other words access sibling roles through a parent role. Is this correct?


--
Adrian Klaver
adrian.klaver@aklaver.com


Re: Role Inheritance Without Explicit Naming?

From
François Beausoleil
Date:
Le 2014-03-03 à 10:53, Adrian Klaver a écrit :

> On 03/02/2014 08:48 PM, François Beausoleil wrote:
>> Hi all,
>>
>> I have four roles involved:
>>
>> meetphil - the database owner, should not login
>> mpwebui - the role the web application logs in as, should have very limited privileges, but should be able to SET
ROLEto a user that has the correct privileges, should login 
>> mpusers - the main group for regular users, the group on which I'll grant default privileges, should not login
>> francois - one of the roles that has the right to do stuff, should login
>>
>> I've gist'd everything here: https://gist.github.com/francois/9318054 (also appended at the end of this email).
>>
>> In a fresh cluster, I create my users:
>>
>> $ psql -U meetphil -d meetphil
>> psql (9.1.5)
>> Type "help" for help.
>>
>> meetphil=> \du
>>                              List of roles
>>  Role name |                   Attributes                   | Member of
>> -----------+------------------------------------------------+-----------
>>  colette   |                                                | {mpusers}
>>  francois  |                                                | {mpusers}
>>  meetphil  |                                                | {}
>>  mpusers   | Cannot login                                   | {}
>>  mpwebui   | No inheritance                                 | {mpusers}
>>  postgres  | Superuser, Create role, Create DB, Replication | {}
>>  rene      |                                                | {mpusers}
>>
>
>
> If I am following correctly what you want is something like this:
>
>
>           ------   mpusers  < ----
>           |                       |
>       \|/                      |
>        francois                 mpwebui
>
>
> In other words access sibling roles through a parent role. Is this correct?

Yes, when you put it that way, it looks like it. I'm just exploring ideas on how to secure access to the database. I'm
exploringalternatives. 

Bye,
François
Attachment

Re: Role Inheritance Without Explicit Naming?

From
Adrian Klaver
Date:
On 03/04/2014 06:00 AM, François Beausoleil wrote:
>
> Le 2014-03-03 à 10:53, Adrian Klaver a écrit :
>
>> On 03/02/2014 08:48 PM, François Beausoleil wrote:
>>> Hi all,
>>>
>>> I have four roles involved:
>>>
>>> meetphil - the database owner, should not login
>>> mpwebui - the role the web application logs in as, should have very limited privileges, but should be able to SET
ROLEto a user that has the correct privileges, should login 
>>> mpusers - the main group for regular users, the group on which I'll grant default privileges, should not login
>>> francois - one of the roles that has the right to do stuff, should login
>>>
>>> I've gist'd everything here: https://gist.github.com/francois/9318054 (also appended at the end of this email).
>>>
>>> In a fresh cluster, I create my users:
>>>
>>> $ psql -U meetphil -d meetphil
>>> psql (9.1.5)
>>> Type "help" for help.
>>>
>>> meetphil=> \du
>>>                               List of roles
>>>   Role name |                   Attributes                   | Member of
>>> -----------+------------------------------------------------+-----------
>>>   colette   |                                                | {mpusers}
>>>   francois  |                                                | {mpusers}
>>>   meetphil  |                                                | {}
>>>   mpusers   | Cannot login                                   | {}
>>>   mpwebui   | No inheritance                                 | {mpusers}
>>>   postgres  | Superuser, Create role, Create DB, Replication | {}
>>>   rene      |                                                | {mpusers}
>>>
>>
>>
>> If I am following correctly what you want is something like this:
>>
>>
>>            ------   mpusers  < ----
>>            |                       |
>>       \|/                      |
>>         francois                 mpwebui
>>
>>
>> In other words access sibling roles through a parent role. Is this correct?
>
> Yes, when you put it that way, it looks like it. I'm just exploring ideas on how to secure access to the database.
I'mexploring alternatives. 


Well my experience is that Postgres will not automatically do the above.
As you have found, you have to explicitly grant from one sibling to
another. There are others on this list that deal with more complicated
set ups then me and might have better ideas. In which case both of us
will learn something:)


>
> Bye,
> François
>


--
Adrian Klaver
adrian.klaver@aklaver.com