Skip to content

Add full name IdP Fleet variable to Apple configuration profiles - #32246

Merged
MagnusHJensen merged 7 commits into
mainfrom
30888-add-fullname-idp-fleet-variable
Aug 26, 2025
Merged

Add full name IdP Fleet variable to Apple configuration profiles#32246
MagnusHJensen merged 7 commits into
mainfrom
30888-add-fullname-idp-fleet-variable

Conversation

@MagnusHJensen

@MagnusHJensen MagnusHJensen commented Aug 25, 2025

Copy link
Copy Markdown
Member

fixes: #30888

Checklist for submitter

If some of the following don't apply, delete the relevant line.

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    See Changes files for more information.

Testing

  • Added/updated automated tests

  • QA'd all new/changed functionality manually

Database migrations

  • Checked table schema to confirm autoupdate

Summary by CodeRabbit

  • New Features
    • Added support for an IdP full name variable in Apple configuration profiles, enabling substitution of a user’s full name.
    • Profiles automatically re-deploy when a user’s IdP full name changes, is removed, or the user is assigned to a host.
  • Bug Fixes
    • Added clearer failure handling: profiles that require an IdP full name now report a delivery failure with a specific message if the value is missing.
  • Tests
    • Expanded test coverage for full name handling and failure scenarios.
  • Chores
    • Seeded the new variable in the database.

@codecov

codecov Bot commented Aug 25, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 74.35897% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.02%. Comparing base (87880ee) to head (589280b).
⚠️ Report is 26 commits behind head on main.

Files with missing lines Patch % Lines
...bles/20250825113751_AddIdpFullnameFleetVariable.go 54.54% 4 Missing and 1 partial ⚠️
server/service/apple_mdm.go 75.00% 4 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #32246      +/-   ##
==========================================
- Coverage   64.04%   64.02%   -0.02%     
==========================================
  Files        1988     1986       -2     
  Lines      194440   194407      -33     
  Branches     6514     6514              
==========================================
- Hits       124521   124466      -55     
- Misses      60221    60230       +9     
- Partials     9698     9711      +13     
Flag Coverage Δ
backend 65.28% <74.35%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

@MagnusHJensen
MagnusHJensen force-pushed the 30888-add-fullname-idp-fleet-variable branch from f547327 to 97d27ed Compare August 25, 2025 10:04
@MagnusHJensen MagnusHJensen changed the title 30888 add fullname idp fleet variable Add full name IdP Fleet variable to Apple configuration profiles Aug 25, 2025
@MagnusHJensen
MagnusHJensen marked this pull request as ready for review August 25, 2025 10:04
@MagnusHJensen
MagnusHJensen requested a review from a team as a code owner August 25, 2025 10:05
@MagnusHJensen

Copy link
Copy Markdown
Member Author

@CodeRabbit full review

@coderabbitai

coderabbitai Bot commented Aug 25, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented Aug 25, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a new Fleet variable for IdP end-user full name, seeds it in the database, exposes a constant, updates Apple MDM profile preprocessing to validate/expand it and fail when missing, ensures SCIM-driven changes trigger profile resend, and adds tests. Schema seed and migration status are updated accordingly.

Changes

Cohort / File(s) Summary
DB migration: seed fullname Fleet var
server/datastore/mysql/migrations/tables/20250825113751_AddIdpFullnameFleetVariable.go
Registers migration to insert FLEET_VAR_HOST_END_USER_IDP_FULL_NAME into fleet_variables with deterministic created_at; down is no-op.
Schema seed updates
server/datastore/mysql/schema.sql
Adds the new Fleet variable row to fleet_variables seed; updates AUTO_INCREMENTs and pre-seeded migration_status_tables data.
Fleet var constant
server/fleet/mdm.go
Adds FleetVarHostEndUserIDPFullname constant ("HOST_END_USER_IDP_FULL_NAME").
SCIM-triggered resend coverage
server/datastore/mysql/scim.go
Includes FleetVarHostEndUserIDPFullname in variables that trigger resend on user change, deletion, or addition to host.
Apple MDM profile preprocessing
server/service/apple_mdm.go
Allows and expands the new variable, derives value from IdpFullName, adds validation and specific failure detail when missing, integrates into variable matching/replace paths.
Tests for fullname handling
server/service/apple_mdm_test.go
Adds test cases covering fullname composition, partial names, and missing fullname leading to DeliveryFailed with new error detail.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Admin
  participant Fleet as Fleet Server
  participant AppleMDM as Apple MDM Service
  participant DS as Datastore
  participant Host as macOS Host

  Admin->>Fleet: Upload profile with $FLEET_VAR_HOST_END_USER_IDP_FULL_NAME
  Fleet->>AppleMDM: Preprocess profile contents
  AppleMDM->>DS: Fetch host end-user IdP data (includes IdpFullName)
  alt IdpFullName present/non-empty
    AppleMDM->>AppleMDM: Substitute fullname in profile
    AppleMDM-->>Host: Install profile
  else missing fullname
    AppleMDM->>DS: Mark profile DeliveryFailed (detail: no IdP fullname)
    AppleMDM-->>Admin: Report failed status for host
  end
Loading
sequenceDiagram
  autonumber
  participant IdP as Identity Provider
  participant SCIM as SCIM Ingest
  participant DS as Datastore
  participant AppleMDM as Apple MDM Service
  participant Hosts as Affected Hosts

  IdP-->>SCIM: User fullname updated
  SCIM->>DS: Store updated IdpFullName
  SCIM->>AppleMDM: triggerResendProfilesUsingVariables([… , HOST_END_USER_IDP_FULL_NAME])
  AppleMDM->>Hosts: Re-deliver affected profiles
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Add new $FLEET_VAR_HOST_END_USER_IDP_FULL_NAME variable in configuration profiles (#30888)
When host lacks full name, mark profile Failed with clear error message (#30888)
Resend configuration profiles when IdP full name changes via SCIM (#30888)
Database schema migrations for new variable seed (#30888)
Paid feature scope: Fleet Premium only label/state (#30888) Not verifiable from code changes.

Assessment against linked issues: Out-of-scope changes

None found.

Possibly related PRs

Suggested reviewers

  • getvictor
  • lucasmrod
  • JordanMontgomery

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 30888-add-fullname-idp-fleet-variable

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server/datastore/mysql/scim.go (1)

1170-1182: Resend will not trigger when only full name (given/family name) changes.

triggerResendProfilesForIDPUserChange now includes FleetVarHostEndUserIDPFullname, but ReplaceScimUser only checks user_name and department deltas before calling it. If only given_name and/or family_name change, profiles that use full name won’t be resent.

Proposed fix: include given_name and family_name in the “changed” check.

@@
-        // load the username and department before updating the user, to check if it changed
-        old := struct {
-            UserName   string  `db:"user_name"`
-            Department *string `db:"department"`
-        }{}
-        err := sqlx.GetContext(ctx, tx, &old, `SELECT user_name, department FROM scim_users WHERE id = ?`, user.ID)
+        // load fields we track for downstream profile resend triggers
+        old := struct {
+            UserName   string  `db:"user_name"`
+            Department *string `db:"department"`
+            GivenName  *string `db:"given_name"`
+            FamilyName *string `db:"family_name"`
+        }{}
+        err := sqlx.GetContext(ctx, tx, &old, `SELECT user_name, department, given_name, family_name FROM scim_users WHERE id = ?`, user.ID)
@@
-        usernameChanged := old.UserName != user.UserName
-        departmentChanged := !cmp.Equal(old.Department, user.Department)
+        usernameChanged := old.UserName != user.UserName
+        departmentChanged := !cmp.Equal(old.Department, user.Department)
+        givenNameChanged := !cmp.Equal(old.GivenName, user.GivenName)
+        familyNameChanged := !cmp.Equal(old.FamilyName, user.FamilyName)
@@
-        // resend profiles that depend on this username if it changed
-        if usernameChanged || departmentChanged {
+        // resend profiles that depend on IdP user fields if any changed
+        if usernameChanged || departmentChanged || givenNameChanged || familyNameChanged {
             err = triggerResendProfilesForIDPUserChange(ctx, tx, user.ID)
             if err != nil {
                 return err
             }
         }

This ensures $FLEET_VAR_HOST_END_USER_IDP_FULL_NAME updates propagate automatically.

🧹 Nitpick comments (6)
changes/308888-add-fullname-idp-fleet-variable (1)

1-1: Name the variable explicitly and mention license + failure behavior.

Consider being explicit about the variable and UX, so release notes are self-contained.

Apply this diff:

-* Added IdP fullname attribute as a valid fleet variable for Apple configuration profiles
+* Add $FLEET_VAR_HOST_END_USER_IDP_FULL_NAME to Apple configuration profiles (Fleet Premium).
+  If a host's IdP full name is missing, profile delivery is marked Failed with a clear error message.
server/service/apple_mdm_test.go (1)

5077-5163: Add a validation test to assert the new variable is “allowed” in profile parsing.

You already test preprocessing; suggest adding one small case to TestValidateConfigProfileFleetVariables to ensure $FLEET_VAR_HOST_END_USER_IDP_FULL_NAME is detected/allowed by validation. This guards against regressions in the allowlist/regex.

Example addition inside TestValidateConfigProfileFleetVariables cases:

// Add to cases in TestValidateConfigProfileFleetVariables:
{
    name:    "Custom profile with IdP full name var",
    profile: string(scopedMobileconfigForTest(
        "FullName Var",
        "com.example.fullname",
        nil,
        "HOST_END_USER_IDP_FULL_NAME", // will be prefixed to $FLEET_VAR_ by helper
    )),
    errMsg:  "",
    vars:    []string{"HOST_END_USER_IDP_FULL_NAME"},
},

I can open a follow-up PR to wire this in if helpful.

server/datastore/mysql/schema.sql (1)

1460-1463: Migration status entry is consistent; consider adding a reversible Down() for the seed (optional).

  • AUTO_INCREMENT=414 with the last row (id 413, version 20250825113751) lines up with the new migration.
  • Optional: For reversibility, implement a Down_20250825113751 that deletes the inserted fleet_variables row by name. Many seed-like migrations in this repo are no-op on Down, so this is a nice-to-have for symmetry, not a blocker.

If you’d like, I can open a follow-up PR to add a reversible Down(). Would you prefer to keep seed Downs as no-op to match precedent?

server/service/apple_mdm.go (3)

5162-5165: Trim whitespace when substituting full name

If IdP returns " First Last " or similar, you probably don’t want those spaces persisted into XML. Safe to trim before replacement.

Apply:

-                case string(fleet.FleetVarHostEndUserIDPFullname):
-                        rx = fleetVarHostEndUserIDPFullnameRegexp
-                        value = user.IdpFullName
+                case string(fleet.FleetVarHostEndUserIDPFullname):
+                        rx = fleetVarHostEndUserIDPFullnameRegexp
+                        value = strings.TrimSpace(user.IdpFullName)

Also applies to: 5189-5193


5391-5391: User-facing message: “full name” (two words) for consistency

Other messages use natural phrasing (“email”, “groups”, “department”). Recommend “full name” over “fullname” in the error string.

-    noFullnameErr := fmt.Sprintf("There is no IdP fullname for this host. Fleet couldn’t populate $FLEET_VAR_%s.", fleet.FleetVarHostEndUserIDPFullname)
+    noFullnameErr := fmt.Sprintf("There is no IdP full name for this host. Fleet couldn’t populate $FLEET_VAR_%s.", fleet.FleetVarHostEndUserIDPFullname)

5421-5433: Trim whitespace-only “full name” values

Defensive check: if the IdP supplies only whitespace, treat it as empty so hosts fail with a clear message (aligns with “missing or empty” acceptance).

--- a/server/service/apple_mdm.go
+++ b/server/service/apple_mdm.go
@@ -5421,7 +5421,7 @@ func someFunction(...) {
-       if fleetVar == string(fleet.FleetVarHostEndUserIDPFullname) && idpUser.IdpFullName == "" {
+       if fleetVar == string(fleet.FleetVarHostEndUserIDPFullname) && strings.TrimSpace(idpUser.IdpFullName) == "" {
            err = ds.UpdateOrDeleteHostMDMAppleProfile(ctx, &fleet.HostMDMAppleProfile{
                CommandUUID:   target.cmdUUID,
                HostUUID:      hostUUID,

Note: the SCIM ingestion’s ScimUser.DisplayName() returns a non-empty string when either GivenName or FamilyName is present (so single-word legal names are still allowed) and only returns "" when both are absent. Adding strings.TrimSpace(...) here ensures that purely whitespace values are treated as missing, without affecting valid single-name cases.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 87880ee and e42d29b.

📒 Files selected for processing (7)
  • changes/308888-add-fullname-idp-fleet-variable (1 hunks)
  • server/datastore/mysql/migrations/tables/20250825113751_AddIdpFullnameFleetVariable.go (1 hunks)
  • server/datastore/mysql/schema.sql (2 hunks)
  • server/datastore/mysql/scim.go (3 hunks)
  • server/fleet/mdm.go (1 hunks)
  • server/service/apple_mdm.go (7 hunks)
  • server/service/apple_mdm_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

⚙️ CodeRabbit configuration file

When reviewing SQL queries that are added or modified, ensure that appropriate filtering criteria are applied—especially when a query is intended to return data for a specific entity (e.g., a single host). Check for missing WHERE clauses or incorrect filtering that could lead to incorrect or non-deterministic results (e.g., returning the first row instead of the correct one). Flag any queries that may return unintended results due to lack of precise scoping.

Files:

  • server/fleet/mdm.go
  • server/datastore/mysql/scim.go
  • server/datastore/mysql/migrations/tables/20250825113751_AddIdpFullnameFleetVariable.go
  • server/service/apple_mdm.go
  • server/service/apple_mdm_test.go
🧠 Learnings (3)
📚 Learning: 2025-07-08T16:13:39.114Z
Learnt from: getvictor
PR: fleetdm/fleet#30589
File: server/datastore/mysql/migrations/tables/20250707095725_HostIdentitySCEPCertificates.go:53-55
Timestamp: 2025-07-08T16:13:39.114Z
Learning: In the Fleet codebase, Down migration functions are intentionally left empty/no-op. The team does not implement rollback functionality for database migrations, so empty Down_* functions in migration files are correct and should not be flagged as issues.

Applied to files:

  • server/datastore/mysql/migrations/tables/20250825113751_AddIdpFullnameFleetVariable.go
📚 Learning: 2025-08-08T08:32:31.529Z
Learnt from: getvictor
PR: fleetdm/fleet#31695
File: server/datastore/mysql/apple_mdm_test.go:132-132
Timestamp: 2025-08-08T08:32:31.529Z
Learning: Datastore.NewMDMWindowsConfigProfile signature is: NewMDMWindowsConfigProfile(ctx context.Context, cp fleet.MDMWindowsConfigProfile, usesFleetVars []string) (*fleet.MDMWindowsConfigProfile, error). Passing nil for usesFleetVars in tests denotes “no Fleet variables referenced” and is used consistently across the repo.

Applied to files:

  • server/service/apple_mdm.go
📚 Learning: 2025-08-01T15:08:16.858Z
Learnt from: sgress454
PR: fleetdm/fleet#31508
File: server/datastore/mysql/schema.sql:102-116
Timestamp: 2025-08-01T15:08:16.858Z
Learning: The schema.sql file in server/datastore/mysql/ is auto-generated from migrations for use with tests, so it cannot be manually edited. Any changes must be made through migrations.

Applied to files:

  • server/datastore/mysql/schema.sql
🔇 Additional comments (9)
server/fleet/mdm.go (1)

49-51: LGTM: new Fleet variable constant is consistent with existing naming.

The identifier and value align with existing Host End User IdP variables and match the struct field Fullname used elsewhere. No issues.

server/datastore/mysql/scim.go (2)

1189-1197: Good: include Full Name in affected vars for user deleted.

This correctly ensures profiles using full name are resent (and likely fail gracefully) when the IdP user is removed.

Please confirm there’s no separate email-triggered resend requirement when SCIM emails change (current code doesn’t resend on email-only updates); out of scope for this PR, but worth tracking if expected.


1231-1250: Good: include Full Name in affected vars for user added to host.

Covers the “user associated to host” path so profiles using full name are resent.

server/service/apple_mdm_test.go (1)

5077-5163: Nice coverage for full name: First+Last, only first, only last, and missing.

The scenarios align with expected substitution and failure behavior, and mirror the style of the existing IdP variable tests.

server/datastore/mysql/schema.sql (1)

326-329: The above script will confirm whether the migration defines Up_<version> and Down_<version> functions matching its filename prefix, and show context to verify naming conventions. Once we have those results, we can finalize whether the schema snapshot truly aligns with the generated migration.

server/service/apple_mdm.go (4)

81-81: Add regexp for new IdP full name variable — looks correct

Pattern matches both $FLEET_VAR_* and ${FLEET_VAR_*} forms and uses the new constant. No issues spotted.


4936-4941: Validation phase: treating full name like other IdP fields is fine

No extra preprocessing validation needed here because missing/empty is enforced later during per-host expansion. Good placement.


5448-5450: No-IdP-user fallback detail: covered

New case funnels to noFullnameErr; behavior matches other IdP fields. Looks good.


84-88: End-to-End Verification Complete: IDP Full Name Fully Integrated

All required pieces for the new HostEndUserIDPFullname variable are in place and wired end-to-end:

  • The fleet.FleetVarHostEndUserIDPFullname constant is referenced throughout the code (e.g. in apple_mdm_test.go), confirming its definition in the fleet package.
  • The MySQL schema seed (server/datastore/mysql/schema.sql) and the migration (AddIdpFullnameFleetVariable.go) insert FLEET_VAR_HOST_END_USER_IDP_FULL_NAME.
  • The SCIM resend logic in server/datastore/mysql/scim.go includes fleet.FleetVarHostEndUserIDPFullname in its trigger lists.
  • server/service/apple_mdm_test.go exercises both success and error scenarios for the full-name variable (Fullname: "Some User" and the “no IdP fullname” error).

No further changes are required here.

@JordanMontgomery JordanMontgomery left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agree with coderabbit re: migration timestamp otherwise looks good to me

@JordanMontgomery

Copy link
Copy Markdown
Member

Agree with coderabbit re: migration timestamp otherwise looks good to me

Actually its comment re: resends is good too. I didn't realize we added that functionality but it sounds like it may need to be updated

@MagnusHJensen
MagnusHJensen merged commit d56d656 into main Aug 26, 2025
41 of 42 checks passed
@MagnusHJensen
MagnusHJensen deleted the 30888-add-fullname-idp-fleet-variable branch August 26, 2025 15:56
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.

Add full name (IdP host vital) as a variable in configuration profiles

2 participants