Skip to content

fix(rbac): preserve specific connection grants when granting All Connections#319

Open
dpage wants to merge 1 commit into
mainfrom
fix/issue-302-preserve-conn-grants
Open

fix(rbac): preserve specific connection grants when granting All Connections#319
dpage wants to merge 1 commit into
mainfrom
fix/issue-302-preserve-conn-grants

Conversation

@dpage

@dpage dpage commented Jun 30, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes READ/WRITE permissions lost when specifying ALL CONNECTIONS / READ #302: a group with specific per-connection grants (e.g. READ on one connection, READ/WRITE on another) silently lost the READ/WRITE when an operator added an "All Connections / READ" grant.
  • Root cause was server-side: AuthStore.GrantConnectionPrivilege ran a destructive DELETE FROM connection_privileges WHERE group_id = ? AND connection_id != 0 whenever the "All Connections" wildcard (connection_id 0) was granted, wiping every specific grant. This contradicted the effective-access resolver resolveConnectionAccess, which is designed for wildcard and specific grants to coexist and resolve to the higher level per connection.
  • The fix removes that destructive cleanup so the wildcard grant is additive. A specific READ/WRITE is preserved when All Connections READ is added, and All Connections applies as the default for connections that have no specific grant. Behaviour is unchanged where only one grant exists.

Scope notes

  • Server-only. The client dialog already sends single-grant requests and the resolver already implements the intended max-semantics; only the destructive grant-side cleanup was wrong.
  • The matching "grant all" cleanups for MCP privileges and admin permissions are intentionally left untouched: their resolvers treat * as subsuming specific grants, so the cleanup is correct there, unlike connection privileges.
  • Reviewed by the security-auditor: no escalation, injection, stale-grant, or error-handling regressions. One non-blocking UX note: a lower-level wildcard does not cap a higher specific grant (the wildcard is additive); to downgrade a specific connection an operator revokes/re-grants that connection's row via the existing per-row revoke (UI, DELETE .../privileges/connections/{id}, or CLI). No change required for READ/WRITE permissions lost when specifying ALL CONNECTIONS / READ #302.

Test plan

  • TestGrantConnectionPrivilegeAllConnectionsPreservesSpecific — grants READ on conn A and READ/WRITE on conn B, then All Connections READ, and asserts all three rows survive with original levels.
  • TestRBACCheckerSpecificThenAllConnections — resolver-level test in the reverse grant order (specific first, then wildcard): conn B resolves read_write, conn A read, an ungranted conn C read via the wildcard.
  • Added an error-path test; GrantConnectionPrivilege and resolveConnectionAccess both at 100% line coverage. gofmt clean, go build ./... and go test ./internal/auth/... pass (in-process SQLite store, no external DB).

Closes #302

Summary by CodeRabbit

  • Bug Fixes
    • Granting access to “All Connections” no longer removes existing per-connection permissions.
    • Specific connection access and wildcard access now work together, with the higher permission taking effect.
    • Added regression coverage for mixed specific and wildcard access rules.
    • Improved error handling when connection permission updates fail.

…ections

GrantConnectionPrivilege destructively deleted every specific
per-connection grant for a group whenever the "All Connections" wildcard
(connection_id 0) was granted. So a group with, say, READ on one
connection and READ/WRITE on another would silently lose the READ/WRITE
when an operator added an All Connections READ grant, contradicting the
effective-access resolver, which is designed to let wildcard and specific
grants coexist and take the higher level per connection.

Remove the destructive cleanup so the wildcard grant is additive. A
specific READ/WRITE is now preserved when All Connections READ is added,
and All Connections applies as the default for connections without a
specific grant. Effective access is unchanged where only one grant
exists. The MCP and admin "grant all" cleanups are intentionally left in
place: their resolvers treat "*" as subsuming specific grants, unlike
connection privileges.

Closes #302
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6d89509e-0503-4e4c-9548-1c0187abbd85

📥 Commits

Reviewing files that changed from the base of the PR and between 6f2fdb1 and 2961ef0.

📒 Files selected for processing (4)
  • docs/changelog.md
  • server/src/internal/auth/access_test.go
  • server/src/internal/auth/privileges.go
  • server/src/internal/auth/privileges_test.go
💤 Files with no reviewable changes (1)
  • server/src/internal/auth/privileges.go

Walkthrough

Removes the cleanup block in GrantConnectionPrivilege that deleted per-connection grants when granting ConnectionIDAll. Adds tests verifying specific grants survive a wildcard grant and that effective access resolves to the higher level. Updates the changelog.

Changes

Fix: All Connections grant no longer deletes specific grants

Layer / File(s) Summary
Remove cleanup logic in GrantConnectionPrivilege
server/src/internal/auth/privileges.go
Removes the 11-line block that deleted per-connection connection_privileges rows when connectionID == ConnectionIDAll, allowing specific and wildcard grants to coexist.
Unit and RBAC tests for coexistence
server/src/internal/auth/privileges_test.go, server/src/internal/auth/access_test.go
Adds TestGrantConnectionPrivilegeAllConnectionsPreservesSpecific (asserts three rows exist and specific access levels are unchanged after wildcard grant), TestGrantConnectionPrivilegeExecError (DB close forces exec failure), and TestRBACCheckerSpecificThenAllConnections (asserts specific grants persist and non-specific connections fall back to wildcard).
Changelog
docs/changelog.md
Adds a Fixed entry under [Unreleased] describing the corrected coexistence behavior and effective-access resolution.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • pgEdge/ai-dba-workbench#89: Also modifies effective privilege resolution for ConnectionIDAll wildcard vs per-connection grant interactions in the auth package.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main RBAC fix for preserving specific connection grants.
Linked Issues check ✅ Passed The code removes wildcard-grant cleanup and adds tests showing specific grants persist while All Connections applies as the default.
Out of Scope Changes check ✅ Passed The changelog update and extra error-path test are directly related to the RBAC fix and do not add unrelated scope.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-302-preserve-conn-grants

Comment @coderabbitai help to get the list of available commands.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 18 complexity · 0 duplication

Metric Results
Complexity 18
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

READ/WRITE permissions lost when specifying ALL CONNECTIONS / READ

1 participant