Orbit passes EUA token during enrollment (#43369)

**Related issue:** Resolves #41379

# Checklist for submitter

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

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [x] Added/updated automated tests
- [ ] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)
- [ ] QA'd all new/changed functionality manually

## fleetd/orbit/Fleet Desktop

- [x] Verified compatibility with the latest released version of Fleet
(see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md))
- [x] 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](../tools/tuf/test/README.md))


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added EUA token support to Orbit enrollment workflow
  * Introduced `--eua-token` CLI flag for Windows MDM enrollment
  * Windows MSI packages now support EUA_TOKEN property (Orbit v1.55.0+)

* **Tests**
* Added tests for EUA token handling in enrollment and Windows packaging

* **Documentation**
* Added changelog entry documenting EUA token inclusion in enrollment
requests

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Konstantin Sykulev
2026-04-13 16:19:47 -05:00
committed by GitHub
co-authored by Copilot
parent 7bcc2c6894
commit 2245359ad1
8 changed files with 173 additions and 1 deletions
+2
View File
@@ -128,6 +128,8 @@ type Options struct {
// EndUserEmail is the email address of the end user that uses the host on
// which the agent is going to be installed.
EndUserEmail string
// EnableEUATokenProperty is a boolean indicating whether to enable EUA_TOKEN property in Windows MSI package.
EnableEUATokenProperty bool
// DisableKeystore disables the use of the keychain on macOS and Credentials Manager on Windows
DisableKeystore bool
// OsqueryDB is the directory to use for the osquery database.
+4
View File
@@ -104,6 +104,10 @@ func BuildMSI(opt Options) (string, error) {
if semver.Compare(orbitVersion, "v1.28.0") >= 0 {
opt.EnableEndUserEmailProperty = true
}
// v1.55.0 introduced EUA_TOKEN property for MSI package: https://github.com/fleetdm/fleet/issues/41379
if semver.Compare(orbitVersion, "v1.55.0") >= 0 {
opt.EnableEUATokenProperty = true
}
// Write files
+58
View File
@@ -0,0 +1,58 @@
package packaging
import (
"bytes"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestWindowsWixTemplateEUAToken(t *testing.T) {
baseOpt := Options{
FleetURL: "https://fleet.example.com",
EnrollSecret: "secret",
OrbitChannel: "stable",
OsquerydChannel: "stable",
DesktopChannel: "stable",
NativePlatform: "windows",
Architecture: ArchAmd64,
}
t.Run("EUA_TOKEN property and flag included when enabled", func(t *testing.T) {
opt := baseOpt
opt.EnableEUATokenProperty = true
var buf bytes.Buffer
err := windowsWixTemplate.Execute(&buf, opt)
require.NoError(t, err)
output := buf.String()
assert.Contains(t, output, `<Property Id="EUA_TOKEN" Value="dummy"/>`)
var argsLine string
for line := range strings.SplitSeq(output, "\n") {
if strings.Contains(line, "Arguments=") && strings.Contains(line, "--fleet-url") {
argsLine = line
break
}
}
require.NotEmpty(t, argsLine, "ServiceInstall Arguments line not found in template output")
assert.Contains(t, argsLine, `--eua-token="[EUA_TOKEN]"`,
"eua-token flag should be in ServiceInstall Arguments")
})
t.Run("EUA_TOKEN property and flag absent when disabled", func(t *testing.T) {
opt := baseOpt
opt.EnableEUATokenProperty = false
var buf bytes.Buffer
err := windowsWixTemplate.Execute(&buf, opt)
require.NoError(t, err)
output := buf.String()
assert.NotContains(t, output, `EUA_TOKEN`)
assert.NotContains(t, output, `--eua-token`)
})
}
+6 -1
View File
@@ -66,6 +66,11 @@ var windowsWixTemplate = template.Must(template.New("").Option("missingkey=error
{{ else if .EndUserEmail }}
{{ $endUserEmailArg = printf " --end-user-email \"%s\"" .EndUserEmail }}
{{ end }}
{{ $euaTokenArg := "" }}
{{ if .EnableEUATokenProperty }}
<Property Id="EUA_TOKEN" Value="dummy"/>
{{ $euaTokenArg = " --eua-token=\"[EUA_TOKEN]\"" }}
{{ end }}
<MediaTemplate EmbedCab="yes" />
@@ -109,7 +114,7 @@ var windowsWixTemplate = template.Must(template.New("").Option("missingkey=error
Start="auto"
Type="ownProcess"
Description="This service runs Fleet's osquery runtime and autoupdater (Orbit)."
Arguments='--root-dir "[ORBITROOT]." --log-file "[System64Folder]config\systemprofile\AppData\Local\FleetDM\Orbit\Logs\orbit-osquery.log" --fleet-url "[FLEET_URL]"{{ if .FleetCertificate }} --fleet-certificate "[ORBITROOT]fleet.pem"{{ end }}{{ if .EnrollSecret }} --enroll-secret-path "[ORBITROOT]secret.txt"{{ end }}{{if .Insecure }} --insecure{{ end }}{{ if .Debug }} --debug{{ end }}{{ if .UpdateURL }} --update-url "{{ .UpdateURL }}"{{ end }}{{ if .UpdateTLSServerCertificate }} --update-tls-certificate "[ORBITROOT]update.pem"{{ end }}{{ if .DisableUpdates }} --disable-updates{{ end }} --fleet-desktop="[FLEET_DESKTOP]" --desktop-channel {{ .DesktopChannel }}{{ if .FleetDesktopAlternativeBrowserHost }} --fleet-desktop-alternative-browser-host {{ .FleetDesktopAlternativeBrowserHost }}{{ end }} --orbit-channel "{{ .OrbitChannel }}" --osqueryd-channel "{{ .OsquerydChannel }}" --enable-scripts="[ENABLE_SCRIPTS]" {{ if and (ne .HostIdentifier "") (ne .HostIdentifier "uuid") }}--host-identifier={{ .HostIdentifier }}{{ end }}{{ $endUserEmailArg }}{{ if .OsqueryDB }} --osquery-db="{{ .OsqueryDB }}"{{ end }}{{ if .DisableSetupExperience }} --disable-setup-experience{{ end }}'
Arguments='--root-dir "[ORBITROOT]." --log-file "[System64Folder]config\systemprofile\AppData\Local\FleetDM\Orbit\Logs\orbit-osquery.log" --fleet-url "[FLEET_URL]"{{ if .FleetCertificate }} --fleet-certificate "[ORBITROOT]fleet.pem"{{ end }}{{ if .EnrollSecret }} --enroll-secret-path "[ORBITROOT]secret.txt"{{ end }}{{if .Insecure }} --insecure{{ end }}{{ if .Debug }} --debug{{ end }}{{ if .UpdateURL }} --update-url "{{ .UpdateURL }}"{{ end }}{{ if .UpdateTLSServerCertificate }} --update-tls-certificate "[ORBITROOT]update.pem"{{ end }}{{ if .DisableUpdates }} --disable-updates{{ end }} --fleet-desktop="[FLEET_DESKTOP]" --desktop-channel {{ .DesktopChannel }}{{ if .FleetDesktopAlternativeBrowserHost }} --fleet-desktop-alternative-browser-host {{ .FleetDesktopAlternativeBrowserHost }}{{ end }} --orbit-channel "{{ .OrbitChannel }}" --osqueryd-channel "{{ .OsquerydChannel }}" --enable-scripts="[ENABLE_SCRIPTS]" {{ if and (ne .HostIdentifier "") (ne .HostIdentifier "uuid") }}--host-identifier={{ .HostIdentifier }}{{ end }}{{ $endUserEmailArg }}{{ $euaTokenArg }}{{ if .OsqueryDB }} --osquery-db="{{ .OsqueryDB }}"{{ end }}{{ if .DisableSetupExperience }} --disable-setup-experience{{ end }}'
>
<util:ServiceConfig
FirstFailureActionType="restart"