Re: [PATCHES] [PATCH] Re: Why READ ONLY transactions?

From: Sean Chittenden <sean(at)chittenden(dot)org>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Christopher Browne <cbbrowne(at)libertyrms(dot)info>, pgsql-patches(at)postgresql(dot)org, Robert Treat <xzilla(at)users(dot)sourceforge(dot)net>, Gavin Sherry <swm(at)linuxworld(dot)com(dot)au>, pgsql-advocacy(at)postgresql(dot)org
Subject: Re: [PATCHES] [PATCH] Re: Why READ ONLY transactions?
Date: 2003-07-30 21:10:26
Message-ID: 20030730211026.GB34647@perrin.int.nxad.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-advocacy pgsql-hackers pgsql-patches

> >> I would NOT call it a "security" provision, as it is fairly
> >> easily defeated using SET TRANSACTION.
>
> > Um, why not make it an actual full blown security feature by
> > applying the following patch?
>
> It's not intended to be a security measure, and I would strongly
> resist any attempt to make it so along the lines you propose.

Intended or not, it does work.

> I do not want to try to base real security on GUC settings. The GUC
> mechanism is not designed to be unsubvertible, it's designed to
> allow convenient administration of a bunch of settings.

I agree that permissions of objects or anything specific should remain
outside of the GUC system, however for global GUC like things, such as
the default mode of a transaction (READ ONLY/READ WRITE), this is
perfect (I think of PostgreSQL's GUC system the same way I do
FreeBSD's sysctl MIB system or Linux's /proc file system: useful for
global things, in appropriate for anything fine grained). I was
thinking about that this morning, a better name would be
"jail_read_only_transactions" as the GUC contains a user to a read
only transaction. It could be confusing in that it doesn't force a
transaction to be read only.

> In any case, we already have mechanisms for preventing specific
> users from altering data: that's what GRANT/REVOKE are for. I don't
> think anyone would have bothered with START TRANSACTION READ ONLY if
> it weren't required by the SQL spec.

Ah, but this falls on its face when you want a user who does have
write access to tables to go through a fixed procedure before opening
up the DB for write access (logging of SELECTs will always require
some goo). To prevent a user who does have write access
(INSERT/UPDATE/DELETE) to tables from modifying tables before they've
started a transaction inside of the database system (different than
BEGIN, custom function start_txn() that sets up the database for
logging), in every function, I used to have to test to see if the
txn_id was in the temp table. With the posted patch, I can ensure a
fully auditable and exceedingly secure database (except for malicious
DBAs) that prevents any kind of unlogged abuse. Here's what I'm
planning on doing in my tree:

-- Username joe is any non-dba
ALTER USER joe SET transaction_force_read_only TO TRUE;
ALTER USER joe SET default_transaction_read_only TO TRUE;
CREATE FUNCTION public.start_txn()
RETURNS BIGINT
EXTERNAL SECURITY DEFINER
AS '
-- Pulls a txn_id from a sequence and stuff value into a temp
-- table that a user doesn't have write access to. Once
-- transaction ID is stored, change the transaction from READ
-- ONLY to READ WRITE. Return the txn_id to the user.
' LANGUAGE 'plpgsql';

Before, I had to have every function that modified data test to see if
a txn_id existed in the session temp table. Now, by relying on the
transaction's mode, I only have to test for that on the tables that I
log when there is SELECT activity, which will cut the number of lines
of pl/PgSQL code by about 1200-1500 lines[1]!

At the very least, it's an easier way of guaranteeing a READ ONLY
database. Securing a database with GRANT/REVOKE can be tedious and
error prone. In the case of a PHP Web shop/hacker that hasn't a clue
about quoting data before sending queries to the backend, this is a
nice safety blanket that takes a few seconds to setup (create user
www, alter user, alter user && *poof*, www user is secure). Right
now, to secure a user, you have to REVOKE INSERT, UPDATE, DELETE on
all tables, schemas and functions running as SECURITY DEFINER that
modify data, whereas jail_read_only_transactions is a simple and
effective blanket. IMHO, this is a huge 2nd safety belt that's easy
to apply, even though you're right, people _should_ rely on
GRANT/REVOKE.... though GRANT/REVOKE doesn't work in some situations
as mentioned above.

-sc

[1] Pl/PgSQL code + surrounding white space (* >300):

PERFORM TRUE FROM [temp_tbl]...;
IF NOT FOUND THEN
RAISE EXCEPTION ''my error message'';
END IF;

--
Sean Chittenden

In response to

Responses

Browse pgsql-advocacy by date

  From Date Subject
Next Message Sean Chittenden 2003-07-30 21:33:35 Re: [PATCH] Re: [pgsql-advocacy] Why READ ONLY transactions?
Previous Message Rod Taylor 2003-07-30 20:43:56 Re: On Domains

Browse pgsql-hackers by date

  From Date Subject
Next Message Sean Chittenden 2003-07-30 21:33:35 Re: [PATCH] Re: [pgsql-advocacy] Why READ ONLY transactions?
Previous Message Christopher Browne 2003-07-30 21:07:31 Re: Upgrading my BSDI box, again

Browse pgsql-patches by date

  From Date Subject
Next Message Sean Chittenden 2003-07-30 21:33:35 Re: [PATCH] Re: [pgsql-advocacy] Why READ ONLY transactions?
Previous Message Nic 2003-07-30 19:44:24 Re: JDBC stored procs doc patch