In our database (DB for brevity) we store some very sensitive government data, and would like to secure the data as much as possible.

There are two way to think about security here:

  1. defense from external intruders (essentially making sure PCI-DSS compliance is in place, for instance),
  2. security from internal intruders.

My question is focused on the latter.

The sensitivity of information is considered so high that we're facing a very likely possibility of internal staff getting their hands on the data.

In other words, we're afraid that internal staff can mass-steal the data and trade it (the data is only interesting when stolen altogether, as it's a huge DB of people's private info).

The DB is accessed by our application, on a record-by-record manner. This is considered fine, as using record-by-record manner of accessing data staff is not expected to mass-steal the information.

An obvious solution would be: give "keys to DB" to a single, most trusted man. However our concern is that even in this case someone can put a gun to his head and ask to make the copy of the DB.

Is there any way we could secure the DB, such that even if the DBA is put a gun to his head, he would be physically unable to steal the data?

Note: The database management system we are using is PostgreSQL, but we may easily switch to another one provided it offers the safety guarantees we're seeking.

  • 1
    A client of mine keeps their administrative password in a safe. If there is a physical security device, such as a safe, vault, bank deposit, etc, that can require two-man authentication, that could be a way forward for you. Along with encrypting the physical storage and backups, obviously. As @JustinCave says, the rest is product-specific. Commented Mar 15, 2017 at 11:38
  • With both external and internal questions, I think this question is too vague to be answered. If you're protecting from gun-against-the-head, that's one question generic to all databases. If you're protecting against externals threats from network intrusion, that's another question. Commented Mar 15, 2017 at 18:42

2 Answers 2



Require more heads. This solution scales linearly. Every gun you need to protect against requires one more disinterested head. Consider methods of discrete head positioning. The more work you spend positioning the heads, the more work others have to spend positioning guns. Hide heads for extra obfuscation.

Security is O(n) with heads: MySQL is equally secure with a rock, which is equally as secure as PostgreSQL. That's the best position in a security analogy MySQL has ever been in.

Software Stack Security

  • Network Encryption, use SSL with an AES cipher. Consider layering DB authentication with network authentication using openswan/strongswan.
  • Disk Encryption, use eCryptfs
  • Authentication, use GSSAPI

Database Security

PostgreSQL supports row-level security. I definitely suggest reviewing the DDL security docs. This protects the database against unbridled app-level access. Perhaps all of your data doesn't need to be read by every app? You can even REVOKE or GRANT access to specific columns on the table, see the docs for more info (search for column).

Special notes

You can store encrypted data in the database too. This gets the DBA admin out of the problem entirely. Then the gun-against-the-head switches points of failure to the end-user. This may or may not be a good thing. Certainly, I prefer them to risk the gun-against-the-head scenarios. I just run it.


My immediate thought is SQL 2016 Enterprise "Always Encrypted", which encrypts the values on the fly but also lets a separate department such as SecurityOps hold the keys. This way the DBA, web admins, and others simply do not have the final encryption values needed and someone else can have it.

Of course this is new and not fool proof. There are all kinds of limitations which you should look up when you decide to test due to them changing over time. You could even have unsecured data which you think is secured if you're not careful.

However if you can properly identify which columns you want encrypted on this level, this is a good solution to look at to see if it fits your needs. Some limitations I copied from here but certainly not all are:

  • Columns using one of the following datatypes: xml, timestamp/rowversion, image, ntext, text, sql_variant, hierarchyid, geography, geometry, alias, user defined-types.
  • FILESTREAM columns
  • Columns with ROWGUIDCOL property
  • String (varchar, char, etc.) columns with non-bin2 collations
  • Columns that are keys for nonclustered indices using a randomized encrypted column as a key column (deterministic encrypted columns are fine)
  • Columns that are keys for clustered indices using a randomized encrypted column as a key column (deterministic encrypted columns are fine)
  • Columns that are keys for fulltext indices containing encrypted columns both randomized and deterministic
  • Columns referenced by computed columns (when the expression does unsupported operations for Always Encrypted)
  • Sparse column set
  • Columns that are referenced by statistics
  • Columns using alias type
  • Partitioning columns
  • Columns with default constraints
  • Columns referenced by unique constraints when using randomized encryption (deterministic encryption is supported)
  • Primary key columns when using randomized encryption (deterministic encryption is supported)
  • Referencing columns in foreign key constraints when using randomized encryption or when using deterministic encryption, if the referenced and referencing columns use different keys or algorithms
  • Columns referenced by check constraints
  • Columns in tables that use change data capture
  • Primary key columns on tables that have change tracking
  • Columns that are masked (using Dynamic Data Masking)
  • Columns in Stretch Database tables. (Tables with columns encrypted with Always Encrypted can be enabled for Stretch.)
  • Columns in external (PolyBase) tables (note: using external tables and tables with encrypted columns in the same query is supported)
  • Columns in table variables

Configuring "Always Encrpyted"

Otherwise you might be better off rolling your own app level encryption support where the key management is handled with a separate team that the ops team cannot access. The data being written will be encrypted as it is being written so there is still no chance of man in the middle attacks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.