Skip to content
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

[PM-18876] Refine PolicyRequirements API #5445

Open
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

eliykat
Copy link
Member

@eliykat eliykat commented Feb 26, 2025

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-18876

📔 Objective

@MGibson1 provided feedback that the static factory methods for policy requirements had too many responsibilities to be a clear interface for other teams. When implementing it, the developer needs to know to:

  1. filter out other policy types (as it received all policies)
  2. filter out exempt users (roles/status/providers etc)
  3. reduce the policies into the requirements object

It would be easy to only implement the last item, which would be wrong.

This PR replaces that with an IPolicyRequirementFactory interface instead, which requires that you handle those 3 business requirements explicitly when implementing it. This way, the interface describes the questions you need to answer. This will be accompanied with documentation (maybe a deep dive) once merged.

I've also provided a default base implementation, which makes the Enforce predicate fully declarative (i.e. configurable just by listing who you want to exempt), and has sensible defaults so that you don't miss something important. This should work in 99% of cases. (To the point where I almost made this the interface, but I wanted to maintain a distinction between the required interface vs. a default implementation.)

Lastly, I've updated the Send requirement I'd already implemented to use the new api.

There are a few flow-on effects worth noting:

  • IPolicyRequirementFactory implementations can be registered as scoped dependencies in the usual fashion, instead of the more flexible but weirder currying of static factory methods to inject any dependencies (if you're wondering "huh what does he mean by that" - exactly). While most factories won't require additional dependencies, some do (mostly GlobalSettings and feature flags) and we need to facilitate that.
  • classes extending BasePolicyRequirementFactory don't need as many tests, because they can rely on the base class to have implemented - and therefore in my view, tested - the Enforce method. They only really need to test their Create method. Given that we're going to have a lot of factories, this should result in way fewer tests.
  • The more granular interface on IPolicyRequirementFactory also makes your tests more granular, and therefore easier to arrange.
  • We can no longer combine multiple policies into 1 requirement, as I did with Send. I chose not to accommodate this because it's not really how we think about policies and it would've made the interface less clear. I think it's clearer to maintain a 1:1 relationship.

📸 Screenshots

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

Copy link
Contributor

github-actions bot commented Feb 26, 2025

Logo
Checkmarx One – Scan Summary & Detailsdcf9b2e8-76a0-497c-968a-04144c786d34

New Issues (13)

Checkmarx found the following issues in this Pull Request

Severity Issue Source File / Package Checkmarx Insight
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 164
detailsMethod Put at line 164 of /src/Api/AdminConsole/Controllers/GroupsController.cs gets a parameter from a user request from model. This parameter val...
Attack Vector
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/GroupsController.cs: 133
detailsMethod Put at line 133 of /src/Api/AdminConsole/Public/Controllers/GroupsController.cs gets a parameter from a user request from model. This parame...
Attack Vector
MEDIUM CSRF /bitwarden_license/src/Scim/Controllers/v2/GroupsController.cs: 104
detailsMethod Patch at line 104 of /bitwarden_license/src/Scim/Controllers/v2/GroupsController.cs gets a parameter from a user request from model. This pa...
Attack Vector
MEDIUM CSRF /bitwarden_license/src/Scim/Controllers/v2/GroupsController.cs: 94
detailsMethod Put at line 94 of /bitwarden_license/src/Scim/Controllers/v2/GroupsController.cs gets a parameter from a user request from model. This param...
Attack Vector
LOW Log_Forging /src/Api/Tools/Controllers/SendsController.cs: 166
detailsMethod PostFile at line 166 of /src/Api/Tools/Controllers/SendsController.cs gets user input from element model. This element’s value flows through...
Attack Vector
LOW Log_Forging /src/Api/Tools/Controllers/SendsController.cs: 156
detailsMethod Post at line 156 of /src/Api/Tools/Controllers/SendsController.cs gets user input from element model. This element’s value flows through the...
Attack Vector
LOW Log_Forging /src/Api/Tools/Controllers/SendsController.cs: 272
detailsMethod Put at line 272 of /src/Api/Tools/Controllers/SendsController.cs gets user input from element model. This element’s value flows through the ...
Attack Vector
LOW Log_Forging /src/Api/Controllers/DevicesController.cs: 86
detailsMethod Post at line 86 of /src/Api/Controllers/DevicesController.cs gets user input from element model. This element’s value flows through the code...
Attack Vector
LOW Log_Forging /src/Api/Controllers/DevicesController.cs: 178
detailsMethod PutToken at line 178 of /src/Api/Controllers/DevicesController.cs gets user input from element model. This element’s value flows through the...
Attack Vector
LOW Log_Forging /src/Api/Controllers/DevicesController.cs: 86
detailsMethod Post at line 86 of /src/Api/Controllers/DevicesController.cs gets user input from element model. This element’s value flows through the code...
Attack Vector
LOW Log_Forging /src/Api/Controllers/DevicesController.cs: 178
detailsMethod PutToken at line 178 of /src/Api/Controllers/DevicesController.cs gets user input from element model. This element’s value flows through the...
Attack Vector
LOW Log_Forging /src/Api/Billing/Controllers/OrganizationBillingController.cs: 165
detailsMethod UpdatePaymentMethodAsync at line 165 of /src/Api/Billing/Controllers/OrganizationBillingController.cs gets user input from element requestBo...
Attack Vector
LOW Missing_CSP_Header /src/Core/MailTemplates/Handlebars/Layouts/SecurityTasks.html.hbs: 11
detailsA Content Security Policy is not explicitly defined within the web-application.
Attack Vector
Fixed Issues (30)

Great job! The following issues were fixed in this Pull Request

Severity Issue Source File / Package
MEDIUM CSRF /src/Api/Controllers/DevicesController.cs: 72
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 143
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 171
MEDIUM CSRF /src/Api/Public/Controllers/CollectionsController.cs: 87
MEDIUM CSRF /src/Api/Controllers/DevicesController.cs: 59
MEDIUM CSRF /src/Api/SecretsManager/Controllers/ServiceAccountsController.cs: 162
MEDIUM Privacy_Violation /src/Core/Auth/Services/Implementations/AuthRequestService.cs: 221
MEDIUM Privacy_Violation /src/Core/Auth/Services/Implementations/AuthRequestService.cs: 230
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Api/Controllers/DevicesController.cs: 191
LOW Log_Forging /src/Api/Controllers/DevicesController.cs: 191
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Billing/Controllers/RecoveryController.cs: 38
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164
LOW Log_Forging /src/Billing/Controllers/StripeController.cs: 164

Copy link

codecov bot commented Feb 26, 2025

Codecov Report

Attention: Patch coverage is 93.33333% with 3 lines in your changes missing coverage. Please review.

Project coverage is 44.49%. Comparing base (bea0d0d) to head (2574b48).

Files with missing lines Patch % Lines
...PolicyRequirements/BasePolicyRequirementFactory.cs 75.00% 2 Missing ⚠️
...Policies/Implementations/PolicyRequirementQuery.cs 90.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5445   +/-   ##
=======================================
  Coverage   44.48%   44.49%           
=======================================
  Files        1533     1535    +2     
  Lines       71073    71079    +6     
  Branches     6379     6379           
=======================================
+ Hits        31619    31624    +5     
- Misses      38087    38089    +2     
+ Partials     1367     1366    -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@r-tome r-tome left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! I have left some initial thoughts

/// </remarks>
public delegate T RequirementFactory<out T>(IEnumerable<PolicyDetails> policyDetails)
where T : IPolicyRequirement;
public interface IRequirementFactory<out T> where T : IPolicyRequirement
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This interface could use a separate file

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

/// <typeparam name="T"></typeparam>
public abstract class SimpleRequirementFactory<T> : IRequirementFactory<T> where T : IPolicyRequirement
{
protected abstract IEnumerable<OrganizationUserType> ExemptRoles { get; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think most policies will have these roles exempt so we could make it virtual to be overridden if necessary

Suggested change
protected abstract IEnumerable<OrganizationUserType> ExemptRoles { get; }
protected virtual IEnumerable<OrganizationUserType> ExemptRoles { get; } =
[OrganizationUserType.Owner, OrganizationUserType.Admin];

We could do the same thing for the exempt statuses

Copy link
Member Author

@eliykat eliykat Mar 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was also Matt Gibson's feedback. I've done this for roles, statuses and exempting providers, all with sensible defaults.

/// <summary>
/// Policy requirements for the Disable Send and Send Options policies.
/// </summary>
public class DisableSendRequirement : IPolicyRequirement
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name would be very specific

Suggested change
public class DisableSendRequirement : IPolicyRequirement
public class DisableSendPolicyRequirement : IPolicyRequirement

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've brought all the names into line so that the PolicyRequirement wording is more consistent.

@eliykat eliykat marked this pull request as ready for review March 4, 2025 05:00
@eliykat eliykat requested review from a team as code owners March 4, 2025 05:00
@eliykat eliykat requested review from r-tome and MGibson1 March 4, 2025 05:00
@eliykat eliykat changed the title Refine PolicyRequirements API [PM-18876] Refine PolicyRequirements API Mar 4, 2025
Copy link
Contributor

@r-tome r-tome left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

Copy link

sonarqubecloud bot commented Mar 6, 2025

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.

3 participants