[PM-29460] feat: Authenticate PricingClient to the pricing service - #8054
[PM-29460] feat: Authenticate PricingClient to the pricing service#8054amorask-bitwarden wants to merge 2 commits into
Conversation
Send the shared X-Pricing-Api-Key header on every cloud request to the pricing service so its use-pricing-api-key-authentication flag can be enabled without breaking plan retrieval. Adds an optional PricingApiKey to GlobalSettings and attaches it as a default request header in AddPricingClient when configured. The header is inert while the pricing service's flag is off (that middleware is a pass-through), so shipping it early is safe and decouples the server deploy from the flag flip.
🤖 Bitwarden Claude Code ReviewOverall Assessment: APPROVE Reviewed an additive change that makes the cloud-side Code Review DetailsNo blocking or actionable findings. Notes considered and dismissed:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8054 +/- ##
==========================================
- Coverage 62.50% 62.50% -0.01%
==========================================
Files 2301 2301
Lines 100156 100161 +5
Branches 9027 9028 +1
==========================================
+ Hits 62605 62606 +1
+ Misses 35369 35368 -1
- Partials 2182 2187 +5 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-29460
📔 Objective
Make
server's cloud-sidePricingClientsend the sharedX-Pricing-Api-Keyheader on every request to the pricing service, so the pricing service'suse-pricing-api-key-authenticationflag can be turned on without breaking cloud plan retrieval.Two small, additive changes:
GlobalSettings.PricingApiKey— a new optional (nullable) setting mirroring the existingPricingUri. Absent/empty means "don't send." Binds fromglobalSettings:pricingApiKey/globalSettings__pricingApiKeylike the otherglobalSettingssecrets.AddPricingClient— attachesX-Pricing-Api-Keyas a default request header on the typed client, guarded on the key being non-empty (mirrors the existingPricingUriempty-guard).PricingClientis unchanged — it already sends whatever default headers the factory configures.Why it's safe to ship ahead of the flag flip:
PricingClientbefore any HTTP call, so the header is never sent from a self-host instance.use-pricing-api-key-authenticationflag is off, its middleware is a pass-through and ignores the header. The header is only sent oncePricingApiKeyis provisioned, so there's no behavior change until then — decoupling the server deploy from the flag flip (no window where both must change together).✅ Testing
ServiceCollectionExtensionsTestsasserts the header is present + correct when the key is configured, and absent when it isn't (verified viaIHttpClientFactory.CreateClient(nameof(IPricingClient))).PricingClientTestsstay green, including the self-hosted no-call cases.dotnet build,dotnet format --verify-no-changes, and the Billing/Pricing suite (99 tests) all pass.🚫 Out of scope
globalSettings__pricingApiKey(separate devops ticket, gated on QA validation; non-prod overlays already wired).bitwarden/billing-pricing— the authentication middleware already exists there.additional-keys-for-cloud-services.jsonsecrets (not this repo), per contributing-docs.