-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
In-Database Configuration #1562
Comments
@wolfgangwalther |
@dwagin I see your point. You could still use the current However, the problem will come up again with the pg_postgrest SQL extension. Since those postgrest instances can run different versions of postgrest, the pg extension would have to be installed multiple times in different versions. To be able to do this, we would need a non-reloadable config option |
The schema variables proposal is really interesting. Nice to see it keeps progressing.
I'm unsure of how to do that with Hasql. The I guess it should be possible to attach the session vars to each connection in the Hasql pool, but not sure if that's supported(maybe we need to patch upstream). To keep it simple in the meantime, we could just get the db settings done with
Yeah, prefix in the config could be like:
And then we'd get the settings from:
|
Just learned about the pg_db_role_setting, with that we can query the database settings. When doing So we could query @wolfgangwalther What do you think about implemeting this just for the |
Let's make that
This is in fact great!
So config file values would take precedence over database settings. This doesn't make sense. A better order, including environment variables (#1624):
So, the config file is loaded first - this is the base. Environment variables can override those settings. Only with those two, the "restart-needed" settings can be set. Once those are set, the database connection can be made and the settings can be queried from No Settings should probably be loaded whenever the schema cache is reloaded, but in advance of that. New settings might change the queries we need to make (think
Ah, I think this can solve two problems:
Yes, that sounds like a plan! |
@wolfgangwalther How about if for dynamic configuration we (ab?)use our NOTIFY channel. Similarly to your idea, we start from the config file as the base but then allow modifying it with a NOTIFY payload: NOTIFY pgrst, '{ "db-schemas" : "v1, v2, v3", "jwt-secret": "reallyreally.." }'; That one would trigger a SIGUSR2 automatically. Good thing is that would work without The only issue I see is: How to check what's the current config after many NOTIFYs? Printing them on the logs doesn't seem appropriate. The other thing that occurs to me is to have another command that NOTIFYes on another channel: -- users sends
NOTIFY pgrst, '{ "command": "--dump-config" }';
-- postgrest listens and then also notifies on another channel with
NOTIFY pgrst_reply, 'full --dump-config here';
-- clients gets the reply on
LISTEN pgrst_reply;
Asynchronous notification "pgrst" with payload "{"jwt-secret": "reallyreally..", "db-schemas": "v1,v2,v3"}" received from server process with PID 7352.
-- I think we would not surpass the payload limit of 8k since our config is small Perhaps it's too complicated, but I'm not seeing better options for now. WDYT? |
For me, the "In-Database configuration" is not dynamic. Maybe I just mis-understand "dynamic" here, though. Is your suggestion an extension on top of mine or an alternative?
The need for high privileges for
I'm not sure what problem is solved with that. Back to my question above: If this was an alternative to my revised suggestion here, then I would see better options... namely my revised suggestion :D. What problems do you see with it? If this was an extension to my revised suggestion.. I don't see the use-case yet. Why do I need to change configuration settings dynamically, i.e. non-persistent? |
@wolfgangwalther Right, that was a bad idea. I wanted to avoid the ALTER DATABASE because it's not possible on cloud providers. But as you mention it's important because it requires high privileges and it's also persistent. So I think it's all set for experimenting with an alter db implementation. I'll do that and come back with feedback. |
Is |
@wolfgangwalther Yes, AFAICT google cloud sql and aws rds allow ALTER ROLE.
Perfect! That pretty much solves it. |
One note here. According to pg docs:
That's not true for changing placeholder GUCs though.
If the role has SUPERUSER, then that works as usual. Freenode chat log(trimmed)RhodiumToad | only a superuser can set a _placeholder_ GUC on a role RhodiumToad | for real GUCs created by actual modules, the permissions of the real GUC apply RhodiumToad | but one of the restrictions of abusing placeholder GUCs for application variables is that only the superuser | can set per-role or per-db values RhodiumToad | a placeholder is a name of the form x.y that hasn't been declared using DefineCustomVariable RhodiumToad | the significance of it being a placeholder is that the db doesn't know what permissions checks would apply to | setting an actual value for it. |
That's really inconsistent :/. If placeholder GUCs can only be set by superusers because of security concerns - why can we set them easily with
It doesn't seem to hard to set up an extension that registers those GUCS. Here's an example from But that would hardly help, because custom extensions are not possible with cloud providers either, right? |
Yeah :/. The worse part is that AWS RDS doesn't let creating a role with the So this makes our ALTER ROLE solution incompatible with cloud providers. It's still good for self-hosted though.
That's true, but with enough usage cloud providers could(potentially) include our extension. Registering the GUCs looks interesting, perhaps that can be part of postgrest-contrib. |
@dwagin FYI, now we're planning to use ALTER ROLE on the authenticator role instead, like this: ALTER ROLE postgrest_test_authenticator SET pgrst."jwt-secret" = 'REALLYREALLYREALLYREALLYVERYSAFE';
ALTER ROLE postgrest_test_authenticator SET pgrst."db-schemas" = 'test, tenant1, tenant2'; So with that you could use the same db for multiple APIs, by creating different authenticator ROLEs(with their own config options) for other postgrest instances. Would that work for you? |
@wolfgangwalther Without the prefix config, that might be possible now(since the GUCs are defined statically).
DigitalOcean did tutorials for us before, once we do our postgrest-contrib extension, we could ask them to include it on their managed db. That would be a start. |
Implemented in #1729 |
This is a suggestion for in-database configuration, based on ideas in #1429 and #1559 (comment).
Currently, all configuration is done file-based in
postgrest.conf
. After the recent addition of #1544, reloading the config on the fly is now possible. Not sure whether this is already possible withNOTIFY
as mentioned in #1542. As mentioned in #1544 this reloads only part of the config, while other parts (like database connection info) need a restart of the server.The downside of the current implementation is, that we don't have a single source of truth for everything set in the config file, that e.g. references database objects. Stuff like:
db-schema
needs to be adjusted together with the schema created/dropped (multi-tenancy Feature Request Configure to Exclude Schemas #1521)pre-request
needs to be set to the corresponding functionjwt-secret
is often copied asapp.settings.jwt-secret
or something like thatIt would be much nicer, if we could (optionally) have the whole reloadable configuration in the database as well.
Using local, session and database variables
We are already using local variables (
SET LOCAL
) to set some values per transaction (request.*
,response.*
,app.settings.*
). We can extend this to use session and database variables as well and add all the reloadable config options as follows:Use
ALTER DATABASE xyz SET pgrst.db_schema='public';
to set config options, just like in the currentpostgrest.conf
.For backwards compatibility: Keep a copy of the config file
postgrest.conf
in memory and add the reloadable parts to each session withSET SESSION
. Those will overwrite the database variables automatically. (This will also support use-cases whereALTER DATABASE
permissions are not available).Query all those config variables when updating the schema cache. Since the
SET SESSION
will have been executed for this session as well, this will result in the currently active config, with both in-database and file-based merged together. Use this config from the schema cache for operation.For each request, add the
request.*
andresponse.*
variables asSET LOCAL
like we do already.This would allow us to:
use only one variable for the jwt secret, instead of two
do stuff like this:
Note: When changing database variables, those are only in effect for new sessions. That means, we would need to recreate all existing sessions when reloading the schema cache.
Extensibility
If we were to implement the pg_postgrest SQL extension to move parts of the code to the database as mentioned in #1511 (comment), we could add a function to set all those variables like this:
Instead of calling
SET
manually, we would then make the call to this function to set the reloadable config options on aSESSION
level and to set the request variables on aLOCAL
level.This would allow overriding this function. By overriding this with a custom implementation, users could make use of version specific features for new PostgreSQL versions, while we still support all of them. When schema variables are finally available, this will allow great stuff like:
Now the
jwt_secret
would be available in the database for token creation, but it would only be readable by thecreate_token
function - and not by any sql-injected* request or something like this.* not that this should even be possible... but still ;)
The text was updated successfully, but these errors were encountered: