Skip to content

Add PSSO registration token#47948

Draft
JordanMontgomery wants to merge 2 commits into
feature/fleet-macos-password-syncfrom
JM-46958-psso-device-reg-token
Draft

Add PSSO registration token#47948
JordanMontgomery wants to merge 2 commits into
feature/fleet-macos-password-syncfrom
JM-46958-psso-device-reg-token

Conversation

@JordanMontgomery

Copy link
Copy Markdown
Member

Related issue: Resolves #

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.

  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters.

  • Timeouts are implemented and retries are limited to avoid infinite loops

  • If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes

Testing

For unreleased bug fixes in a release candidate, one of:

  • Confirmed that the fix is not expected to adversely impact load test results
  • Alerted the release DRI if additional load testing is needed

Database migrations

  • Checked schema for all modified table for columns that will auto-update timestamps during migration.
  • Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects.
  • Ensured the correct collation is explicitly set for character columns (COLLATE utf8mb4_unicode_ci).

New Fleet configuration settings

  • Setting(s) is/are explicitly excluded from GitOps

If you didn't check the box above, follow this checklist for GitOps-enabled settings:

  • Verified that the setting is exported via fleetctl generate-gitops
  • Verified the setting is documented in a separate PR to the GitOps documentation
  • Verified that the setting is cleared on the server if it is not supplied in a YAML file (or that it is documented as being optional)
  • Verified that any relevant UI is disabled when GitOps mode is enabled

fleetd/orbit/Fleet Desktop

  • Verified compatibility with the latest released version of Fleet (see Must rule)
  • If the change applies to only one platform, confirmed that runtime.GOOS is used as needed to isolate changes
  • Verified that fleetd runs on macOS, Linux and Windows
  • Verified auto-update works from the released version of component to the new version (see tools/tuf/test)

Base automatically changed from JM-46930 to feature/fleet-macos-password-sync June 19, 2026 19:39
@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 74.69136% with 41 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (feature/fleet-macos-password-sync@a9ed515). Learn more about missing BASE report.

Files with missing lines Patch % Lines
server/mdm/apple/psso/regtoken/regtoken.go 72.88% 8 Missing and 8 partials ⚠️
server/service/apple_mdm.go 81.57% 4 Missing and 3 partials ⚠️
...19165649_AddPSSODeviceRegistrationTokenFleetVar.go 68.42% 4 Missing and 2 partials ⚠️
server/mdm/nanomdm/service/nanomdm/service.go 16.66% 3 Missing and 2 partials ⚠️
server/datastore/mysql/secret_variables.go 75.00% 2 Missing and 2 partials ⚠️
ee/server/service/apple_psso.go 72.72% 1 Missing and 2 partials ⚠️
Additional details and impacted files
@@                         Coverage Diff                          @@
##             feature/fleet-macos-password-sync   #47948   +/-   ##
====================================================================
  Coverage                                     ?   67.09%           
====================================================================
  Files                                        ?     3627           
  Lines                                        ?   230299           
  Branches                                     ?    11787           
====================================================================
  Hits                                         ?   154518           
  Misses                                       ?    61819           
  Partials                                     ?    13962           
Flag Coverage Δ
backend 68.71% <74.69%> (?)

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

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

@JordanMontgomery

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copilot AI 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.

Warning

  • Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.

Pull request overview

This PR introduces a new Apple Platform SSO (PSSO) “device registration token” that’s delivered via configuration profile as a Fleet variable, expanded at MDM command-delivery time as a per-host Fleet-signed JWT, and then required/validated when the PSSO extension registers device keys.

Changes:

  • Add $FLEET_VAR_PSSO_DEVICE_REGISTRATION_TOKEN (Premium-only) with server-side validation that it only appears in the correct Platform SSO payload/key.
  • Implement host-secret expansion at MDM command delivery to mint and inject a per-host JWT registration token (never stored / not exposed via /mdm/commands).
  • Require/validate registration_token in the PSSO registration endpoint and update the macOS extension to send it.

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
server/service/apple_psso.go Decode registration_token from PSSO registration form body.
server/service/apple_mdm.go Add PSSO reg token Fleet var support + placement validation for config profiles (Premium-gated).
server/service/apple_mdm_test.go Add tests for PSSO variable placement and Premium gating.
server/mdm/nanomdm/service/nanomdm/service.go Expand host-scoped secrets for “ProfileWithSecrets” commands at delivery time before signing/encoding.
server/mdm/apple/psso/regtoken/regtoken.go New package to mint/validate Fleet-signed ES256 JWT registration tokens (aud-locked, sub=host UUID).
server/mdm/apple/psso/regtoken/regtoken_test.go Unit tests for token mint/validate behavior and rejection cases.
server/mdm/apple/profile_processor.go Replace PSSO Fleet var with a host-secret placeholder and short-circuit per-host fan-out when it’s the only variable.
server/mdm/apple/profile_processor_test.go Tests covering placeholder substitution and fan-out behavior when mixed with other host vars.
server/fleet/secrets.go Add new host secret type for PSSO device registration token.
server/fleet/mdm.go Add Fleet variable constant + regexp for PSSO device registration token.
server/fleet/apple_psso.go Add RegistrationToken field to PSSODeviceRegistrationRequest and document host identity derivation from it.
server/fleet/apple_profiles.go Treat both org secrets and host secrets as requiring the “profile with secrets” command path.
server/datastore/mysql/secret_variables.go Mint PSSO registration token from stored signing key asset during ExpandHostSecrets.
server/datastore/mysql/secret_variables_test.go Test host secret expansion for PSSO registration token, including missing-asset failure.
server/datastore/mysql/schema.sql Add fleet_variables seed row + bump auto-increments and migration status seed.
server/datastore/mysql/migrations/tables/20260619165649_AddPSSODeviceRegistrationTokenFleetVar.go Migration to insert new fleet_variables row.
server/datastore/mysql/migrations/tables/20260619165649_AddPSSODeviceRegistrationTokenFleetVar_test.go Migration test ensuring the variable is inserted.
ee/server/service/apple_psso.go Validate registration token and derive host UUID from token subject during device registration.
ee/server/service/apple_psso_test.go Tests for token-required registration and host identity derivation from token subject.
apps/fleet-desktop-macos/FleetPSSOExtension/AuthenticationViewController+Shared.swift Add registration_token to the registration payload.
apps/fleet-desktop-macos/FleetPSSOExtension/AuthenticationViewController+PSSO.swift Pass registration token from loginManager into registration POST.
apps/fleet-desktop-macos/fleet-sso-extension-example.mobileconfig Example profile includes RegistrationToken set to the new Fleet var.
docs/Contributing/research/mdm/psso.md Updated (content excluded from review).
Files excluded by content exclusion policy (1)
  • docs/Contributing/research/mdm/psso.md

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ee/server/service/apple_psso.go
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: aggregate-result

Failed stage: Check for failures [❌]

Failed test name: integration-enterprise-mysql8.0.44

Failure summary:

The action failed because one of the aggregated test job status artifacts contained fail.
- The
status-check script scanned downloaded status files and found
./integration-enterprise-mysql8.0.44-status/status had status content fail (log lines 181-182).
- As
a result, it reported ❌ One or more test jobs failed: integration-enterprise-mysql8.0.44 and exited
with code 1 (log lines 191-192).

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

126:  Artifact download completed successfully.
127:  Extracting artifact entry: /home/runner/work/fleet/fleet/fleetctl-mysql8.0.44-status/status
128:  Artifact download completed successfully.
129:  Extracting artifact entry: /home/runner/work/fleet/fleet/main-mysql8.0.44-status/status
130:  Artifact download completed successfully.
131:  Redirecting to blob download url: https://productionresultssa0.blob.core.windows.net/actions-results/d2f373ee-bc7c-4a8f-bf05-823234e92637/workflow-job-run-27a9002b-e61f-5c59-838c-b8c9572d779b/artifacts/023cd68f0028f26ec8a302741c14d1063773dfa881aec556f78d076f4e6e56a0.zip
132:  Starting download of artifact to: /home/runner/work/fleet/fleet/integration-enterprise-mysql8.0.44-status
133:  Extracting artifact entry: /home/runner/work/fleet/fleet/integration-enterprise-mysql8.0.44-status/status
134:  Artifact download completed successfully.
135:  Redirecting to blob download url: https://productionresultssa0.blob.core.windows.net/actions-results/d2f373ee-bc7c-4a8f-bf05-823234e92637/workflow-job-run-41e7d9b1-3f79-520b-8855-745a679afa02/artifacts/8ca4ef2662e0cd51261c933e428eb486df37063bc2bbd7d8f27684bd463f4007.zip
136:  Starting download of artifact to: /home/runner/work/fleet/fleet/vuln-mysql8.0.44-status
137:  Extracting artifact entry: /home/runner/work/fleet/fleet/vuln-mysql8.0.44-status/status
138:  Artifact download completed successfully.
139:  Total of 10 artifact(s) downloaded
140:  Download artifact has finished successfully
141:  ##[group]Run failed_tests=""
142:  �[36;1mfailed_tests=""�[0m
143:  �[36;1mstatus_count=0�[0m
144:  �[36;1m# Find all status files (they are in directories like 'fleetctl-mysql8.0.44-status/status')�[0m
145:  �[36;1mfor status_file in $(find ./ -type f -name 'status'); do�[0m
146:  �[36;1m  status_count=$((status_count + 1))�[0m
147:  �[36;1m  # Extract test name from parent directory (e.g., 'fleetctl-mysql8.0.44-status')�[0m
148:  �[36;1m  test_dir=$(basename $(dirname "$status_file"))�[0m
149:  �[36;1m  # Remove '-status' suffix to get the test name�[0m
150:  �[36;1m  test_name="${test_dir%-status}"�[0m
151:  �[36;1m  status_content=$(cat "$status_file")�[0m
152:  �[36;1m  echo "Processing: $status_file (Test: $test_name) with status content: $status_content"�[0m
153:  �[36;1m  if grep -q "fail" "$status_file"; then�[0m
154:  �[36;1m    echo "  ❌ Test failed: $test_name"�[0m
155:  �[36;1m    failed_tests="${failed_tests}${test_name}, "�[0m
156:  �[36;1m  else�[0m
157:  �[36;1m    echo "  ✅ Test passed: $test_name"�[0m
158:  �[36;1m  fi�[0m
159:  �[36;1mdone�[0m
160:  �[36;1mif [[ $status_count -eq 0 ]]; then�[0m
161:  �[36;1m  echo "❌ ERROR: No status files found! This indicates a workflow issue."�[0m
162:  �[36;1m  exit 1�[0m
163:  �[36;1mfi�[0m
164:  �[36;1mif [[ -n "$failed_tests" ]]; then�[0m
165:  �[36;1m  echo "❌ One or more test jobs failed: ${failed_tests%, }"�[0m
166:  �[36;1m  exit 1�[0m
167:  �[36;1mfi�[0m
168:  �[36;1mecho "✅ All test jobs succeeded."�[0m
169:  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
170:  ##[endgroup]
171:  Processing: ./fleetctl-mysql8.0.44-status/status (Test: fleetctl-mysql8.0.44) with status content: success
172:  ✅ Test passed: fleetctl-mysql8.0.44
173:  Processing: ./vuln-mysql8.0.44-status/status (Test: vuln-mysql8.0.44) with status content: success
174:  ✅ Test passed: vuln-mysql8.0.44
175:  Processing: ./service-mysql8.0.44-status/status (Test: service-mysql8.0.44) with status content: success
176:  ✅ Test passed: service-mysql8.0.44
177:  Processing: ./integration-core-mysql8.0.44-status/status (Test: integration-core-mysql8.0.44) with status content: success
178:  ✅ Test passed: integration-core-mysql8.0.44
179:  Processing: ./mysql-mysql8.0.44-status/status (Test: mysql-mysql8.0.44) with status content: success
180:  ✅ Test passed: mysql-mysql8.0.44
181:  Processing: ./integration-enterprise-mysql8.0.44-status/status (Test: integration-enterprise-mysql8.0.44) with status content: fail
182:  ❌ Test failed: integration-enterprise-mysql8.0.44
183:  Processing: ./integration-mdm-mysql8.0.44-status/status (Test: integration-mdm-mysql8.0.44) with status content: success
184:  ✅ Test passed: integration-mdm-mysql8.0.44
185:  Processing: ./scripts-status/status (Test: scripts) with status content: success
186:  ✅ Test passed: scripts
187:  Processing: ./fast-status/status (Test: fast) with status content: success
188:  ✅ Test passed: fast
189:  Processing: ./main-mysql8.0.44-status/status (Test: main-mysql8.0.44) with status content: success
190:  ✅ Test passed: main-mysql8.0.44
191:  ❌ One or more test jobs failed: integration-enterprise-mysql8.0.44
192:  ##[error]Process completed with exit code 1.
193:  Post job cleanup.

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.

2 participants