Preventing Human Errors in Postgres

Whenever discussion on Disaster Recovery Planning for the databases comes up, “Preventing & Recovering from Human Error” topic arises because human tends to make mistakes and engineers are humans ūüôā ¬†Having best DBAs around and with restrictions & ¬†best practices/policies in-place, ¬†you still can’t afford to ignore the fact – “an engineer could make mistake”. ¬†For disaster recovery planning , this factor should be taken into consideration.

Fixing or recovering from human errors, specially inside databases, is costly , which is ¬† accepted fact¬†ūüôĀ ¬†Having better access, restrictions and good practices in-place could help to avoid some of the silly mistakes but you never know !!¬†What if the Superuser (DBAs or anyone having super privileges) makes the mistake?

While dealing with databases, there are number of unknown and unimaginable ways, the engineer could make ¬†mistakes, but I’m going to talk about couple of known and specific mistakes and how Postgres features could be used ¬†to prevent those mistakes:

Preventing DROP DATABASE

Last week, Payal, one of my colleagues , asked me ; Is there anyway to prevent superuser from dropping ¬†production database? My immediate response was: superuser(DBAs) can’t afford to make that mistake !!!!

She asked me another question; What if I convert production db to template database so it can _NOT_ be dropped even you are superuser? As you can see below, template database can not be dropped:

testdb=# drop database template1;
ERROR: cannot drop a template database

My  immediate response was;  hrmm.. there  could be security issue. The topic looked interesting to me so I started digging further into the topic on making production db to template database. As the Document suggests,  datistemplate can be set to indicate that a database is intended as a template for CREATE DATABASE. If this flag is set, the database can be cloned by any user with CREATEDB privileges; if it is not set, only superusers and the owner of the database can clone it.

As you might have realized now , there is a little risk because a user with CREATEDB can close the production database. Fortunately, CREATEDB is not default permission, you have to grant it explicitly. ¬†The gain of preventing DROP DATABASE is much higher than underlying security issue.¬†This is still experimental thought !! If you see any problems setting production db to template database, please shout out! ¬†The below example converts the “proddb” to template database by setting datistemplate flag to true and try to drop the database using superuser:

testdb=# update pg_database set datistemplate=true where datname=’proddb’;
UPDATE 1
testdb=# drop database proddb;
ERROR: cannot drop a template database

Preventing DROP TABLE

After coming up possible fix on DROP DATABASE, we decided to investigate further on similar ways of preventing dropping table accidentally !!

Actually, Postgres 9.3 introduced new feature “System level Trigger“. This can be used to prevent table drop in production. The below¬†example shows how to prevent specific table to be dropped from the database:

Function to prevent single table drop

CREATE OR REPLACE FUNCTION confirm_drop()
RETURNS event_trigger
LANGUAGE plpgsql
AS $$
DECLARE
obj record;
BEGIN
FOR obj in SELECT * from pg_event_trigger_dropped_objects()
LOOP
IF obj.object_name = ‘users’ AND obj.schema_name = ‘testing’ THEN
RAISE EXCEPTION ‘command % is disabled for this table’, tg_tag;
END IF;
END LOOP;
END;
$$;

Place System Level Trigger

CREATE EVENT TRIGGER confirm_drop on sql_drop WHEN TAG IN (‘DROP TABLE’) EXECUTE PROCEDURE confirm_drop();

Let’s try to drop USERS table…

postgres=# drop table testing.users;
ERROR: command DROP TABLE is disabled for this table
STATEMENT: drop table testing.users;
ERROR: command DROP TABLE is disabled for this table

The above output shows even superuser can not drop the table. You could use similar approach to prevent TABLE DROP on SCHEMA or ALL TABLES in the production database.

However,  I can think off two possible downside of this approach ; (i) The system level trigger feature is not available until Postgres 9.3 (ii) You have to take the system level trigger into consideration while  actually dropping individual table or  any table in schema or databases.

I’d still rely on best practices for making sure the human errors can be avoided by putting required restrictions in place and following best practices for schema changes . Though, PostgreSQL allows us technical capability to prevent these mistakes by providing very low overhead technical solutions. Is it worth to take advantage of it? If you are planning on attending PGConf NYC or PGCon in Ottawa this year, let’s discuss in-person?

Thoughts/Comments/Concerns are welcome.

Postgres Security & PGConf NYC 2014

As per my knowledge, I haven’t heard or attended ¬†Postgres conference with dedicated “Security” track . Rarely, you find one or two talks about security over couple of Postgres conferences but ¬†never a dedicated track ! ¬†It is ¬†indisputable to say that ¬†Security is one of the most critical areas to consider for selecting ¬†database for the application. I’m really excited ¬†to attend and speak ¬†about Postgres Security features at PGConf ¬†NYC 2014 conference, which is going to be held on April 3-4, 2014 in New York and will have dedicated “security” track ! Hats off to organizers ¬†ūüôā

My employer,¬†OmniTI,¬†is one of the Gold sponsors for the event.¬†¬†If you are planning to attend the conference, please use code “OMNITINYC14” at checkout, it will allow you to receive a 10% discount on both the Early Bird and Regular ticket prices – the code is valid through March 15th.

If you want to make friends in Postgres community and eager to learn ¬†advance features ¬†in Postgres & more specifically Security features, ¬†you probably don’t want to miss out this rare opportunity!

Send me note, if you want to catchup in-person in NYC.  Looking forward to see you there !