Multi tenancy with Schemas and RLS in PostgreSQL - postgresql

I am new to Postgres/databases and am thinking of how to design a multi tenant application. I read some of the basic stuff such as schemas supported by Postgres and Row Level Security which is added since Postgres 9.5. So in my case a tenant can have many users. Two different tenants can have users with same name ( Kind of like a hierarchy). So at the top level, I can have a schema for each tenant. And then within each there is a RLS policy for users. Can this be done in Postgres and is this a good option ? With RLS, I will need a role for each user. This will probably blow up since my understanding is that roles are global across schemas.
Or other thing I can think of is that I keep everything in same tables but have policies which honor the user as well as tenant columns in the table. Is this possible in Postgres ? For example, when I add a policy with current_users = "column_name" ,can I add another condition where I add a check that the top level tenant name matches. But where and how is this set, similar to SET ROLE "user"
Bit confused about the right approach to use.

I would go with tenant per database. This is a little easier to backup (per tenant) and a little more secure by default. And a little easier to manage w pgAdmin.
You don't need a db user for each application user to use RLS, but it's probably a good idea.
Set db_user_namespace=true in postgresql.conf to allow per-db usernames. See http://www.postgresql.org/docs/9.5/static/runtime-config-connection.html for caveats

Related

RedShift Group Vs Roles

I am getting confused between the group and role concept in RedShift. When do we use groups and when are roles used? I was trying to understand it from typical RBAC implementation in other products, but could not match it with how RedShift has implemented it. It looks like it is continuing with PostgreSQL legacy approach
You can't have groups inheriting groups. Roles can inherit other roles. Unless you need tiered hierarchies, groups and users are easier to manage and you can get all the information you need to manage users and groups using the admin views in the amazon redshift utilities https://github.com/awslabs/amazon-redshift-utils/tree/master/src/AdminViews
In Redshift, nobody has permission to see the pg_roles tables and I still haven't found a way out to see which GRANTs are assigned to a given ROLE. Without this, administration of roles is a bit trickier in Redshift.

Postgres inherit from schema

I am initiating a new project which will be available as a SaaS for multiple customers. So, I am thinking of creating a database and then create individual schema for every customer.
I have defined some rules and the first rule is all the customers must always have the same schema. No matter what. If one customer gets an update, all the other customers will get the update as well.
For this purpose, my question is, is it possible to inherit schema from another schema in the same database? If not, do I have to manually create all the tables and indexes in the new schema and inherit them from the tables in master schema?
I am using Postgresql 9.6 but I can upgrade it as well if needed.
I open to suggestions.
Thanks in advance
There is no automated way to establish inheritance between all tables in two schemas, you'd have to do it one by one (a function can help).
However, I invite you to stop and think about your data model for a bit. How many users do you expect? If there could be many, plan differently, because databases with thousands of schemas become unwieldy (e.g. catalog lookups will become slow).
You might be better off with one schema for all users. If you are concerned with separation of the data and security, row level security might be the solution for you.

How to create a read-only user in postgres for all schema?

I am wondering if anyone knows a command to create a read-only user for all schemas and tables in a postgres DB. I have found ways to do it for specific tables and specific schemas but not across the board (we have many schemas and I would rather not run the command 60+ times). Thanks in advance
There is no simple way to do that in PostgreSQL.
What you should do is create a role that has read access to all tables (and yes, you'll have to run at least one GRANT statement per schema) and grant that role to all login users that need read access.
That way you have to do the work only once, and dropping the user becomes so much easier.

Decentralizing Database Structure

Although this question fancies PostgreSQL, it is still a general DB question.
I have always been curious about the term schema as it relates to databases. Recently, we switched over to using PostgreSQL, where that term has actual significance to the underlying database structure.
In PostgreSQL-land, the decentralized structure is as follows:
DB Server (`some-server.com:5432`)
>> Database (`fizz`)
>> Schema (`buzz`)
>> Table (`foo`)
Thus, the FQDN for table [foo] is fizz.buzz.foo.
I understand that a "database" is a logical grouping of tables. For instance, an organization might have a "domain" database where all POJOs/VOs are persisted, an "orders" database where all sales-related info is stored, and a "logging" databases where all log messages get sent for future analysis, etc.
The introduction of this "schema" construct in between the database and its tables has me very confused, and the PostgreSQL documentation is a little too heavy-handed (and lacking good examples) for a newbie such as myself to understand.
I'm wondering if anyone can give me a laymen's description of not only what this "schema" construct is within the realm of PostgreSQL (and how it relates databases to tables), but I'm wondering what it means to database structures in general.
Thanks in advance!
Think of schemas as namespaces. We can use them to logically group tables (such as a People schema). Additionally, we can assign security to that schema so we can allow certain folks to look at a Customer schema, but not an Employee schema. This allows us to have a granularity of control of security just above an object level but below the database level.
Security is probably the most important reason to use schemas, but I've seen them used for logical groupings as well. It just depends on what you need them for.
Late to the party, but ..
I use schemas to split tables in to groups that are used by different applications that share a few tables, for example.
users
application1
application2
Here, if we log in with app1, we see users + application1; if we log in to app2, we see users and application2. So our user data can be shared between both, without exposing app1 users to app2 data. It also means that a superuser can do queries across both sets of data.

Assign different roles to the same user on different databases on the same server

I've setup our postgresql server with two databases: one production and one training. I would like users to be limited to their true roles in the production database, but be given free reign in the training database.
ie.
Assign one set of roles to a user on one database, and another set of roles to the same user in a different database on the same server.
I figure one way around this would be to create a new "training" role with full access, and then limit this role to just the training database using pg_hba.conf. It's not what I'm hoping for, but is this the only option?
You can GRANT different privileges to different ROLES in different databases, but ROLES are global to the entire server. You might consider using GROUPS (prod_dba group vs dev_dba group) and then assign users to the different groups.