Database Layer
The multi-schema approach is OK but as always the devil is in the detail.
One major isolation technique that is underappreciated is separate schemas for the tabledata owner and for the web-app to access.
- This reduces the impact of any compromise by using least privilege, taking away specific rights of the connecting database user to really destroy the database (cannot drop tables or view hidden data).
- Allows the application to hide data (behind packages or views).
- You can use synonyms to map between web-app user and table owner schemas.
An Example Setup to get you started.
Data Owner: MYCLIENT_OWNER Web User: MYCLIENT_USER <- Django points to this schema Synonyms: MYCLIENT_USER.TABLE1 -> MYCLIENT_OWNER.TABLE1 (for all required tables) Grants: MYCLIENT_USER Granted Select, Insert, Update Delete as appropriate. Packages: MYCLIENT_USER Synonyms/Grants for required Packages, Functions and Procedures. Authentication Layer
The authentication of users can be isolated into a sso / ldap server.
- This reduces the impact of a compromise of your web-app.
- The surface area of the authentication service is much much smaller than the whole system.
- But as always this is more complicated and usually more expensive (even if only for setup time).
Symmetric Encryption
I have heard that wallet key storage outside the database is the best practice here, but an alternative is to hide the data behind functions as above.
I suspect that a encryption service on a different box might be a good alternative, but I have never seen this design used before.