diff --git a/changes/13338-use-local-wix b/changes/13338-use-local-wix new file mode 100644 index 0000000000..18dd282933 --- /dev/null +++ b/changes/13338-use-local-wix @@ -0,0 +1,2 @@ +* Add the option to use locally-installed WiX v3 binaries when generating the Fleetd installer for +Windows on a Windows machine. diff --git a/cmd/fleetctl/package.go b/cmd/fleetctl/package.go index 9d89e91876..5547273426 100644 --- a/cmd/fleetctl/package.go +++ b/cmd/fleetctl/package.go @@ -182,6 +182,12 @@ func packageCommand() *cli.Command { EnvVars: []string{"FLEETCTL_NATIVE_TOOLING"}, Destination: &opt.NativeTooling, }, + &cli.StringFlag{ + Name: "local-wix-dir", + Usage: "Use local install of WiX instead of Docker Hub (only available on Windows w/ WiX v3)", + EnvVars: []string{"FLEETCTL_LOCAL_WIX_DIR"}, + Destination: &opt.LocalWixDir, + }, &cli.StringFlag{ Name: "macos-devid-pem-content", Usage: "Dev ID certificate keypair content in PEM format", @@ -262,6 +268,11 @@ func packageCommand() *cli.Command { return errors.New("native tooling is only available in Linux") } + if opt.LocalWixDir != "" && runtime.GOOS != "windows" { + return errors.New(`Could not use local WiX to generate an osquery installer. This option is only available on Windows. + Visit https://wixtoolset.org/ for more information about how to use WiX.`) + } + if opt.FleetCertificate != "" { err := checkPEMCertificate(opt.FleetCertificate) if err != nil { diff --git a/orbit/pkg/packaging/packaging.go b/orbit/pkg/packaging/packaging.go index 77e56617ff..cc7212ce10 100644 --- a/orbit/pkg/packaging/packaging.go +++ b/orbit/pkg/packaging/packaging.go @@ -113,6 +113,9 @@ type Options struct { UseSystemConfiguration bool // EnableScripts enables script execution on the agent. EnableScripts bool + // LocalWixDir uses a Windows machine's local WiX installation instead of a containerized + // emulation to build an MSI fleetd installer + LocalWixDir string } func initializeTempDir() (string, error) { diff --git a/orbit/pkg/packaging/windows.go b/orbit/pkg/packaging/windows.go index 57151182eb..8833997535 100644 --- a/orbit/pkg/packaging/windows.go +++ b/orbit/pkg/packaging/windows.go @@ -150,7 +150,7 @@ func BuildMSI(opt Options) (string, error) { } } - if err := wix.Heat(tmpDir, opt.NativeTooling); err != nil { + if err := wix.Heat(tmpDir, opt.NativeTooling, opt.LocalWixDir); err != nil { return "", fmt.Errorf("package root files: %w", err) } @@ -158,11 +158,11 @@ func BuildMSI(opt Options) (string, error) { return "", fmt.Errorf("transform heat: %w", err) } - if err := wix.Candle(tmpDir, opt.NativeTooling); err != nil { + if err := wix.Candle(tmpDir, opt.NativeTooling, opt.LocalWixDir); err != nil { return "", fmt.Errorf("build package: %w", err) } - if err := wix.Light(tmpDir, opt.NativeTooling); err != nil { + if err := wix.Light(tmpDir, opt.NativeTooling, opt.LocalWixDir); err != nil { return "", fmt.Errorf("build package: %w", err) } diff --git a/orbit/pkg/packaging/wix/wix.go b/orbit/pkg/packaging/wix/wix.go index a325238dd6..06b8871bc2 100644 --- a/orbit/pkg/packaging/wix/wix.go +++ b/orbit/pkg/packaging/wix/wix.go @@ -18,10 +18,10 @@ const ( // The Heat command creates XML fragments allowing WiX to include the entire // directory. See // https://wixtoolset.org/documentation/manual/v3/overview/heat.html. -func Heat(path string, native bool) error { +func Heat(path string, native bool, localWixDir string) error { var args []string - if !native { + if !native && localWixDir == "" { args = append( args, "docker", "run", "--rm", "--platform", "linux/amd64", @@ -30,8 +30,13 @@ func Heat(path string, native bool) error { ) } + heatPath := `heat` + if localWixDir != "" { + heatPath = localWixDir + `\heat.exe` + } + args = append(args, - "heat", "dir", "root", // command + heatPath, "dir", "root", // command "-out", "heat.wxs", "-gg", "-g1", // generate UUIDs (required by wix) "-cg", "OrbitFiles", // set ComponentGroup name @@ -43,7 +48,7 @@ func Heat(path string, native bool) error { cmd := exec.Command(args[0], args[1:]...) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - if native { + if native || localWixDir != "" { cmd.Dir = path } @@ -58,10 +63,10 @@ func Heat(path string, native bool) error { // // See // https://wixtoolset.org/documentation/manual/v3/overview/candle.html. -func Candle(path string, native bool) error { +func Candle(path string, native bool, localWixDir string) error { var args []string - if !native { + if !native && localWixDir == "" { args = append( args, "docker", "run", "--rm", "--platform", "linux/amd64", @@ -70,8 +75,12 @@ func Candle(path string, native bool) error { ) } + candlePath := `candle` + if localWixDir != "" { + candlePath = localWixDir + `\candle.exe` + } args = append(args, - "candle", "heat.wxs", "main.wxs", // command + candlePath, "heat.wxs", "main.wxs", // command "-ext", "WixUtilExtension", "-arch", "x64", ) @@ -79,7 +88,7 @@ func Candle(path string, native bool) error { cmd := exec.Command(args[0], args[1:]...) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - if native { + if native || localWixDir != "" { cmd.Dir = path } @@ -94,10 +103,10 @@ func Candle(path string, native bool) error { // // See // https://wixtoolset.org/documentation/manual/v3/overview/light.html. -func Light(path string, native bool) error { +func Light(path string, native bool, localWixDir string) error { var args []string - if !native { + if !native && localWixDir == "" { args = append( args, "docker", "run", "--rm", "--platform", "linux/amd64", @@ -106,8 +115,12 @@ func Light(path string, native bool) error { ) } + lightPath := `light` + if localWixDir != "" { + lightPath = localWixDir + `\light.exe` + } args = append(args, - "light", "heat.wixobj", "main.wixobj", // command + lightPath, "heat.wixobj", "main.wixobj", // command "-ext", "WixUtilExtension", "-b", "root", // Set directory for finding heat files "-out", "orbit.msi", @@ -117,7 +130,7 @@ func Light(path string, native bool) error { cmd := exec.Command(args[0], args[1:]...) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - if native { + if native || localWixDir != "" { cmd.Dir = path }