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)
+
+ }
+}