nixos/postgresql: add ensureRoles option to ensureUsers#252071
nixos/postgresql: add ensureRoles option to ensureUsers#252071vs49688 wants to merge 1 commit intoNixOS:masterfrom
Conversation
|
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/prs-ready-for-review/3032/2608 |
|
Yes, I believe the
Kind of? No permissions are copied per se, it's just effectively saying "this user/role inherits everything of this other role".
It's the same deal for
|
For an ensure option, I wholeheartedly agree, but the issue has been raised that ensure-style options cause stale state, so we may do well to avoid ensure-style options in the first place, and go for a solution where the declared state is managed entirely, consistently by NixOS. Whether ensure is good enough may be subjective, so I don't think it's a deal breaker. Could you add this to the test suite? |
I agree it's a bit iffy and does cause stale state under some circumstances - but what's the alternative? Short of doing some hackage such as with dumping all the existing roles/users at re-build time and comparing them to what's there (which, in turn has its own state issues), I don't really see a nicer way.
Can do.
What if I rename |
I just had a thought on this - we (NixOS) explicitly create a database (e.g. |
We should stick to upstream terminology, so I'd be in favor of such a change.
When I scanned the docs for this feature, there wasn't a term that jumped out, to name this relation, but I'm sure they've named it somewhere. Ideally we use a name they already use, even if the name isn't documented (and not terrible, because then they might change it or document it differently later). Maybe it shows in postgres' internal schema; something like
Yeah, I think it should look like that, although we could possibly improve it by taking it in either of two directions:
|
👍
Postgres uses Looking at https://www.postgresql.org/docs/current/role-membership.html, there's "role membership", "group role", and "member roles". Some options: services.postgresql.ensureRoles = [ # Changed from ensureUsers
{ name = "backup"; ensureRoles = [ "pg_read_all_data" ]; }
{ name = "backup"; memberOf = [ "pg_read_all_data" ]; }
{ name = "backup"; memberships = [ "pg_read_all_data" ]; }
{ name = "backup"; groups = [ "pg_read_all_data" ]; }
{ name = "backup"; ensureGroups = [ "pg_read_all_data" ]; }
{ name = "backup"; additionalRoles = [ "pg_read_all_data" ]; }
{ name = "backup"; ensureAdditionalRoles = [ "pg_read_all_data" ]; }
];
All definitely outside the scope of this PR, but both options are worth looking into. |
Broadly the choice seems to be between just "role", "group" and "member".
I think it'd be good to highlight that we're still only ever adding to the memberships, by repeating |
|
I just started attacking this - turns out there is a difference between a user and a role. Users have the |
| userRoles = concatStringsSep "," user.ensureRoles; | ||
| in '' | ||
| $PSQL -tAc 'GRANT "${userRoles}" TO "${user.name}"' | ||
| '') (filter (user: length user.ensureRoles != 0) cfg.ensureUsers); |
There was a problem hiding this comment.
AFAIU GRANTs aren't dropped here when removed from the configuration, right?
I'm not sure if there's a reasonable way to implement that, but if not then it should be warned about this behavior in at least the option's description.
There was a problem hiding this comment.
AFAIU GRANTs aren't dropped here when removed from the configuration, right?
Correct.
I'm not sure if there's a reasonable way to implement that, but if not then it should be warned about this behavior in at least the option's description.
There's not, we're dealing with an inherently stateful system. Nix can only do so much in that regard.
I had planned to add it to the description, I just wanted to nail down what we actually want with this PR before I continued.
Indeed, I planned to add one once I'd finished the rest.
Btw, do you have an opinion/preference on this? I never received a response, which is why I stopped working on this PR. |
I think I prefer |
|
I agree with @roberth's suggestion about a state management solution in the longterm, however
so we'll need a solution. Unless we go for a full revert this is IMHO the most reasonable solution[1] as it doesn't expand on the problematic
Just to be clear, you mean the way it's currently implemented in this PR, correct? If yes, I agree. Inventing our own names means that everyone has to map the NixOS names onto the Postgres names when reading upstream docs and that seems like a very bad idea. And [1] Though an even simpler solution would be to unconditionally add the CREATE permission to restore the pre-15 behavior. |
|
Yes, I agree with you Ma27.
Le lun. 23 oct. 2023, 22:02, Maximilian Bosch ***@***.***> a
écrit :
… I agree with @roberth <https://github.com/roberth>'s suggestion about a
state management solution in the longterm, however
- ensureUsers is broken for quite a bunch of services apparently on
master
- a new NixOS release is knocking on the door
so we'll need a solution.
Unless we go for a full revert this is IMHO the most reasonable
solution[1] as it doesn't expand on the problematic ensure* approach.
I think I prefer ensureUsers and ensureRoles separated, DBA PGSQL people
knows what it means and how it differs, also it's synced with upstream docs.
Just to be clear, you mean the way it's currently implemented in this PR,
correct? If yes, I agree.
Inventing our own names means that everyone has to map the NixOS names
onto the Postgres names when reading upstream docs and that seems like a
very bad idea. And roles is the correct term for what we want to do now.
Finally, I wouldn't want to bikeshed ensureUsers and block this PR on
that now (and in the future the time is probably better invested into
alternatives).
[1] Though an even simpler solution would be to unconditionally add the
CREATE permission to restore the pre-15 behavior.
—
Reply to this email directly, view it on GitHub
<#252071 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACMZRDLNCJ64EHZWJS5VALYA3LPPAVCNFSM6AAAAAA4CINM5OVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONZWGAYTMMZSG4>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
|
Okay I've had a look at some of the issues on master, and now I'm a bit confused (granted it is very late, so I'm looking at this through sleepy eyes). PG15 doesn't add the This PR adds (Unless you're abusing the syntax with |
Excellent point. I am travelling ATM, I don't have PGSQL docs but this only hints to me that ensureRoles can do more and should have a more general name? |
This is a good point. I guess I was too focused on the user vs role thing that I missed we have a third entity that's relevant here, permissions 🤦 That's kinda embarassing and I'm very sorry for that. Also unless I'm missing something that wouldn't even be sufficient, you'd have to commit crimes like This means that
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index 2d4ef0563182..f3fbabfab5a0 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -559,7 +559,10 @@ in
let
userPermissions = concatStringsSep "\n"
(mapAttrsToList
- (database: permission: ''$PSQL -tAc 'GRANT ${permission} ON ${database} TO "${user.name}"' '')
+ (database: permission: ''
+ $PSQL -tAc 'GRANT ${permission} ON ${database} TO "${user.name}"'
+ $PSQL -U postgres -d wiki -tAc 'GRANT CREATE ON SCHEMA public TO "${user.name}"'
+ '')
user.ensurePermissions
); though we'd need a way to determine the database here properly (I hardcoded it to fix the |
|
Yeah, then I'm not sure what the immediate path forward is here. Unfortunately, I have neither the time nor the patience to come up with a proper solution, getting it reviewed (potentially months), dealing with the inevitable bikeshedding, etc. I'm using this as a standalone module as it solves an actual problem I had (a backup user needing access to everything). Standalone module, for reference: { config, lib, ... }: {
options.services.postgresql.ensureUsers = with lib; mkOption {
type = types.listOf (types.submodule {
options = {
ensureRoles = mkOption {
type = types.listOf types.str;
default = [];
description = lib.mdDoc ''
Roles to ensure for the user, specified as a list of strings.
For more information on how to specify the role, see the
[GRANT syntax](https://www.postgresql.org/docs/current/sql-grant.html).
The attributes are used as `GRANT ''${role}.
'';
example = literalExpression ''
[
"pg_read_all_data"
"pg_write_all_data"
]
'';
};
};
});
};
config = {
systemd.services.postgresql.postStart = lib.concatMapStrings (user: let
userRoles = lib.concatStringsSep "," user.ensureRoles;
in ''
$PSQL -tAc 'GRANT "${userRoles}" TO "${user.name}"'
''
) (lib.filter (user: lib.length user.ensureRoles != 0) config.services.postgresql.ensureUsers);
};
} |
It's unfortunate because as we are running this immediate PostgreSQL 15 problem, us, contributors, were examining your solution as the most promising one for expedited review and merge. But it's fair. |
I was probably a bit harsh, I apologise. I was just agitated. As far as I understood, this solution can't be used to fix the pg15 problem in an elegant way, which is why I closed it. |
Description of changes
Adds an
ensureRolesoption toservices.postgresql.ensureUsers. Mostly useful to for granting the new predefined roles in Postgres 14.Use like so:
Fixes #204189.
Things done
sandbox = trueset innix.conf? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/)