fleet/orbit/pkg/packaging/windows.go
Lucas Manuel Rodriguez ecdfd627b6
Fleet Desktop MVP (#4530)
* WIP

* WIP2

* Fix orbit and fleetctl tests

* Amend macos-app default

* Add some fixes

* Use fleetctl updates roots command

* Add more fixes to Updater

* Fixes to app publishing and downloading

* Add more changes to support fleetctl cross generation

* Amend comment

* Add pkg generation to ease testing

* Make more fixes

* Add changes entry

* Add legacy targets (until our TUF system exposes the new app)

* Fix fleetctl preview

* Fix bool flag

* Fix orbit logic for disabled-updates and dev-mode

* Fix TestPreview

* Remove constant and fix zip-slip attack (codeql)

* Return unknown error

* Fix updater's checkExec

* Add support for executable signing in init_tuf.sh

* Try only signing orbit

* Fix init_tuf.sh targets, macos-app only for osqueryd

* Specify GOARCH to support M1s

* Add workflow to generate osqueryd.app.tar.gz

* Use 5.2.2 on init_tuf.sh

* Add unit test for tar.gz target

* Use artifacts instead of releases

* Remove copy paste residue

* Fleet Desktop Packaging WIP

* Ignore gosec warning

* Trigger on PR too

* Install Go in workflow

* Pass url parameter to desktop app

* Fix fleetctl package

* Final set of changes for v1 of Fleet Desktop

* Add changes

* PR fixes

* Fix CI build

* add larger menu bar icon

* Add transparency item

* Delete host_device_auth entry on host deletion

* Add SetTargetChannel

* Update white logo and add desktop to update runner

* Add fleet-desktop monitoring to orbit

* Define fleet-desktop app exec name

* Fix update runner creation

* Add API test before enabling the My device menu item

Co-authored-by: Zach Wasserman <zach@fleetdm.com>
2022-03-21 14:53:53 -03:00

139 lines
3.8 KiB
Go

package packaging
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"github.com/fleetdm/fleet/v4/orbit/pkg/constant"
"github.com/fleetdm/fleet/v4/orbit/pkg/packaging/wix"
"github.com/fleetdm/fleet/v4/orbit/pkg/update"
"github.com/fleetdm/fleet/v4/pkg/file"
"github.com/fleetdm/fleet/v4/pkg/secure"
"github.com/rs/zerolog/log"
)
// BuildMSI builds a Windows .msi.
func BuildMSI(opt Options) (string, error) {
tmpDir, err := initializeTempDir()
if err != nil {
return "", err
}
defer os.RemoveAll(tmpDir)
filesystemRoot := filepath.Join(tmpDir, "root")
if err := secure.MkdirAll(filesystemRoot, constant.DefaultDirMode); err != nil {
return "", fmt.Errorf("create root dir: %w", err)
}
orbitRoot := filesystemRoot
if err := secure.MkdirAll(orbitRoot, constant.DefaultDirMode); err != nil {
return "", fmt.Errorf("create orbit dir: %w", err)
}
// Initialize autoupdate metadata
updateOpt := update.DefaultOptions
updateOpt.RootDirectory = orbitRoot
updateOpt.Targets = update.WindowsTargets
// Override default channels with the provided values.
updateOpt.Targets.SetTargetChannel("orbit", opt.OrbitChannel)
updateOpt.Targets.SetTargetChannel("osqueryd", opt.OsquerydChannel)
updateOpt.ServerURL = opt.UpdateURL
if opt.UpdateRoots != "" {
updateOpt.RootKeys = opt.UpdateRoots
}
updatesData, err := InitializeUpdates(updateOpt)
if err != nil {
return "", fmt.Errorf("initialize updates: %w", err)
}
log.Debug().Stringer("data", updatesData).Msg("updates initialized")
if opt.Version == "" {
// We set the package version to orbit's latest version.
opt.Version = updatesData.OrbitVersion
}
// Write files
if err := writeSecret(opt, orbitRoot); err != nil {
return "", fmt.Errorf("write enroll secret: %w", err)
}
if err := writeOsqueryFlagfile(opt, orbitRoot); err != nil {
return "", fmt.Errorf("write flagfile: %w", err)
}
if err := writeOsqueryCertPEM(opt, orbitRoot); err != nil {
return "", fmt.Errorf("write certs.pem: %w", err)
}
if opt.FleetCertificate != "" {
if err := writeCertificate(opt, orbitRoot); err != nil {
return "", fmt.Errorf("write fleet certificate: %w", err)
}
}
if err := writeWixFile(opt, tmpDir); err != nil {
return "", fmt.Errorf("write wix file: %w", err)
}
if runtime.GOOS == "windows" {
// Explicitly grant read access, otherwise within the Docker container there are permissions
// errors.
out, err := exec.Command("icacls", tmpDir, "/grant", "everyone:R", "/t").CombinedOutput()
if err != nil {
fmt.Println(string(out))
return "", fmt.Errorf("icacls: %w", err)
}
}
if err := wix.Heat(tmpDir); err != nil {
return "", fmt.Errorf("package root files: %w", err)
}
if err := wix.TransformHeat(filepath.Join(tmpDir, "heat.wxs")); err != nil {
return "", fmt.Errorf("transform heat: %w", err)
}
if err := wix.Candle(tmpDir); err != nil {
return "", fmt.Errorf("build package: %w", err)
}
if err := wix.Light(tmpDir); err != nil {
return "", fmt.Errorf("build package: %w", err)
}
filename := "fleet-osquery.msi"
if err := file.Copy(filepath.Join(tmpDir, "orbit.msi"), filename, constant.DefaultFileMode); err != nil {
return "", fmt.Errorf("rename msi: %w", err)
}
log.Info().Str("path", filename).Msg("wrote msi package")
return filename, nil
}
func writeWixFile(opt Options, rootPath string) error {
// PackageInfo is metadata for the pkg
path := filepath.Join(rootPath, "main.wxs")
if err := secure.MkdirAll(filepath.Dir(path), constant.DefaultDirMode); err != nil {
return fmt.Errorf("mkdir: %w", err)
}
var contents bytes.Buffer
if err := windowsWixTemplate.Execute(&contents, opt); err != nil {
return fmt.Errorf("execute template: %w", err)
}
if err := ioutil.WriteFile(path, contents.Bytes(), 0o666); err != nil {
return fmt.Errorf("write file: %w", err)
}
return nil
}