Which postgres system table stores a map of PIDs to session authorizations? - postgresql

I want to look further into the PIDs listed in pg_stat_activity to know what their last succesful call to SET SESSION AUTHORIZATION set their session authorization to. Which table or view do I need on PostgreSQL 9.0?

PostgreSQL doesn't expose that information, at least in 9.4 or any prior version.
The user id in pg_stat_activity is the login user; it's the user that RESET SESSION AUTHORIZATION goes back to. It won't change when you SET SESSION AUTHORIZATION or SET ROLE.
Information about the current effective session authorization and current role are internal to the backend. You can access them locally to the backend with SELECT current_user, current_role, etc, but there's no inter-process way to get at them.
It might be nice to have that, if it could be added without making it more expensive to maintain pg_stat_activity or to query it. You'd need to get into PostgreSQL's guts and develop a patch to expose the information, though.
Surprisingly, log_line_prefix doesn't seem to include format symbols to show the effective role and effective session user. Given the use of session authorization by PgBouncer that's sufficiently odd that I feel like I must have missed something.
In any case, the only way I see to do this is to dig through the logs, logging pid and session ID then associating successful SET SESSION AUTHORIZATION calls with subsequent statements.

Related

How to use Supabase RLS with third-party client library?

I'm using Supabase as my database, with RLS turned on. I query the DB from a Node backend using the postgres.js client (it could be any other JS client really). As such I'm connecting direct with the default postgres user and I issue raw SQL queries.
How can I query my DB while still maskerading as a user from Supa's auth.users table? I have triggers and RLS policies that take advantage of the current logged-in user, via Supa's auth.uid() function.
All I can find online is that I must set the current_user_id postgres setting to the current Supabase user, but I don't grasp the implications of that, from a functional and security perspective. I wouldn't want to leak the current user to another session.

How to setup row level access in Postgres without creating a user

I have an existing API connected to an AWS PostgreSQL database that uses AWS Cognito for User authentication.
The goal is for users to insert data via the API with some field mapped to their Cognito id, and retrieve the same data. The idea would be for each user to only have access to the data 'owned' by them. Similarly to the way row level access works.
But I do not want to create a role for each user which seems to be necessary.
The idea would be that I need to somehow setup a connection to the PostgreSQL DB with the user_id without creating a user and handle the accessible data via a policy, or somehow pass the data to the policy directly.
What would be an ideal way to do this, or is creating a PG user for each user a necessity for this setup?
Thanks in advance
EDIT: I am currently querying the database through my backend with custom code. But I would rather have a system where instead of writing the code myself, the PostgreSQL system handles the security itself using policies(or something similar). I fully understand how PostgreSQL row-level-access works with roles and policies and I would prefer a system where PostgreSQL does the major work without me implementing custom back-end logic and preferably not creating thousands of PostgreSQL roles for the users.
You should not allow users to make a direct connection to the database.
Instead, they should make requests to your back-end, where you have business logic that determines what each user is permitted to access. Your back-end then makes the appropriate calls to the database and returns the response to the user.
This is a much 'safer' response because it prevents users having direct access to your database and it is also a better architecture because it allows you to swap-out the database engine for another one without impacting your service.
The database is for your application, not for your users.

How to integrate Postgres RLS into backend server

I'm trying to understand backends more and using row level security seems to be great idea to simplify backend code and increase security. I struggle to understand how to make RLS work. Let's say i have the following policy
CREATE POLICY user_mod_account ON accounts USING (username = current_user)
How does it know who is 'current_user'. I've followed few tutorials for making backend servers and if i'm not mistaken the way auth works is that you have some middleware that is in charge of authentication (usually by making additional requests against db to check if session exists and is valid), but all operations on the database are performed by backend which logs in as one user.
Let's say I have two tables - user, post and post has foreign key 'author' relating to 'username' in user table. Is it possible to have the following query on backend
SELECT * FROM post
and have it protected by RLS so the data is protected by the database itself (and have it return only posts from the user that backend is making request for)? If i connect to db as 'postgres' user, is 'current_user' postgres, or is there a way to make requests from backend as selected user. Maybe it's not the purpose of RLS, i would be glad if you could point me to some sources that could help me understand database <-> backend relation better. I feel like it is not really that complicated and my brain just didn't 'click' yet :P

Roles, groups and set session authorization in postgres

I am mucking around with postgres row level security for multi tenant applications. I want achieve this via a policy which separates rows based on the tenant_name which is a column in my tables. I have roles for each tenant. However, I am maintaining a connection pool by connection via a superuser. This is so that i can have only one connection pool. Once i have a query from a tenant, i want to drop privileges to that tenant first and then execute the query.
So I connect to the database as a superuser, and then i do "set session authorization tenant_role". This sets the session_user and current_user variables. However, the problem is that this tenant user can himself do a "set session authorization some_other_tenant" and then Row security doesn't matter. I am guessing that this happens because the DB login context is the superuser.
So how do i achieve this ? Once i do "set session authorization" or "set role" to some user , that user should not be able to run the same thing again.
Thanks
You may want to read this, for your answer.
Essentially, create a no-privilege user and login to the pool via that (instead of connection pooling as a supervisor role). Once logged in, then escalate the role to the actually connected user. The URL above tells you how to do that.
What I am unable to understand is that if this is an uncontrolled environment, then even with this solution, a user can escalate to someone else's role and still play havoc. So although even if this answers the question, it may still not be what you want to eventually do!

How to find if an Oracle APEX session is expired

Short version:
If the function wwv_flow_custom_auth_std.is_session_valid (or apex_custom_auth_std.is_session_valid) returns TRUE, is it possible that the session is expired but still alive? If so, how can you check if a session is expired?
Long version:
I have created a single-sign-on system for our Oracle APEX applications, roughly based on this tutorial:
http://www.oracle.com/technology/oramag/oracle/09-may/o39security.html
The only difference is that my master SSO login is in Perl, rather than another APEX app. It sets an SSO cookie, and the app can check if it's valid with a database procedure.
I have noticed that when I arrive in the morning, the whole system doesn't work. I reload a page from the APEX app, it then sends me to the SSO page because the session was expired, I logon, and get redirected back to my original APEX app page. This usually works except first thing in the morning. It seems the APEX session is expired. In that case it seems to find the session, but then refuse to use it, and sends me back to the login page.
I've tried my best to trace the problem. The "wwv_flow_custom_auth_std.is_session_valid" function returns true, so I'm assuming the session is valid. But nothing works until I remove the APEX session cookie. Then I can log back in easily.
Anybody knows if there is another call that would tell me if the session is expired or not?
Thanks
You can set the Maximum Session length in seconds under the application security attributes page.
Apex states the following:
"The session duration may be superseded by the operation of the job that runs every eight hours which deletes sessions older than 12 hours."
You could use the view apex_040100.APEX_WORKSPACE_SESSIONS to determine if a session is valid based on its existance or creation time. eg: session_created - systdate > 12Hours.
You should also use the "On session timeout direct to this URL" attribute.
This solution would require privileged access but you can query the wwv_flow_sessions$ view in your apex schema for any session that matches your username. If none exists, your session has timed out. This view also gives you a field 'idle_timeout_on' that will tell when your session is scheduled to time out.