-
-
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
feat: get configuration parameters from the db and allow reloading config with NOTIFY #1729
Conversation
One thing that is missing is a test for reloading the config with the db settings. But it doesn't make much sense to reload with a SIGUSR2 signal. I think we should extend our NOTIFY channel to allow reloading the config from there. So, how about: -- These two for reloading the schema cache
NOTIFY pgrst;
NOTIFY pgrst, 'SIGUSR1';
-- This one for reloading the config
NOTIFY pgrst, 'SIGUSR2'; Thoughts? |
I think that was suggested / discussed somewhere else already, right? I am not sure what is currently implemented already and whether that would be any breaking change, but how about:
While we can use the signals for that too, I think it'd be easier to have some more explicit strings. We're not really sending those signals. And a string like this is easier to extend in the future. |
Awesome! :)
I think the SQL query could easily be extended to support |
A couple of config options to think about:
|
Just tested in a cloud hosted Postgres on Aiven, and as you've already discussed, it doesn't work unfortunately. I hope you find a way at some point to allow non-superusers to use the db as config. I think it would make it easier to do jwt key rotation by simply updating a config in the db. |
@wolfgangwalther Deliberate decision, and now it's on point with what LorenzHenk mentioned on #1179 (comment):
If we keep this isolated to the authenticator role, uninstalling postgrest(not that we want that) would be matter of dropping the roles + schema. I also feel that this would look better on the docs - doing an ALTER DATABASE looks more invasive(though requiring the same privileges unfortunately). Also, the ROLE approach it's more flexible, we could even remove the So that's why I think we should restrict to ROLEs only.
I like it! The strings look much better. I'll add that.
Totally agree. I'll deny changing those settings.
I think that one deserves it's own PR, it's a breaking change after all - there would be no panic when it's missing.
Same as above. It's also a bit weird to enable running postgrest when it's in a "broken state". Would need more discussion. WDYT? |
@nerfpops Thanks for reporting, too bad about Aiven. Later on we could create a postgrest extension to register the GUCs so no SUPERUSER is needed. Or we could just wait for SCHEMA VARIABLES to land on postgres as mentioned by Wolfgang on #1562 (comment). |
I'm not really convinced by this argument...
... but very much but this one! Even the current implementation doesn't need the prefix at all, you're right. Using different
I can kind of see use-cases where it would be easier to have the database option, too. But since that's easy to extend, I will come back to this, once I should really hit one of those cases. So see you in a couple of years... - ah wait, we'll have schema variables by then... :o)
Yes, absolutely fine to put those into different PRs. Just wanted to bring it up, because those are related here, too.
I think the "broken, but defined state" is better then any undefined state. Assume you're just setting up PostgreSQL and PostgREST. Most setups would probably restart PostgREST once it errors out. Assume you're initializing the database and are not creating all the roles and objects etc. in one transaction. PostgREST would kind of magically start serving the schema once the config variable is set - even though the schema might have any number of objects so far (empty, some created, all created - randomly). It'd be much better if, after setting everything up, you just |
Do we still have a config option for this? Or do we just load config options from database all the time? Not sure if there's any downside to doing so - I don't see any right now. |
I think not! I would also like removing the prefix config. I'll check it out. |
23df4d2
to
3b55d0a
Compare
Actually, one downside to load the db settings always is that it's wasteful for users that don't have superuser over their db(most of our users maybe). The query is simple, but still. Another one is that it slows down the io-tests, I'm getting a So, how about having this config: db-settings = true @wolfgangwalther WDYT? |
Hm. I'm not too concerned about performance, because it's only on reload, not while serving requests. In the context of reloading the overhead should be rather small. IO test performance is a thing however. So if we can make the default Enabling by default seems appealing to me, because the whole point of putting the config in the database is, that I want to have the least amount of config needed in my config file / docker-compose file. So instead of having this:
it would be
It's not much, but it "just works". Does that make sense? Thinking about the name of the config option. Currently we are only using the term "settings" in the context of Given that, I suggest we call it WDYT? |
I like that 👍, I've renamed the config and made it True by default. |
5ef4d83
to
b546c1f
Compare
Looking good. Suggested just a few more minor changes.
Are you going to do that in this PR? If yes, cool. If no, I suggest to still add a test for now that tests the reloading with a |
One other note: I wonder why codecov doesn't add any status checks here. The upload part says this:
@steve-chavez have you enabled codecov for you fork, too? Maybe that's causing this. It could also be circleci, that's enabled for your fork. I noticed that when you currently open a PR for the first time CircleCI has already run the pipeline in your fork and will not report anything in the PR until you trigger a rebuild somehow. I had the same thing while I had Circle enabled in my own fork. Once I disabled it, it behaved as expected again. |
Triggered a rebuild but it didn't seem to work.
Yes, I do have it enabled in my fork. It's helpful for running tests before making a PR though, so I would prefer not to disable it.
That one I could disable. I'll try it out. |
Yeah. I digged further and it seems like disabling it for the fork is in fact the only way to "solve" this. Circle not showing up when I first open the PR was annoying enough for me to do that. I'm totally fine with you keeping it enabled, though. It will eventually show up once anything changes in the PR or if we manually trigger a rebuild.
I assume it will not work. This is because we are using the tokenless-upload. Therefore the codecov upload script has to take the repo info from what it gets from CircleCI - and this is running with your fork's repo name. In this case you could try to add the postgrest repo's codecov token to your fork in CircleCI. This way, the upload script should pick up this token when running under your CircleCI user and still upload to the main repo. |
I guess that's just what I assumed:
That |
Compare this to the same from #1724. I don't have circle enabled for my fork and it shows this:
I hope setting up the codecov token in your circleci user will work. |
Let's see. I've just copied the CODECOV_TOKEN from https://app.codecov.io/gh/PostgREST/postgrest/settings to my postgrest project env vars on CircleCI. Edit: Worked! |
Sweet!
|
Enables reloading the config by doing: NOTIFY pgrst, 'reload config' Adds an alias for reloading the schema cache: NOTIFY pgrst, 'reload schema'
6ea7e92
to
0fecc50
Compare
@wolfgangwalther Ah, and there's also more security because of the switch from "set locals" to prepared statements. Perhaps we can call it something like enterprise-grade release? Not sure for now :) |
Btw, code coverage is amazing(first time user here). I see we have a badge already on the repo. But maybe we could also list it as a feature on the release since it means more quality and trust in the postgrest codebase. |
While the settings are scoped per role, they are readable by everybody that can connect to the database. |
|
||
-- reloadable config options for io tests | ||
ALTER ROLE postgrest_test_authenticator SET pgrst."jwt-aud" = 'https://example.org'; | ||
ALTER ROLE postgrest_test_authenticator SET pgrst."openapi-server-proxy-uri" = 'https://example.org/api'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while naming the settings like pgrst."openapi-server-proxy-uri"
, the alter statement works, and they are stored in the pg config tables, however, all the settings named like this can not be read using show setting
or current_setting
, and it should work under normal conditions (i bet that is why you used that semi complicated statement to get them back).
The problem here is the -
character, it it were named like pgrst.openapi_server_proxy_uri
(or maybe PGRST.OPENAPI_SERVER_PROXY_URI
like the env vars) then show
and current_setting
functions work properly and the dbSettingsStatement
statement can be a bit more clear/explicit as to what it's fetching from the database
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might not work with SHOW
, but it does work with current_setting
.
set app."test-a-b-c" = 'hello world';
select current_setting('app.test-a-b-c');
returns "hello world" for me. No problem there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PG 13.1 here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. I'm probably mis-understanding something. The same thing works for me with SHOW
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. Happens only when using ALTER ROLE ... SET
- then loading the guc on login is broken once there is a -
in it. I'd consider this a bug in Postgres.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, can reproduce as well on pg 11.5 - not even current_setting
works when the guc has a dash. I guess this should be fine for our config since we get it through pg_db_role_setting
. But not for using the guc configs through functions, which should be the case for jwt-secret
.
Not sure if we should change the dashes to underscores, looks like this is already been considered as a bug on the pg mailing list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the latest post on the mailing list, the bug seems to be that those variables are actually available with _
instead of -
already.
So for all PG versions that have the bug, SELECT current_setting('pgrst.openapi_server_proxy_uri')
should work even without changes from our side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wolfgangwalther Great! I've also confirmed this works.
Though I guess it'd be good to keep the config option names consistent. I'll change the dashes to underscores on another PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be our only way forward, too, because the consensus on the PG mailing list now is to don't allow -
in GUC names anymore.
While it might be a bug, it will be fixed only for 13+ which means postgrest will not work properly for any other version. This is not released yet so its the perfect time to switch to _ just like the env vars
… On 9 Feb 2021, at 18:39, Steve Chavez ***@***.***> wrote:
@steve-chavez commented on this pull request.
In test/fixtures/roles.sql:
> @@ -5,3 +5,32 @@ CREATE ROLE postgrest_test_default_role;
CREATE ROLE postgrest_test_author;
GRANT postgrest_test_anonymous, postgrest_test_default_role, postgrest_test_author TO :USER;
+
+-- reloadable config options for io tests
+ALTER ROLE postgrest_test_authenticator SET pgrst."jwt-aud" = 'https://example.org';
+ALTER ROLE postgrest_test_authenticator SET pgrst."openapi-server-proxy-uri" = 'https://example.org/api';
Ah, can reproduce as well on pg 11.5 - not even current_setting works when the guc has a dash. I guess this should be fine for our config since we get it through pg_db_role_setting. But not for using the guc configs through functions, which should be the case for jwt-secret.
Not sure if we should change the dashes to underscores, looks like this is already been considered as a bug on the pg mailing list.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
True. That's something the It's not a risk if you don't allow a direct SQL connection for external users though. Which I think it's the case for most PostgREST users. |
the |
I think this would be enough for protecting the setttings: -- don't allow reading the settings for every role
REVOKE SELECT ON pg_catalog.pg_db_role_setting FROM public;
-- explicitly allow the authenticator to read the settings
GRANT SELECT ON pg_catalog.pg_db_role_setting TO authenticator; Then every non-SUPERUSER role that connects to the db cannot read from The above would have to be done for every postgrest-enabled database. |
So In my current project, I don't know the name of the database in advance (could be development, staging, ...) and there is nothing like We could probably read both the settings for the current database and the settings for all databases at the same time from WDYT? |
Sounds cool. I haven't tested it - does |
Looking at the test-cases in here a bit more closely, I guess my problem is somewhere else. Still.. looking at the code I wonder what happens when somebody sets both And the query seems to assume that all settings in |
Oh, that shouldn't be the case. According to tests: postgrest/test/fixtures/roles.sql Lines 10 to 15 in 0ddd676
I definitely intended for the ROLE guc settings to be global - all databases. I didn't know this was only being applied for the current db, I'll check it out.
If the An error ocurred when trying to query database settings for the config parameters:
SessionError (QueryError "\n with\n role_setting as (\n select unnest(setconfig) as setting from pg_catalog.pg_db_role_setting where setrole = current_user::regrole::oid\n ),\n kv_settings as (\n select split_part(setting, '=', 1) as key, split_part(setting, '=', 2) as value from role_setting\n )\n select replace(key, 'pgrst.', '') as key, value from kv_settings where key like 'pgrst.%';\n " [] (ResultError (ServerError "42501" "permission denied for table pg_db_role_setting" Nothing Nothing)))
Attempting to connect to the database...
Listening on port 3000
Connection successful
Schema cache loaded So postgrest still starts as usual, but it cannot get the guc settings from the db, and it sticks to the config file settings. If the |
Not sure whether there is a mis-understanding. The problem is this:
When postgrest (connected to database A) reads
Definitely a mis-understanding. I wanted to know if everything still works correctly after create role alice login;
alter role alice set a.b to 'c';
revoke select on pg_catalog.pg_db_role_setting from public; Is it still possible to login as user alice without error? I just tested it and it still works. |
And another problem with loading the config: I have a docker setup with one container for the database and one container for postgrest. When I launch both containers at the same time ( This is the postgrest output:
What's basically missing is a Should we reload the config whenever the connection is re-tried? And possibly the schema cache, too? (If not already the case) |
Summarizing a TODO list from all the points above, so we're not missing anything:
|
Working this on #1760.
I went with underscore - |
Feature
For #1562. Allows configuring postgrest from the db by setting config options on the connection role. For example:
That will set the
jwt-secret
config option accordingly.SUPERUSER privileges are required for ALTERing role settings(see #1562 (comment)), so this might not work on some cloud-managed databases.
Config options can only be set on
ALTER ROLE .. SET ..
and notALTER DATABASE .. SET
. Though the same privileges are required(SUPERUSER), ROLE level settings are better because they're scoped to ourauthenticator
role.