[PM-40336] Access Rules: API - #7983
Conversation
🤖 Bitwarden Claude Code ReviewOverall Assessment: APPROVE Reviewed the commercial CRUD API for org-scoped PAM Access Rules — the endpoint handler, request/response models, condition models, create/update/delete commands, and the shared write validator, plus their unit tests. Security-sensitive paths are sound: every endpoint is gated behind Code Review DetailsNo blocking findings. Notes considered and not flagged:
|
0351a28 to
37a5507
Compare
37a5507 to
a85b172
Compare
a85b172 to
9c09687
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## pam/access-rule #7983 +/- ##
===================================================
- Coverage 67.29% 62.79% -4.51%
===================================================
Files 2306 2314 +8
Lines 100426 100689 +263
Branches 9028 9052 +24
===================================================
- Hits 67582 63223 -4359
- Misses 30562 35277 +4715
+ Partials 2282 2189 -93 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
56c6cac to
44b46da
Compare
c17c469 to
ccf6444
Compare
| private async Task EnsureMemberAsync(Guid orgId) | ||
| { | ||
| if (!await currentContext.OrganizationUser(orgId)) | ||
| { | ||
| throw new NotFoundException(); | ||
| } | ||
| } | ||
|
|
||
| private async Task EnsureAdminAsync(Guid orgId) | ||
| { | ||
| if (!await currentContext.OrganizationAdmin(orgId) && !await currentContext.OrganizationOwner(orgId)) | ||
| { | ||
| throw new NotFoundException(); | ||
| } | ||
| } |
There was a problem hiding this comment.
We should move this into RequireAuthorization (the minimal API variant of Authorize attribute). However since MemberRequirement is in Api we can't use it in PAM.
@eliykat Any interest in lifting this out into it's own server library?
e5f25d5 to
801a80f
Compare
801a80f to
ca963d2
Compare
ca963d2 to
77d93e9
Compare
77d93e9 to
9a6165c
Compare
9a6165c to
d6deeaa
Compare
Remove the time_of_day condition kind along with the AccessWeekday enum and its JSON converter, which existed only to type the weekday tokens inside a time window. Access rules now expose human_approval and ip_allowlist; a document that still carries a time_of_day entry is rejected as an unknown kind.
The create and update commands each carried their own copy of the same checks: name required, a positive maximum when extensions are allowed, the conditions document, name uniqueness within the organization, and the collection lookup that confirms every requested collection exists, belongs to the organization, and is not already governed by another rule. Move all of it into AccessRuleWriteValidator, which takes the id of the rule being updated, or null when creating. Both places where the two paths differ reduce to a comparison against that id: an update excludes itself from the uniqueness check and may keep the collections it already governs, and with a null id the same expressions give a create its stricter behaviour, where any governed collection conflicts. The validator returns the deduplicated collection ids so callers do not normalize them a second time. The commands keep only what is theirs. Neither needs ICollectionRepository any more, and update keeps its existence guard and the plain AccessRule it maps for persistence. Update now resolves the rule before judging the payload, so editing a rule that does not exist, or belongs to another organization, is a 404 rather than a 400 from a field check. The command tests assert the validator is never reached in those cases to hold that order in place, and the shared rules are covered once in AccessRuleWriteValidatorTests, including the create and update asymmetries.
….csproj Pam.csproj now references Pam.Domain directly for the AccessRule command and validator implementations, so consumers of the Pam service need the reference recorded in their own lock files too. Force-evaluated a full-solution restore to bring every lock file back in sync.
The access-rule commands now take ICollectionRepository for the collection association write, matching the method's new home after review feedback on #7981.
d6deeaa to
e13bb46
Compare
🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-40336
📔 Objective
Add the commercial CRUD API for org-scoped PAM Access Rules, consuming the
domain and persistence layer from #7981. This PR is stacked on #7981 — review
and merge that first; GitHub will retarget this PR to
mainonce it lands.All endpoints are gated behind the
pm-37044-pam-v-0(FeatureFlagKeys.Pam)feature flag, so nothing is reachable in production until PAM v0 ships. Access-rule
data (name, description, conditions) is organization configuration metadata, not
Vault Data — no zero-knowledge surface is touched.
What's included
API —
bitwarden_license/src/Services/PamGET(list),GET {id},POST,PUT {id},DELETE {id}, all org-scoped and feature-flag gated.AccessRuleRequestModel,AccessRuleResponseModel)and the condition models:
human_approvalandip_allowlist.Create/Update/Deletecommands behind interfaces;AccessRuleValidatorvalidating the conditions JSON (max 10 conditions, per-type rules; empty list is
vacuously valid and still routes access through PAM for audit).
📸 Screenshots
N/A — backend only.