Skip to content

PM-40665 - Seed SSO configuration and a realistic local-sso dev org in the Seeder#8014

Open
theMickster wants to merge 13 commits into
mainfrom
seeder/add-sso-to-seeder
Open

PM-40665 - Seed SSO configuration and a realistic local-sso dev org in the Seeder#8014
theMickster wants to merge 13 commits into
mainfrom
seeder/add-sso-to-seeder

Conversation

@theMickster

@theMickster theMickster commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

🎟️ Tracking

PM-40665 - Seed a working SSO configuration through the preset catalog

📔 Objective

Dev-tooling enhancement to the Seeder (util/Seeder)

  1. Make SAML SSO configuration seedable via a new preset, so a login-ready SSO org stands up with one command.
  2. Turn the shared enterprise-basic fixtures into a realistic org and add a golden local-sso preset that seeds a reproducible, populated SSO org against the bundled local IdP.

Key changes

  • Introduce SsoConfigSeeder and CreateSsoConfigStep — build and seed a SAML SsoConfig, fetching the IdP signing certificate live from the local IdP metadata endpoint at seed time (XXE-safe), so no certificate is baked into the repo.
  • Add an sso preset block and a WithSso(...) recipe step consumed by PresetLoader; commit the config via EF Add in BulkCommitter (single row, long identity PK).
  • Thread an optional fixed organization id through CreateOrganizationStep/OrganizationSeeder so a golden org reproduces the same GUID across clean-slate seeds.
  • Print an .env SSO wiring block from the CLI after seeding a preset that produced an SsoConfig.
  • Retire the tde-vault/sso-vault cipher fixtures; re-point sso-enterprise/tde-enterprise to enterprise-basic.
  • Grow the enterprise-basic roster to 25 realistic members with groups and matching collections.
  • Enrich the enterprise-basic cipher fixture to 45 items across all eight cipher types, ~40% carrying attachments (bundled sample bodies across v0/v1/v2), plus archived and soft-deleted items.
  • Add the golden local-sso preset (fixed org GUID, SAML masterPassword) with collectionAssignments routing every cipher into the department collections; commit local-IdP wiring templates so it logs in against the bundled SimpleSAMLphp IdP out of the box.

Not changed: the SSO broker app, Identity, and the Rust SDK — the Seeder writes the same server-side SsoConfig/OrganizationUser records a real client produces; it never fabricates key material or device-trust state.

🧪 Testing

Expand for seed + login verification

Step 1: Fixture parse/coverage tests

dotnet test test/SeederApi.IntegrationTest/ --filter FixtureParsingTests → 6/6 pass (fixture deserializes, all eight cipher types present, attachment bodies embedded), alongside the SSO factory/step tests.

Step 2: Clean-slate seed

preset --name features.local-sso against a fresh DB with Azurite running seeds org a1b2c3d4-…:

Metric Value
Members 25
Groups 4
Collections 40
Ciphers 45 (18 with attachments, 4 archived, 4 deleted, 8 cipher-key)
SsoConfig Enabled, configType=2, memberDecryptionType=0, spUniqueEntityId=true

Step 3: End-to-end SSO login

Logged in through the local SimpleSAMLphp IdP as the seeded owner and landed in a populated Password Manager vault. The owner reaches 39/40 collections via UserCollectionDetails (the 40th is the intentional No-Access placeholder).

Add the SsoConfigSeeder factory that builds a SAML SsoConfig, the SeedPreset sso block plus an optional fixed organization id, and the LocalSamlIdp constants for the bundled dev IdP. No pipeline wiring yet.
The sso preset block and the Enterprise UseSso flag already existed, but no step ever wrote an SsoConfig row, so seeded SSO orgs were only half-configured and could not broker a login. This wires the SSO factory into the pipeline to close that gap, following the existing OrganizationDomain seed pattern.

- CreateSsoConfigStep reads the org from context, sets its Identifier, fetches the IdP signing certificate live from the local IdP metadata endpoint (XXE-safe reader), and stages the SsoConfig.
- WithSso(...) on the recipe builder (guarded on an existing org) and PresetLoader consumption of the sso block; an optional fixed org id is threaded through CreateOrganizationStep/OrganizationSeeder so golden orgs reproduce the same GUID.
- BulkCommitter commits the single row via EF Add (long identity PK); the SSO identifier is surfaced on the pipeline and organization result models.

The certificate is fetched at seed time rather than baked into the repo so a ~1 KB base64 blob never trips secret/SAST scanners, and it auto-tracks the dev IdP image's cert.
After seeding an SSO org the operator still has to point the local IdP at it, and the SP entity id / ACS URL are easy to get subtly wrong by hand — they embed the org GUID and depend on the Sso launch-profile port. Rather than leave that as a manual copy-from-the-Admin-Console step, the CLI now prints the exact wiring.

- ConsoleOutput.PrintSsoWiring emits a ready-to-paste dev/.env block (IDP_SP_ENTITY_ID, IDP_SP_ACS_URL) plus the login identifier for the seeded org.
- PresetCommand invokes it only when the seed result carries an SSO identifier (set on the SAML path together with the SsoConfig), so non-SSO and OIDC presets print nothing extra.
tde-vault (7 login stubs) and sso-vault (a single login) were thin, low-value cipher fixtures that gave their presets almost no content. Consolidating on the shared enterprise-basic fixture — enriched in the following commit — lets those SSO/TDE presets seed a realistic vault and drops two near-empty fixtures.

- Delete ciphers/tde-vault.json and ciphers/sso-vault.json.
- Re-point sso-enterprise and tde-enterprise to the enterprise-basic cipher fixture. (The golden local-sso preset is added later already pointing at enterprise-basic.)
The roster's five members were role-name placeholders (Enterprise Owner, Admin, User, Custom, Custom-Two) under a single All Members group — it didn't resemble a real company. It's also the roster the golden local-sso org now uses, so these members/groups/collections are exactly what a developer sees after an SSO login.

- Replace the placeholders with 25 realistically-named members across owner/admin/user/custom roles.
- Add Finance, Human Resources, and Information Technology groups with sensible department membership. All Members is retained and repopulated with everyone, since the existing collections grant against it.
- Add four named collections: Finance, Human Resources, and Information Technology (each managed by its department group and by the owner directly) plus a Company-Wide collection for All Members.

The legacy placeholder collections are retained (the Default collection's owner grant is updated to the renamed owner); the new collections are added alongside, preserving existing access.
The fixture was 24 near-empty items (login stubs with test/123, several empty login objects, one card, one secure note) covering only three cipher types — not enough to demo the client or exercise the attachment and lifecycle paths.

- Rewrite it as 45 realistically-named items covering all eight cipher types (login, card, identity, secureNote, sshKey, bankAccount, driversLicense, passport) with richer fields: notes, uris, custom fields, totp, password history.
- Attach bundled sample bodies to 18 items (~40%) across the v0/v1/v2 schemes; every v2 attachment sits on a cipherKey host per the scheme invariant.
- Seed 4 archived and 4 soft-deleted items so those states are present.
- Extend FixtureParsingTests to assert enterprise-basic covers all eight types, carries archived/deleted items, and references only embedded attachment bodies — bundled here because those assertions only pass against the enriched fixture.

All data is fake/mock; no new attachment files are added — existing bundled bodies are reused.
Standing up a SAML SSO org by hand — Enterprise org, Admin Console config, certificate extraction, .env wiring, IdP account mapping — is fiddly and easy to get subtly wrong. This adds a fixed, reproducible golden org so 'preset --name features.local-sso' (seeded without --mangle) yields a login-ready, populated SSO org against the bundled SimpleSAMLphp IdP.

- Add the local-sso preset: fixed org GUID, SAML masterPassword, on the enriched enterprise-basic roster and ciphers, with collectionAssignments routing all 45 ciphers into the Finance/HR/IT/Company-Wide collections so the owner logs in to a populated vault. (Explicit routing leaves the legacy placeholder collections empty in this org.)
- Pre-wire the committed dev templates: the .env template sets IDP_SP_ENTITY_ID/ACS for the fixed org GUID, and the IdP authsources template maps the 'owner' login to the seeded owner (dana.whitfield@verdant.example) — so a fresh checkout logs in out of the box.

The live dev/.env and dev/authsources.php are gitignored; only the .example templates are committed.
Keep the preset catalog in step with the fixture changes so the docs don't drift.

- Update the sso-enterprise and tde-enterprise rows to show the enterprise-basic cipher fixture (was sso-vault/tde-vault).
- Add a local-sso row and a note: golden fixed-GUID SAML 2.0 org, seed without --mangle, log in as owner/password, and the Azurite requirement now that enterprise-basic carries attachments.

The formatter re-aligned the QA table columns as well (whitespace only; no QA content changed).
@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed a dev-tooling PR that makes SAML SSO seedable in util/Seeder and adds a local-sso golden preset. Scope is limited to the Seeder, SeederUtility, tests, dev/*.example files, and JSON fixtures — no product or runtime code. The XXE-safe IdP metadata fetch (DtdProcessing.Prohibit, XmlResolver = null), the fixed-org-GUID threading, the CoreHelpers.GenerateComb()CombGuid.Generate() swap, and the EF-based SsoConfig commit path all check out. Seed fixtures use clearly-marked fake credentials, consistent with existing conventions.

Code Review Details
  • ⚠️ : Assert.Superset arguments reversed — test does not verify all eight cipher types are present, contradicting its name/comment. Affects both the new EnterpriseBasicFixture test and the modified EncryptionModesFixture test.
    • test/SeederApi.IntegrationTest/FixtureParsingTests.cs:75
    • test/SeederApi.IntegrationTest/FixtureParsingTests.cs:59

@theMickster theMickster added ai-review Request a Claude code review t:misc Change Type - ¯\_(ツ)_/¯ Prefer using other type labels labels Jul 19, 2026
Comment thread util/Seeder/Factories/OrganizationSeeder.cs Fixed
Comment thread test/SeederApi.IntegrationTest/FixtureParsingTests.cs Fixed
Comment thread test/SeederApi.IntegrationTest/FixtureParsingTests.cs Dismissed
Comment thread util/Seeder/Steps/CreateSsoConfigStep.cs Dismissed
@codecov

codecov Bot commented Jul 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.44%. Comparing base (eeb1c26) to head (42e556d).
⚠️ Report is 9 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8014      +/-   ##
==========================================
+ Coverage   62.36%   62.44%   +0.08%     
==========================================
  Files        2286     2290       +4     
  Lines       99673    99752      +79     
  Branches     9003     9004       +1     
==========================================
+ Hits        62157    62289     +132     
+ Misses      35344    35291      -53     
  Partials     2172     2172              

☔ View full report in Codecov by Harness.
📢 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.

Comment thread test/SeederApi.IntegrationTest/FixtureParsingTests.cs Fixed
theMickster and others added 2 commits July 20, 2026 10:38
… expression'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Comment thread test/SeederApi.IntegrationTest/FixtureParsingTests.cs Outdated
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Comment thread test/SeederApi.IntegrationTest/FixtureParsingTests.cs
@theMickster theMickster changed the title Seed SSO configuration and a realistic local-sso dev org in the Seeder PM-40665 - Seed SSO configuration and a realistic local-sso dev org in the Seeder Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review t:misc Change Type - ¯\_(ツ)_/¯ Prefer using other type labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant