Re: [v9.4] row level security - Mailing list pgsql-hackers

From Gregory Smith
Subject Re: [v9.4] row level security
Date
Msg-id 52ABCF6C.4010409@gmail.com
Whole thread Raw
In response to Re: [v9.4] row level security  (Craig Ringer <craig@2ndquadrant.com>)
Responses Re: [v9.4] row level security
Re: [v9.4] row level security
List pgsql-hackers
While Craig has been soldiering onward to the write side of things, I've
been working with some groups who are evaluating if the RLS feature is
good enough for switching some real world apps over to use PostgreSQL.
Amazingly I can even say that these are applications involving the US
Department of Defense, and they're going well so far.  There has been
some concern on this list as to whether this feature is being evaluated
by people who are serious about real-world database security issues.
The crowd I'm talking to now sure is.  There's some interesting bad
news, like how we're going to have to completely refactor all the "if
(!superuser())" shortcuts into real permissions one day to make them
happy.  But for the most part the prototype conversions have been
working out.  The RLS feature set available with the CF submission is
good enough for those projects to continue exploring PostgreSQL.  I feel
good now that if the code issues around what's already been developed
are sorted out to commit quality, the users really will queue once this
hits.

== Review demo code ==

Attached is a small demo piece built by my new co-worker Jeff McCormick
that I've been hacking lightly on.  The idea was to get something a step
beyond trivial that maps into real-world need, well enough that we could
get people to agree it was usefully representative.  What they did is
take the sort of security levels these apps have, which often includes
two different criteria for each row, and mapped that into what the RLS
submission supports. There are a set of roles for the permission to see
various shapes (triangle/circle/square/heart) and colors, and then
people can see a row only if they have both color and shape
permissions.  The part that I thought was cute when I first read it is
how this query looks up data in the catalog to accomplish that:

ALTER TABLE colors_shapes
   SET ROW SECURITY FOR ALL TO (
   color IN (
     SELECT permission_role.rolname FROM pg_roles active_role,
pg_auth_members, pg_roles permission_role WHERE
       active_role.rolname = current_user AND
       active_role.oid = pg_auth_members.member AND
       permission_role.oid = pg_auth_members.roleid
     )
   AND shape IN (
     SELECT permission_role.rolname FROM pg_roles active_role,
pg_auth_members, pg_roles permission_role WHERE
       active_role.rolname = current_user AND
       active_role.oid = pg_auth_members.member AND
       permission_role.oid = pg_auth_members.roleid
     )
);

Insert some data that looks like this:

  id |    color    |     shape
----+-------------+---------------
   1 | blue_role   | triangle_role
   2 | red_role    | heart_role
   3 | purple_role | circle_role

And then users can see rows only if they have a pair of matches on both
those role sets.  The fact that you can just plug in whatever you want
into SET ROW SECURITY allows all kinds of things.  I have a more
complicated sample we're still poking at, using a full pl/pgsql function
there, but I've already got enough to try and cover in this message to
bring that in today.  One reason the users I've been talking to feel
comfortable that they'll be able to build apps usefully with this
feature is this interface.  It feels more like a pluggable API for
defining rules than a specific implementation. Congratulations to the
usual community members who expect complete feature overkill in every
design.

== Code review ==

Onto coding.  Rather than trying to cope with patches I pulled KaiGai's
tree from https://github.com/kaigai/sepgsql/tree/rowsec to try things
out.  That hasn't been merged against head in a while and it's suffered
serious but not terminal bit rot.  The REPLICA IDENTITY changes in
particular touched adjacent code all over the place, since it and RLS
are both added things to the end of existing lists.  The merges to get
thing back to working again were only hard when my eyes crossed on the
always fun pg_class bootstrapping table.  I did all that myself up to
committed changes on Dec 3.  The only real change I made was to punt the
OID number assignment into a whole different range, to make future merge
rot less likely.  Those are going to get reassigned at commit time
anyway, no need to try and guess the appropriate next number for each today.

I just pushed a fork of KaiGai's repo to
https://github.com/gregs1104/sepgsql/tree/rls that includes all of the
must fix items to get the feature working again.  That's what the
attached demo code was tested again.  The regression tests are still
seriously busted, beyond just regenerating new output.  I pushed that
off for now, I need to study recent commits better to catch up on what
changed.  For community reference I'm attaching an updated patch that
forks master after dfd5151c5800448a2be521797f95e1aa63d87b67 and then has
the merging I did.  I'm hoping that getting a positive functional review
will lure KaiGai back to help me update things.  Hopefully pulling or
looking at commits from my merge attempt helps with that.

The (blue) elephant in the room here for this feature is the list of
committers in particular who are very picky about the parts of the code
this feature is touching (*cough* Tom).  One reason I'm trying to get
these demo pieces together--Jeff here is building a whole RLS test
sample repo--is to try and make the job of testing this out easier.  As
I dig myself out of the hole I'm in after getting really sick instead of
going to PG.EU, I've got a whole lot of time set aside to work on
community features lined up.

== Outstanding issues ==

Things I can already see to work on here are:

-Fix the regression tests
-Catch up to master again
-Continue to expand the functional tests
-Is there enough information about row security available in psql
output?  For example, there's nothing in "\d" output that suggests it
might exist.  pg_rowsecurity is a monster to try and read.
-Documentation needs plenty of editing, which I can take care of.

== Cover Channels ==

One last topic since I know it's been a sore point.  Covert channels.
There's still some obvious ones around.  In this example I was plenty
uneasy about some of what you can learn from the EXPLAIN output too.
But no one I've talked to about deploying PostgreSQL RLS seem terrible
uncomfortable with the exposure at this point.  RLS is just one layer of
extra protection on checks that are also happening in the application
API exposing the data to users. No one expects any one layer to be the
impenetrable one.  In the interest of CYA, I've talked through some
scenarios where attackers have resources like a hacked libpq client and
enough info to search the key space.  Instead of expecting that the
database can survive that, which is pretty unreasonable, what I'm
getting requests for now is better audit logging to make it easier to
detect that.  We should certainly close any holes we can, but where
things are at today doesn't seem functionally unacceptable anymore.

--
Greg Smith greg.smith@crunchydatasolutions.com
Chief PostgreSQL Evangelist - http://crunchydatasolutions.com/

Attachment

pgsql-hackers by date:

Previous
From: Tatsuo Ishii
Date:
Subject: encoding name "SHIFT_JIS" is absent in chklocale.c
Next
From: Craig Ringer
Date:
Subject: Re: [v9.4] row level security