Home Explore Blog CI



postgresql

36th chunk of `doc/src/sgml/ddl.sgml`
c36475e694e59f563bd91ce6d3280804ed8fa4e3547ed2810000000100000fa3
 using
   the <quote>OR</quote> Boolean operator.  While permissive policies can be constructed
   to only allow access to rows in the intended cases, it can be simpler to
   combine permissive policies with restrictive policies (which the records
   must pass and which are combined using the <quote>AND</quote> Boolean operator).
   Building on the example above, we add a restrictive policy to require
   the administrator to be connected over a local Unix socket to access the
   records of the <literal>passwd</literal> table:
  </para>

<programlisting>
CREATE POLICY admin_local_only ON passwd AS RESTRICTIVE TO admin
    USING (pg_catalog.inet_client_addr() IS NULL);
</programlisting>

  <para>
   We can then see that an administrator connecting over a network will not
   see any records, due to the restrictive policy:
  </para>

<programlisting>
=&gt; SELECT current_user;
 current_user
--------------
 admin
(1 row)

=&gt; select inet_client_addr();
 inet_client_addr
------------------
 127.0.0.1
(1 row)

=&gt; TABLE passwd;
 user_name | pwhash | uid | gid | real_name | home_phone | extra_info | home_dir | shell
-----------+--------+-----+-----+-----------+------------+------------+----------+-------
(0 rows)

=&gt; UPDATE passwd set pwhash = NULL;
UPDATE 0
</programlisting>

  <para>
   Referential integrity checks, such as unique or primary key constraints
   and foreign key references, always bypass row security to ensure that
   data integrity is maintained.  Care must be taken when developing
   schemas and row level policies to avoid <quote>covert channel</quote> leaks of
   information through such referential integrity checks.
  </para>

  <para>
   In some contexts it is important to be sure that row security is
   not being applied.  For example, when taking a backup, it could be
   disastrous if row security silently caused some rows to be omitted
   from the backup.  In such a situation, you can set the
   <xref linkend="guc-row-security"/> configuration parameter
   to <literal>off</literal>.  This does not in itself bypass row security;
   what it does is throw an error if any query's results would get filtered
   by a policy.  The reason for the error can then be investigated and
   fixed.
  </para>

  <para>
   In the examples above, the policy expressions consider only the current
   values in the row to be accessed or updated.  This is the simplest and
   best-performing case; when possible, it's best to design row security
   applications to work this way.  If it is necessary to consult other rows
   or other tables to make a policy decision, that can be accomplished using
   sub-<command>SELECT</command>s, or functions that contain <command>SELECT</command>s,
   in the policy expressions.  Be aware however that such accesses can
   create race conditions that could allow information leakage if care is
   not taken.  As an example, consider the following table design:
  </para>

<programlisting>
-- definition of privilege groups
CREATE TABLE groups (group_id int PRIMARY KEY,
                     group_name text NOT NULL);

INSERT INTO groups VALUES
  (1, 'low'),
  (2, 'medium'),
  (5, 'high');

GRANT ALL ON groups TO alice;  -- alice is the administrator
GRANT SELECT ON groups TO public;

-- definition of users' privilege levels
CREATE TABLE users (user_name text PRIMARY KEY,
                    group_id int NOT NULL REFERENCES groups);

INSERT INTO users VALUES
  ('alice', 5),
  ('bob', 2),
  ('mallory', 2);

GRANT ALL ON users TO alice;
GRANT SELECT ON users TO public;

-- table holding the information to be protected
CREATE TABLE information (info text,
                          group_id int NOT NULL REFERENCES groups);

INSERT INTO information VALUES
  ('barely secret', 1),
  ('slightly secret', 2),
  ('very secret', 5);

ALTER TABLE information ENABLE ROW LEVEL SECURITY;

-- a row should be visible to/updatable by users whose security group_id is
-- greater than or equal to the row's group_id
CREATE POLICY

Title: Restrictive Policies, Referential Integrity, Row Security Parameter, and Policy Expressions
Summary
This section expands on row-level security (RLS) by explaining restrictive policies, which use the 'AND' operator. It showcases a restrictive policy that limits administrator access to the 'passwd' table via local Unix socket. It also discusses how referential integrity checks bypass RLS and how the row_security configuration parameter can be used to prevent silent omission of rows from backups. Finally, it explains that policy expressions should ideally only consider current values in the row, but sub-selects are available for policy decisions at the cost of performance and security.