Reconcile Role resources with a non-superuser admin such as the master user of managed PostgreSQL cloud services - #71
Open
ThoSap wants to merge 7 commits into
Open
Conversation
…ter user of managed PostgreSQL cloud services
…` status The catch block around the HMAC computation also caught every error from the load of the key Secret, such as a 403 from the Kubernetes API, and reported it as "HmacSHA256 not available". The key is now loaded before the try block, and the catch covers only the two checked exceptions of the HMAC API. The new test covers the creation of the key Secret with a 32 byte key, the reuse of an existing key by a second operator process, a new key after the Secret is lost, the error for a Secret without the `key` entry, and the exact HMAC construction that existing `Role` statuses depend on.
…atabase commit The fingerprint was written to the status inside the transaction. When the commit failed, the error handler still patched the status with the new fingerprint, and the next reconcile saw no password change. The fingerprint and the server password are now computed before the transaction, and the status receives the fingerprint after the transaction returns. The new test covers the state of every `Role` after the upgrade to the version that introduced the fingerprint. It changes the password in PostgreSQL, removes the fingerprint from the status, and asserts that the Secret password is applied once and left alone afterwards.
…amespace The `create` verb was part of the ClusterRole of the `Role` controller, which allowed the operator to create Secrets in every namespace. It is only needed for the password fingerprint key Secret in the operator namespace. The Quarkus Kubernetes extension now generates a namespaced Role and RoleBinding for it. The default RoleBinding to the `view` ClusterRole is kept explicitly, because configured role bindings replace it.
The flag test now covers `superuser`, `replication`, and `bypassrls`. Two tests run `passwordEncryption: server` and a pre-hashed SCRAM-SHA-256 verifier under the non-superuser admin.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #70
The Role controller failed on AWS RDS with
permission denied for table pg_authid.The same happens on every managed PostgreSQL service and on any vanilla PostgreSQL where the admin/management user is usually not a superuser, not do the cloud offerings support crating a superuser.
This PR makes the Role controller work with an admin role that has only
LOGIN,CREATEDB, andCREATEROLE.What changed
pg_rolesinstead ofpg_authid. Role state and membership come from the public viewpg_rolesand the public catalogpg_auth_members.pg_authidstays in the generated jOOQ sources for the test helper only.ALTER ROLEnames only the options that differ from the current state. PostgreSQL rejectsNOSUPERUSER,NOREPLICATION, andNOBYPASSRLSfrom a non-superuser even when the value does not change, so the previous full statement failed on every update of an existing role.pg_authidcannot be read without superuser rights. The operator now stores an HMAC-SHA256 of the Secret password instatus.passwordFingerprintand compares against it on each reconcile. The key is random and lives in a Secret in the operator namespace (postgresql-operator.password-fingerprint.secret-name). A reader of the Role status learns nothing about the password without that key. The RBAC rule for secrets gainscreatefor this one Secret.passwordEncryption: serveropts out for MD5-only clients. CloudNativePG does the same since v1.29.2.RoleReconcilerNonSuperuserTestruns the controller with aLOGIN CREATEDB CREATEROLEadmin. It covers create, update, password rotation, login toggle, membership, drop, and the error path forsuperuser: true.Documented consequences
docs/cluster-connection.md.superuser,replication, orbypassrls.ADMIN OPTION.credcheckor the Cloud SQL password policy.Verification against a non-superuser admin
Run on PostgreSQL 15 and 18 as
LOGIN NOSUPERUSER CREATEDB CREATEROLE, which mirrors the master user of the managed services.SELECTonpg_authidSELECTonpg_shadowSELECTonpg_roles, all flag columnsSELECTonpg_auth_membersshobj_description(oid, 'pg_authid')with the oid frompg_rolesbuildAlterRolestatementALTER ROLE ... NOSUPERUSER/NOREPLICATION/NOBYPASSRLSaloneALTER ROLEwith login, password, createdb, createrole, inherit, connection limit, valid untilGRANT/REVOKEmembership on a role the admin createdALTER ROLE ... PASSWORD '<SCRAM verifier>'Managed PostgreSQL offerings
pg_authidrds_superusercloudsqlsuperuser,alloydbsuperusercloudsql.pg_authid_select_rolecan grant itazure_pg_adminneon_superuserpostgrespostgresThe change works on all of them, because it uses only public catalogs and never names superuser-only options without a change.
Tests
javac -Xlintsettings of Replace Checkstyle with Error Prone #66 and Enable thejavac -Xlintcategories that Error Prone cannot see #67.