diff --git a/cmd/fleetctl/package.go b/cmd/fleetctl/package.go index bd3491fd49..9d89e91876 100644 --- a/cmd/fleetctl/package.go +++ b/cmd/fleetctl/package.go @@ -212,6 +212,12 @@ func packageCommand() *cli.Command { EnvVars: []string{"FLEETCTL_USE_SYSTEM_CONFIGURATION"}, Destination: &opt.UseSystemConfiguration, }, + &cli.BoolFlag{ + Name: "enable-scripts", + Usage: "Enable script execution", + EnvVars: []string{"FLEETCTL_ENABLE_SCRIPTS"}, + Destination: &opt.EnableScripts, + }, }, Action: func(c *cli.Context) error { if opt.FleetURL != "" || opt.EnrollSecret != "" { diff --git a/orbit/changes/13310-scripts-config b/orbit/changes/13310-scripts-config new file mode 100644 index 0000000000..502179c4ff --- /dev/null +++ b/orbit/changes/13310-scripts-config @@ -0,0 +1,2 @@ +* Add a `--enable-scripts` flag to `fleetctl package` to build a package capable of script execution +* Allow script execution to be enabled by providing a configuration profile with `PayloadType` equal to `com.fleetdm.fleetd.config` and a key `ScriptsEnabled` set to `true`. diff --git a/orbit/cmd/orbit/orbit.go b/orbit/cmd/orbit/orbit.go index 4637fb66a4..98e35ebf52 100644 --- a/orbit/cmd/orbit/orbit.go +++ b/orbit/cmd/orbit/orbit.go @@ -170,6 +170,11 @@ func main() { EnvVars: []string{"ORBIT_USE_SYSTEM_CONFIGURATION"}, Hidden: true, }, + &cli.BoolFlag{ + Name: "enable-scripts", + Usage: "Enable script execution", + EnvVars: []string{"ORBIT_ENABLE_SCRIPTS"}, + }, } app.Before = func(c *cli.Context) error { // handle old installations, which had default root dir set to /var/lib/orbit @@ -266,8 +271,6 @@ func main() { // alarms when users look into the orbit logs, it's perfectly normal to // not have a configuration profile, or to get into this situation in // operating systems that don't have profile support. - case errors.Is(err, profiles.ErrNotImplemented), errors.Is(err, profiles.ErrNotFound): - log.Debug().Msgf("reading configuration profile: %v", err) case err != nil: log.Error().Err(err).Msg("reading configuration profile") case config.EnrollSecret == "" || config.FleetURL == "": diff --git a/orbit/pkg/packaging/linux_shared.go b/orbit/pkg/packaging/linux_shared.go index 6898b270fa..0ec8823538 100644 --- a/orbit/pkg/packaging/linux_shared.go +++ b/orbit/pkg/packaging/linux_shared.go @@ -288,6 +288,7 @@ ORBIT_FLEET_DESKTOP_ALTERNATIVE_BROWSER_HOST={{ .FleetDesktopAlternativeBrowserH {{ if .UpdateTLSServerCertificate }}ORBIT_UPDATE_TLS_CERTIFICATE=/opt/orbit/update.pem{{ end }} {{ if .EnrollSecret }}ORBIT_ENROLL_SECRET={{.EnrollSecret}}{{ end }} {{ if .Debug }}ORBIT_DEBUG=true{{ end }} +{{ if .EnableScripts }}ORBIT_ENABLE_SCRIPTS=true{{ end }} `)) func writeEnvFile(opt Options, rootPath string) error { diff --git a/orbit/pkg/packaging/macos_templates.go b/orbit/pkg/packaging/macos_templates.go index d065daf64e..dfd5c7b7e2 100644 --- a/orbit/pkg/packaging/macos_templates.go +++ b/orbit/pkg/packaging/macos_templates.go @@ -125,6 +125,10 @@ var macosLaunchdTemplate = template.Must(template.New("").Option("missingkey=err ORBIT_USE_SYSTEM_CONFIGURATION {{ .UseSystemConfiguration }} {{- end }} + {{- if .EnableScripts }} + ORBIT_ENABLE_SCRIPTS + {{ .EnableScripts }} + {{- end }} {{- if .DisableUpdates }} ORBIT_DISABLE_UPDATES true diff --git a/orbit/pkg/packaging/packaging.go b/orbit/pkg/packaging/packaging.go index 27b8686719..77e56617ff 100644 --- a/orbit/pkg/packaging/packaging.go +++ b/orbit/pkg/packaging/packaging.go @@ -111,6 +111,8 @@ type Options struct { // EnrollSecret from a system configuration that's present on the host. // Currently only macOS profiles are supported. UseSystemConfiguration bool + // EnableScripts enables script execution on the agent. + EnableScripts bool } func initializeTempDir() (string, error) { diff --git a/orbit/pkg/packaging/windows_templates.go b/orbit/pkg/packaging/windows_templates.go index 9bcd161a87..a2d25049bd 100644 --- a/orbit/pkg/packaging/windows_templates.go +++ b/orbit/pkg/packaging/windows_templates.go @@ -99,7 +99,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 }}{{ if .Desktop }} --fleet-desktop --desktop-channel {{ .DesktopChannel }}{{ if .FleetDesktopAlternativeBrowserHost }} --fleet-desktop-alternative-browser-host {{ .FleetDesktopAlternativeBrowserHost }}{{ end }}{{ end }} --orbit-channel "{{ .OrbitChannel }}" --osqueryd-channel "{{ .OsquerydChannel }}"' + 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 }}{{ if .Desktop }} --fleet-desktop --desktop-channel {{ .DesktopChannel }}{{ if .FleetDesktopAlternativeBrowserHost }} --fleet-desktop-alternative-browser-host {{ .FleetDesktopAlternativeBrowserHost }}{{ end }}{{ end }} --orbit-channel "{{ .OrbitChannel }}" --osqueryd-channel "{{ .OsquerydChannel }}" {{ if .EnableScripts }} --enable-scripts{{ end }}' > {{ .EnrollSecret }} FleetURL {{ .ServerURL }} + EnableScripts + PayloadDisplayName Fleetd configuration PayloadIdentifier diff --git a/server/mdm/apple/mobileconfig/profiles_test.go b/server/mdm/apple/mobileconfig/profiles_test.go new file mode 100644 index 0000000000..4d8a9d243b --- /dev/null +++ b/server/mdm/apple/mobileconfig/profiles_test.go @@ -0,0 +1,41 @@ +package mobileconfig + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" + "howett.net/plist" +) + +func TestFleetdProfileTemplate(t *testing.T) { + cases := []FleetdProfileOptions{ + {}, + {PayloadType: "", EnrollSecret: "", ServerURL: ""}, + {PayloadType: "test.example", EnrollSecret: "abc", ServerURL: "https://test.example"}, + } + + for _, c := range cases { + // execute template + var prof bytes.Buffer + err := FleetdProfileTemplate.Execute(&prof, c) + require.NoError(t, err) + + // unmarshal plist and check values + var out map[string]any + _, err = plist.Unmarshal(prof.Bytes(), &out) + require.NoError(t, err) + contents, ok := out["PayloadContent"].([]any) + require.True(t, ok) + pc, ok := contents[0].(map[string]any) + require.True(t, ok) + require.Equal(t, c.EnrollSecret, pc["EnrollSecret"]) + require.Equal(t, c.ServerURL, pc["FleetURL"]) + require.Equal(t, c.PayloadType, pc["PayloadType"]) + // script execution is always enabled + enableScripts, ok := pc["EnableScripts"].(bool) + require.True(t, ok) + require.True(t, enableScripts) + + } +}