Re: Non-superuser subscription owners
Robert Haas <robertmhaas@gmail.com>
From: Robert Haas <robertmhaas@gmail.com>
To: Jeff Davis <pgsql@j-davis.com>
Cc: Andres Freund <andres@anarazel.de>,
Mark Dilger <mark.dilger@enterprisedb.com>, Amit Kapila <amit.kapila16@gmail.com>, Andrew Dunstan <andrew@dunslane.net>, PostgreSQL-development <pgsql-hackers@postgresql.org>
Date: 2023-02-27T15:45:06Z
Lists: pgsql-hackers
On Wed, Feb 22, 2023 at 12:18 PM Jeff Davis <pgsql@j-davis.com> wrote: > There are two questions: > > 1. Is the security situation with logical replication bad? Yes. You > nicely summarized just how bad. > > 2. Is it the same situation as accessing a table owned by a user you > don't absolutely trust? > > Regardless of how the second question is answered, it won't diminish > your point that logical replication is in a bad state. If another > situation is also bad, we should fix that too. Well said. > So I don't think "shouldn't" is quite good enough. In the first place, > the user needs to know that the risk exists. Second, what if they > actually do want to access a table owned by someone else for whatever > reason -- how do they do that safely? Good question. I don't think we currently have a good answer. > I can't resist mentioning that these are all SECURITY INVOKER problems. > SECURITY INVOKER is insecure unless the invoker absolutely trusts the > definer, and that only really makes sense if the definer is a superuser > (or something very close). That's why we keep adding exceptions with > SECURITY_RESTRICTED_OPERATION, which is really just a way to silently > ignore the SECURITY INVOKER label and use SECURITY DEFINER instead. That's an interesting way to look at it. I think there are perhaps two different possible perspectives here. One possibility is to take the view that you've adopted here, and blame it on SECURITY INVOKER. The other possibility, at least as I see it, is to blame it on the fact that we have so many places to attach executable code to tables and very few ways for people using those tables to limit their exposure to such code. Suppose Alice owns a table and attaches a trigger to it. If Bob inserts into that table, I think we have to run the trigger, because Alice is entitled to assume that, for example, any BEFORE triggers she might have defined that block certain kinds of inserts are actually going to block those inserts; any constraints that she has applied to the table are going to be enforced against all new rows; and any default expressions she supplies are actually going to work. I think Bob has to be OK with those things too; otherwise, he just shouldn't insert anything into the table. But Bob doesn't have to be OK with Alice's code changing the session state, or executing DML or DDL with his permissions. I wonder if that's where we should be trying to insert restrictions here. Right now, we think of SECURITY_RESTRICTED_OPERATION as a way to prevent a function or procedure that runs under a different user ID than the session user from poisoning the session state. But I'm thinking that maybe the problem isn't really with code running under a different user ID. It's with running code *provided by* a different user ID. Maybe we should stop thinking about the security context as something that you set when you switch to running as a different user ID, and start thinking about it as something that needs to be set based on the relationship between the user that provided the code and the session user. If they're not the same, some restrictions are probably appropriate, except I think in the case where the user who provided the code can become the session user anyway. > Another option is having some kind SECURITY NONE that would run the > code as a very limited-privilege user that can basically only access > the catalog. That would be useful for running default expressions and > the like without the definer or invoker needing to be careful. This might be possible, but I have some doubts about how difficult it would be to get all the details right. We'd need to make sure that this limited-privilege user couldn't ever create a table, or own one, or be granted any privileges to do anything other than the minimal set of things it's supposed to be able to do, or poison the session state, etc. And it would have weird results like current_user returning the name of the limited-privilege user rather than any of the users involved in the operation. Maybe that's all OK, but I find it more appealing to try to think about what kinds of operations can be performed in what contexts than to invent entirely new users. -- Robert Haas EDB: http://www.enterprisedb.com
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Fix possible crash in tablesync worker.
- b5c517379a40 16.0 landed
-
Display 'password_required' option for \dRs+ command.
- 19e65dff38bd 16.0 landed
-
Restart the apply worker if the 'password_required' option is changed.
- c1cc4e688b60 16.0 landed
-
Fix possible logical replication crash.
- e7e7da2f8d57 16.0 landed
-
Add new predefined role pg_create_subscription.
- c3afe8cf5a1e 16.0 landed
-
Expand AclMode to 64 bits
- 7b378237aa80 16.0 cited
-
More cleanup of a2ab9c06ea.
- 96a6f11c0625 15.0 landed
-
Respect permissions within logical replication.
- a2ab9c06ea15 15.0 landed
-
Improve table locking behavior in the face of current DDL.
- 2ad36c4e44c8 9.2.0 cited