Thread: Security Label Inheritance

Security Label Inheritance

From
Damien Clochard
Date:
Hi

My name's Damien Clochard and I'm the main developer of the PostgreSQL 
Anonymizer extension. This extension relies heavily on security labels. 
Among other things, users can add labels to define a "masking rule" upon 
a column and to declare that a roles is "masked".

More details on how this works on the documentation:
https://postgresql-anonymizer.readthedocs.io/en/latest/dynamic_masking/

Currently a security label is applied to one and only one object. In 
particular a label does not apply to the objects that inherit from the 
objet it is originally associated with.

Consider the following

ALTER DATABASE foo SET session_preload_libraries = 'anon';
ALTER DATABASE foo SET anon.transparent_dynamic_masking = TRUE;

CREATE TABLE people AS SELECT 5432 AS id, 'slonik' AS name;
CREATE EXTENSION anon;
SECURITY LABEL FOR anon ON COLUMN people.name IS 'MASKED WITH VALUE 
NULL';
CREATE ROLE extern INHERIT;
SECURITY LABEL FOR anon ON ROLE extern IS 'MASKED';
GRANT USAGE ON SCHEMA public TO extern;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO extern;
CREATE ROLE joe LOGIN IN ROLE extern;

When connecting as role joe, I will have all the privileges granted to 
extern. However, joe is not affected by the security label defined on 
the extern group. He can read the personal data.

\connect - joe

SELECT * FROM people;
   id  |  name
------+--------
  5432 | slonik

I need to explicitly change the role for the label to be applied and in 
that case the mask upon the people.name column is applied

SET ROLE extern;

SELECT * FROM people;
   id  | name
------+------
  5432 |

I am not suggesting that this behaviour should change but I receive a 
lot of feedback from users showing some confusion as they would expect 
that the INHERIT clause would also apply to security labels, just like 
granted privileges.

A similar confusion occurs with inherited tables :

\connect - postgres
CREATE TABLE french (eat_frogs BOOLEAN) INHERITS(people);
INSERT INTO french VALUES (0,'damien', FALSE);
GRANT SELECT ON TABLE french TO extern;

SET ROLE extern;

The mask is applied to the parent table

SELECT * FROM people;
   id  |  name
------+--------
  5432 |
     0 |

But it is not applied to the child table

SELECT * FROM french;
  id |  name  | eat_frogs
----+--------+-----------
   0 | damien | f

Again most users expect that the masking rule on people.name would also 
be applied to french.name.


So my first question is : Do you think it would be helpful to update the 
SECURITY LABEL command documentation to clarify that security labels are 
not concerned by object inheritance ?

My second question is more open : do you think it would be worth adding 
a new way to declare that a security label applies to an object and all 
its inheritants ?  As I understand this would concern only roles and 
tables.

Maybe a new optional `[ [WITH] INHERIT | NOINHERIT ]` syntax at the end 
of the SECURITY LABEL command....

Something like this :

SECURITY LABEL FOR anon ON ROLE extern IS 'MASKED' WITH INHERIT;

SECURITY LABEL FOR anon ON COLUMN people.name
   IS 'MASKED WITH VALUE NULL'
   WITH INHERIT;

The default would be NOINHERIT and all extensions that rely on the 
current behaviour would continue to work without any change.

Let me know if I missed anything or if there's another way to achieve 
this kind of security label inheritance.

Regards,

--
Damien




Re: Security Label Inheritance

From
Andres Freund
Date:
Hi,

On February 25, 2025 10:08:44 AM GMT+01:00, Damien Clochard <damien@dalibo.info> wrote:
>So my first question is : Do you think it would be helpful to update the SECURITY LABEL command documentation to
clarifythat security labels are not concerned by object inheritance ? 

Couldn't hurt.


>My second question is more open : do you think it would be worth adding a new way to declare that a security label
appliesto an object and all its inheritants ?  As I understand this would concern only roles and tables. 
>
>Maybe a new optional `[ [WITH] INHERIT | NOINHERIT ]` syntax at the end of the SECURITY LABEL command....
>
>Something like this :
>
>SECURITY LABEL FOR anon ON ROLE extern IS 'MASKED' WITH INHERIT;
>
>SECURITY LABEL FOR anon ON COLUMN people.name
>  IS 'MASKED WITH VALUE NULL'
>  WITH INHERIT;
>
>The default would be NOINHERIT and all extensions that rely on the current behaviour would continue to work without
anychange. 

I doubt that is viable. That'd mean we somehow need to teach the label infrastructure about all kinds of inheritance
*and*make that recursive label collection fast. The caching right now uses generic infrastructure, it certainly
couldn'twith inheritance support.That'd be a fair bit of infrastructure.  

Greetings,

Andres
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.