Extremely safe Postgres permissioning - sql

Let's say that I have four tables in my Postgres database, two of which are private and contain highly sensitive information (private1 and private2), and two that contain information I want to allow anyone in the world to be able to query arbitrarily (public1 and public2). I'm aware that this is a very poor design, but bear with me.
I want to set up a user that can solely run SELECTs on the two public tables, but can in no way do anything else even remotely malicious with the other two tables (or the database more generally).
My naive approach would be to do something like set up a new user public_querier, run a REVOKE ALL ON private1, private2, public1, public2 FROM public_querier; and then a GRANT SELECT ON public1, public2 TO public_querier;.
My sneaking suspicion is that this does not fulfill my security desideratum because of some subtleties that I don't have knowledge of, and I'd greatly appreciate a spot check on that suspicion.
Cheers!

You can only revoke permissions that were previously granted.
Use \z table_name in psql to examine the permissions.
If you see nothing, the table has the default permissions: only the table owner can access it.
In that case, grant SELECT to the public tables to the role and do nothing about the private tables.
If there are already permissions granted on the private tables, revoke them as desired.

Related

Unable to select all rows of information_schema.triggers

I have two kinds of users in my Postgres database. One has access to everything in the database and has admin access. The other kind has SELECT access on public schema and USAGE access on information_schema.
When I run the following query, the second kind of user sees only a subset of all results which the first kind of user can see.
SELECT action_statement, event_object_table
FROM information_schema.triggers;
I am not able to understand what could be happening here. Triggers on the table from same public schema are present, but miraculously some triggers are missing for other tables in the same public schema.

EXECUTE permission not sufficient to use Stored Procedure. Also have to give SELECT permissions on underlying objects. Why?

I have a Stored Procedure in Database A, that references 3 tables in Database B. Both Databases are on Server 1.
I gave the user:
public permission on Server 1
EXECUTE permissions on the Stored Procedure in Database A
An entry with no permissions on Database B
However, this isn't sufficient. I end up having to assign SELECT permissions to the user, for the 3 tables in Database B (plus SELECT permissions on the schema). Then things work - but why is that necessary?
Per Microsoft, this shouldn't be the case:
"Stored procedures take advantage of ownership chaining to provide access to data so that users do not need to have explicit permission to access database objects."
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/managing-permissions-with-stored-procedures-in-sql-server
Googling, I see this concept confirmed.
This is my first time assigning permissions to anyone though, so obviously I'm missing something and/or misunderstanding.
Edit: "Permissions only chain within a single database." That explains it!
"Permissions only chain within a single database." per comment from Larnu. That explains it.

How can I insert records into Postgres with RLS when user has `grant all` perms and a loose policy

I'm new to Postgres' RLS feature. I believe I'm following the documentation appropriately, but am getting unexpected behavior. Consider the following case:
i have a table named report_files
this table has a simple policy, policy <name> for all using (true)
the user has grant all permissions on the table (grant all on all tables in schema testing to testuser;, along with grant execute on all functions ... and grant usage for the schema as well)
the user can now read all fields in the table, but cannot insert records, against expectation
Here's a really short snippet from psql demonstrating the aforementioned: https://gist.github.com/cdaringe/85dd9a7b1278afe4770869dc494216f3
I have set a permissive policy, which clearly evaluates OK as evidenced by the successful select command.
What can I troubleshoot to get the insert to work?
Thanks!
ERROR: permission denied for sequence report_files_id_seq
It looks to me like you need to grant your user permission to use the id sequence: report_files_id_seq
You should be able to do this with the following
GRANT USAGE, SELECT ON SEQUENCE report_files_id_seq TO testuser;
Or to bulk add all tables:
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA <insert schema name here>
ALL is equivalent to USAGE, SELECT, UPDATE
As I cannot comment yet, I will add some input as an answer if anyone arrives on this thread like me today.
Yes, you have to grant permissions on sequence(s) separately, in addition to the privileges already granted on the table(s). In fact it is what you have to do.
Even if your table is dependant on the sequence object, they are both different objects from the RDBMS point of view, so they require distinct privileges.
As for your indices example, index in a sub-object of a table, and no additional privilege is required to be able to make use of indices so no further action than the index creation is needed.
Moreover, be careful to prefix the sequence name in case it is stored in a schema which is not the default one (public) and which is not in your search_path.
If that is not the case, you may encounter a permission denied error even though you have all necessary privilege on the sequence you aim to work with.

Hide databases in Amazon Redshift cluster from certain users

Is it possible to hide the existence of and access to databases (incl. their schemas, tables etc) from certain users within Amazon Redshift.
By default, it seems like every user is able to see other DBs even though he doesnt have permission to select data nor any other (non-default) privileges.
I tried
REVOKE ALL PRIVILEGES ON DATABASE testdb FROM testdbuser;
and similar but still testdbuser can connect to the testdb DB and even see all other objects in his object browser in a SQL tool (here: Aginity Redshift Workbench).
Ideally, testdbuser would not be able to see anything else except what he got explicitly granted access to.
Note, testdbuser is not a superuser.
Thanks!
Try to revoke from the PUBLIC group vs the specific user
REVOKE USAGE ON SCHEMA information_schema FROM PUBLIC;
REVOKE USAGE ON SCHEMA pg_catalog FROM PUBLIC; -- This should suffice, but...
REVOKE SELECT ON TABLE pg_catalog.pg_database FROM PUBLIC; -- just to be sure.
Note that this could have an undesirable effect on all users within the selected database.
You will need to do this on all databases, since the user can guess another database name and see pg_catalog information there.
The user could still find all the databases via a brute force attack simply by trying to switch or connect to all possible strings.
Unfortunately it is not possible today. Redshift does not support the REVOKE CONNECT FROM DATABASE command, so users can connect to any database.
Because Redshift is built on PostgreSQL, once connected, users can read a list of all databases in the cluster from the system tables, and by connecting to each database can read the list of schemas, tables, and even table columns from the system tables, even if they are prevented from reading the data within those tables through the use of REVOKE ... FROM SCHEMA or REVOKE ... FROM TABLE.

Oracle: control access to data through views?

I have a problem with controling access to data in a database. The data is a mix of price-data from my company and price-data bought from a data-provider and since they charge per user who can access their data I need to be able to limit the access to data.
I have a scheme "DATA" which holds all price-data. I am thinking having 2 additional schemes (example: LIM_ACCESS and FULL_ACCESS) with VIEWS that is build on the DATA-scheme. example:
CREATE VIEW LIM_ACCESS.V_PRICES AS<br>
SELECT [] FROM DATA.PRICES<br>
WHERE SOURCE = [MyCompany]
CREATE VIEW FULL_ACCESS.V_PRICES AS<br>
SELECT [] FROM DATA.PRICES
But to my experience then the LIM_ACCESS- and FULL_ACCESS-schemes has to have select-privelige on the DATA-tables to create the views and then I am back to square 1.
Being a novice in databases I feel there must be a relative simple solution to this so any advice or hint(if this question has been asked and answered before) is appreciated :-)
Kind Regards,
Svend
You can put all the views in your DATA schema. Then GRANT SELECT on them to other schemas as necessary, ideally via database roles as Woot4Moo suggested.
The use of a view will not prevent a subset of users from accessing the data. What you need to do is implement row level security.
Another approach is to use some form of role based permissions, that enable only the specific group of users you want to access the "paid" information. This can be done fairly trivially example follows.
create user foo
identified by password;
--no permissions
create role paid_data;
--grant privileges here for the paid_data role
grant paid_data to foo
User foo will now have the permissions that the paid_data role has. The advantage of using roles like this is that you can quickly revoke everyone's access that is in that group / add more accesses as they need to be incorporated.
As GriffeyDog suggested, this is the best way to do it. First create two views in your schema and then grant select on those views to the two users.
CREATE VIEW LIM_ACCESS_V_PRICES AS<br>
SELECT [] FROM DATA.PRICES<br>
WHERE SOURCE = [MyCompany];
GRANT SELECT ON LIM_ACCESS_V_PRICES TO LIM_ACCESS;
CREATE VIEW FULL_ACCESS_V_PRICES AS<br>
SELECT [] FROM DATA.PRICES;
GRANT SELECT ON FULL_ACCESS_V_PRICES TO FULL_ACCESS;
Another approach is to use Oracle Row Level Security otherwise known as Oracle Label Security. I've used this to greatly simplify my application design while ensuring users only see the data they're allowed to see.