From ecf2346ace6860c57a1c31eb5aff1bbcaaf0bcce Mon Sep 17 00:00:00 2001 From: Dante Catalfamo <43040593+dantecatalfamo@users.noreply.github.com> Date: Wed, 17 Jul 2024 16:07:59 -0400 Subject: [PATCH] Add support for Linux ARM64 (#19931) #1845 Co-authored-by: Lucas Manuel Rodriguez Co-authored-by: Roberto Dip --- .github/workflows/fleet-and-orbit.yml | 2 +- .../workflows/generate-desktop-targets.yml | 28 ++++++++++ .../workflows/generate-osqueryd-targets.yml | 29 ++++++++++ .github/workflows/goreleaser-orbit.yaml | 33 ++++++++++++ Makefile | 19 ++++++- changes/1845-linux-arm64 | 2 + cmd/fleetctl/package.go | 20 +++++++ ee/fleetctl/updates.go | 4 +- orbit/README.md | 1 + orbit/changes/1845-linux-arm64 | 1 + orbit/cmd/orbit/orbit.go | 6 ++- orbit/goreleaser-linux-arm64.yml | 40 ++++++++++++++ orbit/pkg/packaging/linux_shared.go | 20 +++++-- orbit/pkg/packaging/packaging.go | 7 +++ orbit/pkg/update/options.go | 27 ++++++++++ ...ptions_linux.go => options_linux_amd64.go} | 0 orbit/pkg/update/options_linux_arm64.go | 14 +++++ orbit/pkg/update/update.go | 34 ++++++++++++ orbit/pkg/update/update_test.go | 7 +++ orbit/tools/cleanup/cleanup_macos.sh | 8 ++- tools/test_extensions/hello_world/build.sh | 4 +- .../download-artifacts/download-artifacts.go | 29 +++++----- tools/tuf/releaser.sh | 16 ++++-- tools/tuf/test/create_repository.sh | 51 ++++++++++++++++-- tools/tuf/test/docker_package.sh | 2 +- tools/tuf/test/gen_pkgs.sh | 54 +++++++++++++++++-- tools/tuf/test/main.sh | 4 +- 27 files changed, 424 insertions(+), 38 deletions(-) create mode 100644 changes/1845-linux-arm64 create mode 100644 orbit/changes/1845-linux-arm64 create mode 100644 orbit/goreleaser-linux-arm64.yml rename orbit/pkg/update/{options_linux.go => options_linux_amd64.go} (100%) create mode 100644 orbit/pkg/update/options_linux_arm64.go diff --git a/.github/workflows/fleet-and-orbit.yml b/.github/workflows/fleet-and-orbit.yml index 6c222b3774..b4ada881ec 100644 --- a/.github/workflows/fleet-and-orbit.yml +++ b/.github/workflows/fleet-and-orbit.yml @@ -296,7 +296,7 @@ jobs: - name: Build Repository and run TUF server env: - SYSTEMS: "macos windows linux" + SYSTEMS: "macos windows linux linux-arm64" PKG_FLEET_URL: ${{ needs.gen.outputs.address }} PKG_TUF_URL: http://localhost:8081 DEB_FLEET_URL: ${{ needs.gen.outputs.address }} diff --git a/.github/workflows/generate-desktop-targets.yml b/.github/workflows/generate-desktop-targets.yml index 9dff22841a..56cd06fede 100644 --- a/.github/workflows/generate-desktop-targets.yml +++ b/.github/workflows/generate-desktop-targets.yml @@ -157,3 +157,31 @@ jobs: with: name: desktop.tar.gz path: desktop.tar.gz + + desktop-linux-arm64: + runs-on: ubuntu-latest + steps: + + - name: Harden Runner + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + egress-policy: audit + + - name: Install Go + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version: ${{ vars.GO_VERSION }} + + - name: Checkout + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + - name: Generate desktop.tar.gz + run: | + FLEET_DESKTOP_VERSION=$FLEET_DESKTOP_VERSION \ + make desktop-linux-arm64 + + - name: Upload desktop.tar.gz + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # 4.3.3 + with: + name: desktop-arm64.tar.gz + path: desktop.tar.gz diff --git a/.github/workflows/generate-osqueryd-targets.yml b/.github/workflows/generate-osqueryd-targets.yml index f7f377d17d..12e08bddac 100644 --- a/.github/workflows/generate-osqueryd-targets.yml +++ b/.github/workflows/generate-osqueryd-targets.yml @@ -76,6 +76,35 @@ jobs: name: osqueryd path: opt/osquery/bin/osqueryd + generate-linux-arm64: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + egress-policy: audit + + - name: Checkout + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + - name: Install file + run: | + sudo apt-get install -y file + + - name: Download and extract osqueryd for linux-arm64 + run: | + curl -L https://github.com/osquery/osquery/releases/download/${{ env.OSQUERY_VERSION }}/osquery_${{ env.OSQUERY_VERSION }}-1.linux_arm64.deb --output osquery.deb + ar x osquery.deb + tar xf data.tar.gz + chmod +x ./opt/osquery/bin/osqueryd + file ./opt/osquery/bin/osqueryd | grep aarch64 + + - name: Upload osqueryd for linux-arm64 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v2 + with: + name: osqueryd-arm64 + path: opt/osquery/bin/osqueryd + generate-windows: runs-on: windows-latest steps: diff --git a/.github/workflows/goreleaser-orbit.yaml b/.github/workflows/goreleaser-orbit.yaml index 1ce2386dd9..d866e140d4 100644 --- a/.github/workflows/goreleaser-orbit.yaml +++ b/.github/workflows/goreleaser-orbit.yaml @@ -106,6 +106,39 @@ jobs: name: orbit-linux path: dist/orbit_linux_amd64_v1/orbit + goreleaser-linux-arm64: + runs-on: ubuntu-20.04 + permissions: + contents: read + steps: + - name: Harden Runner + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + egress-policy: audit + + - name: Checkout + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + # Note that goreleaser does not like the orbit- prefixed flag unless you use the closed-source + # paid version. We pay for goreleaser, but using the closed source build would weaken our + # supply-chain integrity goals, so we hack around it by replacing the tag. + - name: Replace tag + run: git tag $(echo ${{ github.ref_name }} | sed -e 's/orbit-//g') && git tag -d ${{ github.ref_name }} + + - name: Set up Go + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version: ${{ vars.GO_VERSION }} + + - name: Run GoReleaser + run: go run github.com/goreleaser/goreleaser@56c9d09a1b925e2549631c6d180b0a1c2ebfac82 release --debug --rm-dist --skip-publish -f orbit/goreleaser-linux-arm64.yml # v1.20.0 + + - name: Upload + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # 4.3.3 + with: + name: orbit-linux-arm64 + path: dist/orbit_linux_arm64_v1/orbit + goreleaser-windows: runs-on: windows-2022 permissions: diff --git a/Makefile b/Makefile index d90f615c9a..8f7cf455d5 100644 --- a/Makefile +++ b/Makefile @@ -249,13 +249,15 @@ fleetd-tables-windows: GOOS=windows GOARCH=amd64 go build -o fleetd_tables_windows.exe ./orbit/cmd/fleetd_tables fleetd-tables-linux: GOOS=linux GOARCH=amd64 go build -o fleetd_tables_linux.ext ./orbit/cmd/fleetd_tables +fleetd-tables-linux-arm64: + GOOS=linux GOARCH=arm64 go build -o fleetd_tables_linux_arm64.ext ./orbit/cmd/fleetd_tables fleetd-tables-darwin: GOOS=darwin GOARCH=amd64 go build -o fleetd_tables_darwin.ext ./orbit/cmd/fleetd_tables fleetd-tables-darwin_arm: GOOS=darwin GOARCH=arm64 CGO_ENABLED=1 go build -o fleetd_tables_darwin_arm.ext ./orbit/cmd/fleetd_tables fleetd-tables-darwin-universal: fleetd-tables-darwin fleetd-tables-darwin_arm lipo -create fleetd_tables_darwin.ext fleetd_tables_darwin_arm.ext -output fleetd_tables_darwin_universal.ext -fleetd-tables-all: fleetd-tables-windows fleetd-tables-linux fleetd-tables-darwin-universal +fleetd-tables-all: fleetd-tables-windows fleetd-tables-linux fleetd-tables-darwin-universal fleetd-tables-linux-arm64 fleetd-tables-clean: rm -f fleetd_tables_windows.exe fleetd_tables_linux.ext fleetd_tables_darwin.ext fleetd_tables_darwin_arm.ext fleetd_tables_darwin_universal.ext @@ -465,6 +467,21 @@ desktop-linux: tar czf desktop.tar.gz fleet-desktop && \ rm -r fleet-desktop" +# Build desktop executable for Linux ARM. +# +# Usage: +# FLEET_DESKTOP_VERSION=0.0.1 make desktop-linux-arm64 +# +# Output: desktop.tar.gz +desktop-linux-arm64: + docker build -f Dockerfile-desktop-linux -t desktop-linux-builder . + docker run --rm -v $(shell pwd):/output desktop-linux-builder /bin/bash -c "\ + mkdir /output/fleet-desktop && \ + GOARCH=arm64 go build -o /output/fleet-desktop/fleet-desktop -ldflags "-X=main.version=$(FLEET_DESKTOP_VERSION)" /usr/src/fleet/orbit/cmd/desktop && \ + cd /output && \ + tar czf desktop.tar.gz fleet-desktop && \ + rm -r fleet-desktop" + # Build orbit executable for Windows. # This generates orbit executable for Windows that includes versioninfo binary properties # These properties can be displayed when right-click on the binary in Windows Explorer. diff --git a/changes/1845-linux-arm64 b/changes/1845-linux-arm64 new file mode 100644 index 0000000000..6ebb53ff63 --- /dev/null +++ b/changes/1845-linux-arm64 @@ -0,0 +1,2 @@ +* Added support for generating fleetd packages for Linux ARM64 +* fleetctl: New `fleetctl package` --arch flag diff --git a/cmd/fleetctl/package.go b/cmd/fleetctl/package.go index 8b80fd3802..1cf3978c72 100644 --- a/cmd/fleetctl/package.go +++ b/cmd/fleetctl/package.go @@ -38,6 +38,12 @@ func packageCommand() *cli.Command { Usage: "Type of package to build", Required: true, }, + &cli.StringFlag{ + Name: "arch", + Usage: "Target CPU Architecture for the installer package (Only supported with '--type' deb or rpm)", + Destination: &opt.Architecture, + Value: "amd64", + }, &cli.StringFlag{ Name: "enroll-secret", Usage: "Enroll secret for authenticating to Fleet server", @@ -331,6 +337,20 @@ func packageCommand() *cli.Command { return errors.New("--use-system-configuration is only available for pkg installers") } + linuxPackage := false + switch c.String("type") { + case "deb", "rpm": + linuxPackage = true + } + + if opt.Architecture != packaging.ArchAmd64 && !linuxPackage { + return fmt.Errorf("can't use '--arch' with '--type %s'", c.String("type")) + } + + if opt.Architecture != packaging.ArchAmd64 && opt.Architecture != packaging.ArchArm64 { + return errors.New("arch must be one of ('amd64', 'arm64')") + } + var buildFunc func(packaging.Options) (string, error) switch c.String("type") { case "pkg": diff --git a/ee/fleetctl/updates.go b/ee/fleetctl/updates.go index 09010e62ee..8ef04ef1f6 100644 --- a/ee/fleetctl/updates.go +++ b/ee/fleetctl/updates.go @@ -259,7 +259,7 @@ func updatesAddFunc(c *cli.Context) error { case name == "desktop" && platform == "windows": // This is a special case for the desktop target on Windows. dstPath = filepath.Join(filepath.Dir(dstPath), constant.DesktopAppExecName+".exe") - case name == "desktop" && platform == "linux": + case name == "desktop" && (platform == "linux" || platform == "linux-arm64"): // This is a special case for the desktop target on Linux. dstPath += ".tar.gz" // The convention for Windows extensions is to use the extension `.ext.exe` @@ -352,7 +352,7 @@ func updatesRotateCommand() *cli.Command { Usage: "Rotate signing keys", ArgsUsage: "", Description: `Rotate the signing keys used for updates metadata signing. This should be used when keys are compromised or expiring. - + role must be one of ['root', 'targets', 'timestamp', 'snapshot'] `, Flags: updatesFlags(), diff --git a/orbit/README.md b/orbit/README.md index 1a55fc263e..6fc1f75d1e 100644 --- a/orbit/README.md +++ b/orbit/README.md @@ -16,6 +16,7 @@ For reference, here are the build configuration files: - [Goreleaser github workflow](../.github/workflows/goreleaser-orbit.yml) - Goreleaser configuration file for each platform: - [goreleaser-linux.yml](./goreleaser-linux.yml) + - [goreleaser-linux-arm64.yml](./goreleaser-linux-arm64.yml) - [goreleaser-macos.yml](./goreleaser-macos.yml) - [goreleaser-windows.yml](./goreleaser-windows.yml) diff --git a/orbit/changes/1845-linux-arm64 b/orbit/changes/1845-linux-arm64 new file mode 100644 index 0000000000..3b49f3fd4d --- /dev/null +++ b/orbit/changes/1845-linux-arm64 @@ -0,0 +1 @@ +* Added support for Linux ARM64 diff --git a/orbit/cmd/orbit/orbit.go b/orbit/cmd/orbit/orbit.go index 8a962b56d2..6cc9fe9f59 100644 --- a/orbit/cmd/orbit/orbit.go +++ b/orbit/cmd/orbit/orbit.go @@ -431,7 +431,11 @@ func main() { case "windows": opt.Targets["desktop"] = update.DesktopWindowsTarget case "linux": - opt.Targets["desktop"] = update.DesktopLinuxTarget + if runtime.GOARCH == "arm64" { + opt.Targets["desktop"] = update.DesktopLinuxArm64Target + } else { + opt.Targets["desktop"] = update.DesktopLinuxTarget + } default: log.Fatal().Str("GOOS", runtime.GOOS).Msg("unsupported GOOS for desktop target") } diff --git a/orbit/goreleaser-linux-arm64.yml b/orbit/goreleaser-linux-arm64.yml new file mode 100644 index 0000000000..33f9c2e01f --- /dev/null +++ b/orbit/goreleaser-linux-arm64.yml @@ -0,0 +1,40 @@ +project_name: orbit + +################################################################################################# +# If this is updated make sure to update the "How to build from source" section in the README.md. +################################################################################################# + +builds: + - id: orbit + dir: ./orbit/cmd/orbit/ + binary: orbit + env: + # CGO is enabled intentionally for Linux because some users need to be + # able to use the cgo versions of the networking libraries (see + # https://github.com/fleetdm/fleet/issues/8992) + - CGO_ENABLED=1 + goos: + - linux + goarch: + - arm64 + flags: + - -trimpath + ldflags: + - -X github.com/fleetdm/fleet/v4/orbit/pkg/build.Version={{.Version}} + - -X github.com/fleetdm/fleet/v4/orbit/pkg/build.Commit={{.Commit}} + - -X github.com/fleetdm/fleet/v4/orbit/pkg/build.Date={{.Date}} + +archives: + - id: orbit + builds: + - orbit + name_template: orbit_{{.Version}}_{{.Os}} + +checksum: + name_template: 'checksums.txt' + +snapshot: + name_template: "{{ .Tag }}-untagged" + +changelog: + skip: true diff --git a/orbit/pkg/packaging/linux_shared.go b/orbit/pkg/packaging/linux_shared.go index 8a1472a7f8..fd273f74c7 100644 --- a/orbit/pkg/packaging/linux_shared.go +++ b/orbit/pkg/packaging/linux_shared.go @@ -36,11 +36,19 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) { return "", fmt.Errorf("create orbit dir: %w", err) } + if opt.Architecture != ArchAmd64 && opt.Architecture != ArchArm64 { + return "", fmt.Errorf("Invalid architecture: %s", opt.Architecture) + } + // Initialize autoupdate metadata updateOpt := update.DefaultOptions updateOpt.RootDirectory = orbitRoot - updateOpt.Targets = update.LinuxTargets + if opt.Architecture == ArchArm64 { + updateOpt.Targets = update.LinuxArm64Targets + } else { + updateOpt.Targets = update.LinuxTargets + } updateOpt.ServerCertificatePath = opt.UpdateTLSServerCertificate if opt.UpdateTLSClientCertificate != "" { @@ -52,7 +60,11 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) { } if opt.Desktop { - updateOpt.Targets["desktop"] = update.DesktopLinuxTarget + if opt.Architecture == ArchArm64 { + updateOpt.Targets["desktop"] = update.DesktopLinuxArm64Target + } else { + updateOpt.Targets["desktop"] = update.DesktopLinuxTarget + } // Override default channel with the provided value. updateOpt.Targets.SetTargetChannel("desktop", opt.DesktopChannel) } @@ -157,7 +169,7 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) { }, // Symlink current into /opt/orbit/bin/orbit/orbit &files.Content{ - Source: "/opt/orbit/bin/orbit/linux/" + opt.OrbitChannel + "/orbit", + Source: "/opt/orbit/bin/orbit/" + updateOpt.Targets["orbit"].Platform + "/" + opt.OrbitChannel + "/orbit", Destination: "/opt/orbit/bin/orbit/orbit", Type: "symlink", FileInfo: &files.ContentFileInfo{ @@ -214,7 +226,7 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) { Name: "fleet-osquery", Version: opt.Version, Description: "Fleet osquery -- runtime and autoupdater", - Arch: "amd64", + Arch: opt.Architecture, Maintainer: "Fleet Device Management", Vendor: "Fleet Device Management", License: "https://github.com/fleetdm/fleet/blob/main/LICENSE", diff --git a/orbit/pkg/packaging/packaging.go b/orbit/pkg/packaging/packaging.go index fe3b576203..781c1c07cb 100644 --- a/orbit/pkg/packaging/packaging.go +++ b/orbit/pkg/packaging/packaging.go @@ -127,8 +127,15 @@ type Options struct { // OsqueryDB is the directory to use for the osquery database. // If not set, then the default is `$ORBIT_ROOT_DIR/osquery.db`. OsqueryDB string + // Architecture that the package is being built for. (amd64, arm64) + Architecture string } +const ( + ArchAmd64 string = "amd64" + ArchArm64 string = "arm64" +) + func initializeTempDir() (string, error) { // Initialize directories tmpDir, err := os.MkdirTemp("", "orbit-package") diff --git a/orbit/pkg/update/options.go b/orbit/pkg/update/options.go index a12e3c72fb..90cdcaf62a 100644 --- a/orbit/pkg/update/options.go +++ b/orbit/pkg/update/options.go @@ -41,6 +41,19 @@ var ( }, } + LinuxArm64Targets = Targets{ + "orbit": TargetInfo{ + Platform: "linux-arm64", + Channel: "stable", + TargetFile: "orbit", + }, + "osqueryd": TargetInfo{ + Platform: "linux-arm64", + Channel: "stable", + TargetFile: "osqueryd", + }, + } + WindowsTargets = Targets{ "orbit": TargetInfo{ Platform: "windows", @@ -82,6 +95,20 @@ var ( }, } + DesktopLinuxArm64Target = TargetInfo{ + Platform: "linux-arm64", + Channel: "stable", + TargetFile: "desktop.tar.gz", + ExtractedExecSubPath: []string{"fleet-desktop", constant.DesktopAppExecName}, + CustomCheckExec: func(execPath string) error { + cmd := exec.Command(execPath, "--help") + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("exec new version: %s: %w", string(out), err) + } + return nil + }, + } + NudgeMacOSTarget = TargetInfo{ Platform: "macos", Channel: "stable", diff --git a/orbit/pkg/update/options_linux.go b/orbit/pkg/update/options_linux_amd64.go similarity index 100% rename from orbit/pkg/update/options_linux.go rename to orbit/pkg/update/options_linux_amd64.go diff --git a/orbit/pkg/update/options_linux_arm64.go b/orbit/pkg/update/options_linux_arm64.go new file mode 100644 index 0000000000..5ed37667dd --- /dev/null +++ b/orbit/pkg/update/options_linux_arm64.go @@ -0,0 +1,14 @@ +package update + +import ( + "github.com/theupdateframework/go-tuf/client" +) + +var defaultOptions = Options{ + RootDirectory: "/opt/orbit", + ServerURL: defaultURL, + RootKeys: defaultRootKeys, + LocalStore: client.MemoryLocalStore(), + InsecureTransport: false, + Targets: LinuxArm64Targets, +} diff --git a/orbit/pkg/update/update.go b/orbit/pkg/update/update.go index 858d60b88d..c6b00df89e 100644 --- a/orbit/pkg/update/update.go +++ b/orbit/pkg/update/update.go @@ -493,11 +493,28 @@ func goosFromPlatform(platform string) (string, error) { return "darwin", nil case "windows", "linux": return platform, nil + case "linux-arm64": + return "linux", nil default: return "", fmt.Errorf("unknown platform: %s", platform) } } +func goarchFromPlatform(platform string) ([]string, error) { + switch platform { + case "macos", "macos-app": + return []string{"amd64", "arm64"}, nil + case "windows": + return []string{"amd64"}, nil + case "linux": + return []string{"amd64"}, nil + case "linux-arm64": + return []string{"arm64"}, nil + default: + return nil, fmt.Errorf("unknown platform: %s", platform) + } +} + // checkExec checks/verifies a downloaded executable target by executing it. func (u *Updater) checkExec(target, tmpPath string, customCheckExec func(execPath string) error) error { localTarget, err := u.localTarget(target) @@ -515,6 +532,23 @@ func (u *Updater) checkExec(target, tmpPath string, customCheckExec func(execPat return nil } + platformGOARCH, err := goarchFromPlatform(localTarget.Info.Platform) + if err != nil { + return err + } + var containsArch bool + for _, arch := range platformGOARCH { + if arch == runtime.GOARCH { + containsArch = true + } + } + if !containsArch && strings.HasSuffix(os.Args[0], "fleetctl") { + // Nothing to do, we can't reliably execute a + // cross-architecture binary. This happens when cross-building + // packages + return nil + } + if strings.HasSuffix(tmpPath, ".tar.gz") { if err := extractTarGz(tmpPath); err != nil { return fmt.Errorf("extract %q: %w", tmpPath, err) diff --git a/orbit/pkg/update/update_test.go b/orbit/pkg/update/update_test.go index 9a9b9c4fae..c756e043c3 100644 --- a/orbit/pkg/update/update_test.go +++ b/orbit/pkg/update/update_test.go @@ -39,6 +39,7 @@ func TestMakeRepoPath(t *testing.T) { }{ {platform: "linux", name: "osqueryd", version: "4.6.0", expected: "osqueryd/linux/4.6.0/osqueryd"}, {platform: "linux", name: "osqueryd", version: "3.3.2", expected: "osqueryd/linux/3.3.2/osqueryd"}, + {platform: "linux-arm64", name: "osqueryd", version: "3.3.2", expected: "osqueryd/linux-arm64/3.3.2/osqueryd"}, {platform: "macos", name: "osqueryd", version: "4.6.0", expected: "osqueryd/macos/4.6.0/osqueryd"}, {platform: "macos", name: "osqueryd", version: "3.3.2", expected: "osqueryd/macos/3.3.2/osqueryd"}, {platform: "macos-app", name: "osqueryd", version: "3.3.2", expected: "osqueryd/macos-app/3.3.2/osqueryd.app.tar.gz"}, @@ -89,6 +90,12 @@ func TestLocalTargetPaths(t *testing.T) { "root/bin/target/linux/stable/fleet-desktop/fleet-desktop", "root/bin/target/linux/stable/fleet-desktop", }, + { + DesktopLinuxArm64Target, + "root/bin/target/linux-arm64/stable/desktop.tar.gz", + "root/bin/target/linux-arm64/stable/fleet-desktop/fleet-desktop", + "root/bin/target/linux-arm64/stable/fleet-desktop", + }, { SwiftDialogMacOSTarget, "root/bin/target/macos/stable/swiftDialog.app.tar.gz", diff --git a/orbit/tools/cleanup/cleanup_macos.sh b/orbit/tools/cleanup/cleanup_macos.sh index 4a9c3b2283..2d66e72b02 100755 --- a/orbit/tools/cleanup/cleanup_macos.sh +++ b/orbit/tools/cleanup/cleanup_macos.sh @@ -23,7 +23,13 @@ if [ "$1" = "remove" ]; then # Give the parent process time to report the success before removing echo "inside remove process" >>/tmp/fleet_remove_log.txt sleep 15 - remove_fleet >>/tmp/fleet_remove_log.txt 2>&1 + if [ -z "$GITHUB_ACTIONS" ]; then + # We are root + remove_fleet >>/tmp/fleet_remove_log.txt 2>&1 + else + # Inside a github action, sudo is passwordless + sudo remove_fleet >>/tmp/fleet_remove_log.txt 2>&1 + fi else # We are in the parent shell, start the detached child and return success echo "Removing fleet, system will be unenrolled in 15 seconds..." diff --git a/tools/test_extensions/hello_world/build.sh b/tools/test_extensions/hello_world/build.sh index 154102b3ab..ee33ad46d8 100755 --- a/tools/test_extensions/hello_world/build.sh +++ b/tools/test_extensions/hello_world/build.sh @@ -2,11 +2,13 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -mkdir -p $SCRIPT_DIR/macos $SCRIPT_DIR/windows $SCRIPT_DIR/linux +mkdir -p $SCRIPT_DIR/macos $SCRIPT_DIR/windows $SCRIPT_DIR/linux $SCRIPT_DIR/linux-arm64 GOOS=darwin GOARCH=amd64 go build -o $SCRIPT_DIR/macos/hello_world_macos.ext $SCRIPT_DIR GOOS=windows GOARCH=amd64 go build -o $SCRIPT_DIR/windows/hello_world_windows.ext.exe $SCRIPT_DIR GOOS=linux GOARCH=amd64 go build -o $SCRIPT_DIR/linux/hello_world_linux.ext $SCRIPT_DIR +GOOS=linux GOARCH=arm64 go build -o $SCRIPT_DIR/linux-arm64/hello_world_linux.ext $SCRIPT_DIR GOOS=darwin GOARCH=amd64 go build -ldflags '-X "main.extensionName=test_extensions.hello_mars" -X "main.tableName=hello_mars" -X "main.columnValue=mars"' -o $SCRIPT_DIR/macos/hello_mars_macos.ext $SCRIPT_DIR GOOS=windows GOARCH=amd64 go build -ldflags '-X "main.extensionName=test_extensions.hello_mars" -X "main.tableName=hello_mars" -X "main.columnValue=mars"' -o $SCRIPT_DIR/windows/hello_mars_windows.ext.exe $SCRIPT_DIR GOOS=linux GOARCH=amd64 go build -ldflags '-X "main.extensionName=test_extensions.hello_mars" -X "main.tableName=hello_mars" -X "main.columnValue=mars"' -o $SCRIPT_DIR/linux/hello_mars_linux.ext $SCRIPT_DIR +GOOS=linux GOARCH=arm64 go build -ldflags '-X "main.extensionName=test_extensions.hello_mars" -X "main.tableName=hello_mars" -X "main.columnValue=mars"' -o $SCRIPT_DIR/linux-arm64/hello_mars_linux.ext $SCRIPT_DIR diff --git a/tools/tuf/download-artifacts/download-artifacts.go b/tools/tuf/download-artifacts/download-artifacts.go index b18d11515c..78a7e624fd 100644 --- a/tools/tuf/download-artifacts/download-artifacts.go +++ b/tools/tuf/download-artifacts/download-artifacts.go @@ -81,9 +81,10 @@ func orbitCommand() *cli.Command { }, Action: func(c *cli.Context) error { return downloadComponents("goreleaser-orbit.yaml", gitTag, map[string]string{ - "macos": "orbit-macos", - "linux": "orbit-linux", - "windows": "orbit-windows", + "macos": "orbit-macos", + "linux": "orbit-linux", + "linux-arm64": "orbit-linux-arm64", + "windows": "orbit-windows", }, outputDirectory, githubUsername, githubAPIToken, retry) }, } @@ -138,9 +139,10 @@ func desktopCommand() *cli.Command { }, Action: func(c *cli.Context) error { return downloadComponents("generate-desktop-targets.yml", gitBranch, map[string]string{ - "macos": "desktop.app.tar.gz", - "linux": "desktop.tar.gz", - "windows": "fleet-desktop.exe", + "macos": "desktop.app.tar.gz", + "linux": "desktop.tar.gz", + "linux-arm64": "desktop-arm64.tar.gz", + "windows": "fleet-desktop.exe", }, outputDirectory, githubUsername, githubAPIToken, retry) }, } @@ -250,7 +252,7 @@ func downloadComponents(workflowName string, headBranch string, artifactNames ma if err := os.RemoveAll(outputDirectory); err != nil { return err } - for _, osPath := range []string{"macos", "windows", "linux"} { + for _, osPath := range []string{"macos", "windows", "linux", "linux-arm64"} { if err := os.MkdirAll(filepath.Join(outputDirectory, osPath), constant.DefaultDirMode); err != nil { return err } @@ -292,6 +294,8 @@ func downloadComponents(workflowName string, headBranch string, artifactNames ma for _, artifact := range artifactList.Artifacts { if *artifact.Name == artifactNames["linux"] { urls["linux"] = *artifact.ArchiveDownloadURL + } else if *artifact.Name == artifactNames["linux-arm64"] { + urls["linux-arm64"] = *artifact.ArchiveDownloadURL } else if *artifact.Name == artifactNames["macos"] { urls["macos"] = *artifact.ArchiveDownloadURL } else if *artifact.Name == artifactNames["windows"] { @@ -300,13 +304,13 @@ func downloadComponents(workflowName string, headBranch string, artifactNames ma fmt.Printf("skipping artifact name: %q\n", *artifact.Name) } } - if len(urls) == 3 || !retry { + if len(urls) == 4 || !retry { break } fmt.Printf("All artifacts are not available yet, the workflow might still be running, retrying in 60s...\n") time.Sleep(60 * time.Second) } - if len(urls) != 3 { + if len(urls) != 4 { return fmt.Errorf("missing some artifact: %+v", urls) } for osName, downloadURL := range urls { @@ -368,9 +372,10 @@ func osquerydCommand() *cli.Command { }, Action: func(c *cli.Context) error { return downloadComponents("generate-osqueryd-targets.yml", gitBranch, map[string]string{ - "macos": "osqueryd.app.tar.gz", - "linux": "osqueryd", - "windows": "osqueryd.exe", + "macos": "osqueryd.app.tar.gz", + "linux": "osqueryd", + "linux-arm64": "osqueryd-arm64", + "windows": "osqueryd.exe", }, outputDirectory, githubUsername, githubAPIToken, retry) }, } diff --git a/tools/tuf/releaser.sh b/tools/tuf/releaser.sh index 7cefdcdf25..cab40567d4 100755 --- a/tools/tuf/releaser.sh +++ b/tools/tuf/releaser.sh @@ -38,7 +38,7 @@ clean_up () { rm -rf "$GO_TOOLS_DIRECTORY" ARG=$? exit $ARG -} +} setup () { echo "Running setup..." @@ -90,7 +90,7 @@ setup () { FLEET_TIMESTAMP_PASSPHRASE=$(op read "op://$TIMESTAMP_PASSPHRASE_1PASSWORD_PATH") export FLEET_TIMESTAMP_PASSPHRASE - go build -o "$GO_TOOLS_DIRECTORY/replace" "$SCRIPT_DIR/../../tools/tuf/replace" + go build -o "$GO_TOOLS_DIRECTORY/replace" "$SCRIPT_DIR/../../tools/tuf/replace" go build -o "$GO_TOOLS_DIRECTORY/download-artifacts" "$SCRIPT_DIR/../../tools/tuf/download-artifacts" } @@ -106,24 +106,27 @@ promote_component_edge_to_stable () { component_version=$2 IFS='.' read -r -a version_parts <<< "$component_version" - major=${version_parts[0]} - minor=${version_parts[1]} + major=${version_parts[0]} + minor=${version_parts[1]} pushd "$TUF_DIRECTORY" case $component_name in orbit) fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/orbit/macos/edge/orbit" --platform macos --name orbit --version "$component_version" -t "$major.$minor" -t "$major" -t stable fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/orbit/linux/edge/orbit" --platform linux --name orbit --version "$component_version" -t "$major.$minor" -t "$major" -t stable + fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/orbit/linux-arm64/edge/orbit" --platform linux-arm64 --name orbit --version "$component_version" -t "$major.$minor" -t "$major" -t stable fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/orbit/windows/edge/orbit.exe" --platform windows --name orbit --version "$component_version" -t "$major.$minor" -t "$major" -t stable ;; desktop) fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/desktop/macos/edge/desktop.app.tar.gz" --platform macos --name desktop --version "$component_version" -t "$major.$minor" -t "$major" -t stable fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/desktop/linux/edge/desktop.tar.gz" --platform linux --name desktop --version "$component_version" -t "$major.$minor" -t "$major" -t stable + fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/desktop/linux-arm64/edge/desktop.tar.gz" --platform linux-arm64 --name desktop --version "$component_version" -t "$major.$minor" -t "$major" -t stable fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/desktop/windows/edge/fleet-desktop.exe" --platform windows --name desktop --version "$component_version" -t "$major.$minor" -t "$major" -t stable ;; osqueryd) fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/osqueryd/macos-app/edge/osqueryd.app.tar.gz" --platform macos-app --name osqueryd --version "$component_version" -t "$major.$minor" -t "$major" -t stable fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/osqueryd/linux/edge/osqueryd" --platform linux --name osqueryd --version "$component_version" -t "$major.$minor" -t "$major" -t stable + fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/osqueryd/linux-arm64/edge/osqueryd" --platform linux-arm64 --name osqueryd --version "$component_version" -t "$major.$minor" -t "$major" -t stable fleetctl updates add --target "$REPOSITORY_DIRECTORY/targets/osqueryd/windows/edge/osqueryd.exe" --platform windows --name osqueryd --version "$component_version" -t "$major.$minor" -t "$major" -t stable ;; *) @@ -188,9 +191,11 @@ release_fleetd_to_edge () { pushd "$TUF_DIRECTORY" fleetctl updates add --target "$ORBIT_ARTIFACT_DOWNLOAD_DIRECTORY/macos/orbit" --platform macos --name orbit --version "$VERSION" -t edge fleetctl updates add --target "$ORBIT_ARTIFACT_DOWNLOAD_DIRECTORY/linux/orbit" --platform linux --name orbit --version "$VERSION" -t edge + fleetctl updates add --target "$ORBIT_ARTIFACT_DOWNLOAD_DIRECTORY/linux-arm64/orbit" --platform linux-arm64 --name orbit --version "$VERSION" -t edge fleetctl updates add --target "$ORBIT_ARTIFACT_DOWNLOAD_DIRECTORY/windows/orbit.exe" --platform windows --name orbit --version "$VERSION" -t edge fleetctl updates add --target "$DESKTOP_ARTIFACT_DOWNLOAD_DIRECTORY/macos/desktop.app.tar.gz" --platform macos --name desktop --version "$VERSION" -t edge fleetctl updates add --target "$DESKTOP_ARTIFACT_DOWNLOAD_DIRECTORY/linux/desktop.tar.gz" --platform linux --name desktop --version "$VERSION" -t edge + fleetctl updates add --target "$DESKTOP_ARTIFACT_DOWNLOAD_DIRECTORY/linux-arm64/desktop.tar.gz" --platform linux-arm64 --name desktop --version "$VERSION" -t edge fleetctl updates add --target "$DESKTOP_ARTIFACT_DOWNLOAD_DIRECTORY/windows/fleet-desktop.exe" --platform windows --name desktop --version "$VERSION" -t edge popd } @@ -221,6 +226,7 @@ release_osqueryd_to_edge () { pushd "$TUF_DIRECTORY" fleetctl updates add --target "$OSQUERYD_ARTIFACT_DOWNLOAD_DIRECTORY/macos/osqueryd.app.tar.gz" --platform macos-app --name osqueryd --version "$VERSION" -t edge fleetctl updates add --target "$OSQUERYD_ARTIFACT_DOWNLOAD_DIRECTORY/linux/osqueryd" --platform linux --name osqueryd --version "$VERSION" -t edge + fleetctl updates add --target "$OSQUERYD_ARTIFACT_DOWNLOAD_DIRECTORY/linux-arm64/osqueryd" --platform linux-arm64 --name osqueryd --version "$VERSION" -t edge fleetctl updates add --target "$OSQUERYD_ARTIFACT_DOWNLOAD_DIRECTORY/windows/osqueryd.exe" --platform windows --name osqueryd --version "$VERSION" -t edge popd } @@ -331,4 +337,4 @@ else exit 1 fi -push_to_remote \ No newline at end of file +push_to_remote diff --git a/tools/tuf/test/create_repository.sh b/tools/tuf/test/create_repository.sh index 2fabf7aa10..82c751e3d9 100755 --- a/tools/tuf/test/create_repository.sh +++ b/tools/tuf/test/create_repository.sh @@ -1,6 +1,6 @@ #!/bin/bash -set -e +set -xe # This script initializes a test Fleet TUF repository. # All targets are created with version 42. @@ -23,7 +23,10 @@ if [[ -d "$TUF_PATH" ]]; then exit 0 fi -SYSTEMS=${SYSTEMS:-macos linux windows} +SYSTEMS=${SYSTEMS:-macos linux linux-arm64 windows} + +echo "Generating packages for $SYSTEMS" + NUDGE_VERSION=stable SWIFT_DIALOG_MACOS_APP_VERSION=2.2.1 SWIFT_DIALOG_MACOS_APP_BUILD_VERSION=4591 @@ -46,8 +49,15 @@ for system in $SYSTEMS; do elif [[ $system == "macos" ]]; then osqueryd="$osqueryd.app.tar.gz" osqueryd_system="macos-app" + elif [[ $system == "linux-arm64" ]]; then + osqueryd_system="linux-arm64" + fi + + if [[ $system == "linux-arm64" ]]; then + osqueryd_path="$TUF_PATH/tmp/${osqueryd}-arm64" + else + osqueryd_path="$TUF_PATH/tmp/$osqueryd" fi - osqueryd_path="$TUF_PATH/tmp/$osqueryd" curl https://tuf.fleetctl.com/targets/osqueryd/$osqueryd_system/$OSQUERY_VERSION/$osqueryd --output $osqueryd_path major=$(echo "$OSQUERY_VERSION" | cut -d "." -f 1) @@ -65,6 +75,13 @@ for system in $SYSTEMS; do if [[ $system == "macos" ]]; then goose_value="darwin" fi + if [[ $system == "linux" ]]; then + goarch_value="amd64" + fi + if [[ $system == "linux-arm64" ]]; then + goose_value="linux" + goarch_value="arm64" + fi orbit_target=orbit-$system if [[ $system == "windows" ]]; then orbit_target="${orbit_target}.exe" @@ -162,6 +179,19 @@ for system in $SYSTEMS; do rm desktop.tar.gz fi + # Add Fleet Desktop application on linux-arm64 (if enabled). + if [[ $system == "linux-arm64" && -n "$FLEET_DESKTOP" ]]; then + FLEET_DESKTOP_VERSION=42.0.0 \ + make desktop-linux-arm64 + ./build/fleetctl updates add \ + --path $TUF_PATH \ + --target desktop.tar.gz \ + --platform linux-arm64 \ + --name desktop \ + --version 42.0.0 -t 42.0 -t 42 -t stable + rm desktop.tar.gz + fi + # Add extensions on macos (if set). if [[ $system == "macos" && -n "$MACOS_TEST_EXTENSIONS" ]]; then for extension in ${MACOS_TEST_EXTENSIONS//,/ } @@ -192,6 +222,21 @@ for system in $SYSTEMS; do done fi + # Add extensions on linux (if set). + if [[ $system == "linux-arm64" && -n "$LINUX_TEST_EXTENSIONS" ]]; then + for extension in ${LINUX_TEST_EXTENSIONS//,/ } + do + extensionName=$(basename $extension) + extensionName=$(echo "$extensionName" | cut -d'.' -f1) + ./build/fleetctl updates add \ + --path $TUF_PATH \ + --target $extension \ + --platform linux-arm64 \ + --name "extensions/$extensionName" \ + --version 42.0.0 -t 42.0 -t 42 -t stable + done + fi + # Add extensions on windows (if set). if [[ $system == "windows" && -n "$WINDOWS_TEST_EXTENSIONS" ]]; then for extension in ${WINDOWS_TEST_EXTENSIONS//,/ } diff --git a/tools/tuf/test/docker_package.sh b/tools/tuf/test/docker_package.sh index 0707a4750c..35b00c60cf 100755 --- a/tools/tuf/test/docker_package.sh +++ b/tools/tuf/test/docker_package.sh @@ -15,7 +15,7 @@ BASE_FLEET_URL=$2 rm -rf test_tuf desktop.tar.gz -SYSTEMS="macos windows linux" \ +SYSTEMS="macos windows linux linux-arm64" \ PKG_FLEET_URL=$BASE_FLEET_URL \ PKG_TUF_URL=$BASE_TUF_URL \ DEB_FLEET_URL=$BASE_FLEET_URL \ diff --git a/tools/tuf/test/gen_pkgs.sh b/tools/tuf/test/gen_pkgs.sh index 517357a1df..f021835aea 100755 --- a/tools/tuf/test/gen_pkgs.sh +++ b/tools/tuf/test/gen_pkgs.sh @@ -24,7 +24,7 @@ set -ex # # ENROLL_SECRET: Fleet server enroll secret. # ROOT_KEYS: TUF repository root keys. -# FLEET_DESKTOP: Whether to build with Fleet Desktop support. +# FLEET_DESKTOP: Whether to build with Fleet Desktop support. # INSECURE: Whether to use the --insecure flag. # USE_FLEET_SERVER_CERTIFICATE: Whether to use a custom certificate bundle. # USE_UPDATE_SERVER_CERTIFICATE: Whether to use a custom certificate bundle. @@ -61,9 +61,32 @@ if [ -n "$GENERATE_PKG" ]; then fi if [ -n "$GENERATE_DEB" ]; then - echo "Generating deb..." + echo "Generating deb (amd64)..." ./build/fleetctl package \ --type=deb \ + --arch=amd64 \ + ${FLEET_DESKTOP:+--fleet-desktop} \ + --fleet-url=$DEB_FLEET_URL \ + --enroll-secret=$ENROLL_SECRET \ + ${USE_FLEET_SERVER_CERTIFICATE:+--fleet-certificate=./tools/osquery/fleet.crt} \ + ${USE_UPDATE_SERVER_CERTIFICATE:+--update-tls-certificate=./tools/osquery/fleet.crt} \ + ${INSECURE:+--insecure} \ + ${DEBUG:+--debug} \ + --update-roots="$ROOT_KEYS" \ + --update-interval=10s \ + --disable-open-folder \ + ${USE_FLEET_CLIENT_CERTIFICATE:+--fleet-tls-client-certificate=./tools/test-orbit-mtls/client.crt} \ + ${USE_FLEET_CLIENT_CERTIFICATE:+--fleet-tls-client-key=./tools/test-orbit-mtls/client.key} \ + ${USE_UPDATE_CLIENT_CERTIFICATE:+--update-tls-client-certificate=./tools/test-orbit-mtls/client.crt} \ + ${USE_UPDATE_CLIENT_CERTIFICATE:+--update-tls-client-key=./tools/test-orbit-mtls/client.key} \ + ${FLEET_DESKTOP_ALTERNATIVE_BROWSER_HOST:+--fleet-desktop-alternative-browser-host=$FLEET_DESKTOP_ALTERNATIVE_BROWSER_HOST} \ + ${ENABLE_SCRIPTS:+--enable-scripts} \ + --update-url=$DEB_TUF_URL + + echo "Generating deb (arm64)..." + ./build/fleetctl package \ + --type=deb \ + --arch=arm64 \ ${FLEET_DESKTOP:+--fleet-desktop} \ --fleet-url=$DEB_FLEET_URL \ --enroll-secret=$ENROLL_SECRET \ @@ -84,9 +107,32 @@ if [ -n "$GENERATE_DEB" ]; then fi if [ -n "$GENERATE_RPM" ]; then - echo "Generating rpm..." + echo "Generating rpm (amd64)..." ./build/fleetctl package \ --type=rpm \ + --arch=amd64 \ + ${FLEET_DESKTOP:+--fleet-desktop} \ + --fleet-url=$RPM_FLEET_URL \ + --enroll-secret=$ENROLL_SECRET \ + ${USE_FLEET_SERVER_CERTIFICATE:+--fleet-certificate=./tools/osquery/fleet.crt} \ + ${USE_UPDATE_SERVER_CERTIFICATE:+--update-tls-certificate=./tools/osquery/fleet.crt} \ + ${INSECURE:+--insecure} \ + ${DEBUG:+--debug} \ + --update-roots="$ROOT_KEYS" \ + --update-interval=10s \ + --disable-open-folder \ + ${USE_FLEET_CLIENT_CERTIFICATE:+--fleet-tls-client-certificate=./tools/test-orbit-mtls/client.crt} \ + ${USE_FLEET_CLIENT_CERTIFICATE:+--fleet-tls-client-key=./tools/test-orbit-mtls/client.key} \ + ${USE_UPDATE_CLIENT_CERTIFICATE:+--update-tls-client-certificate=./tools/test-orbit-mtls/client.crt} \ + ${USE_UPDATE_CLIENT_CERTIFICATE:+--update-tls-client-key=./tools/test-orbit-mtls/client.key} \ + ${FLEET_DESKTOP_ALTERNATIVE_BROWSER_HOST:+--fleet-desktop-alternative-browser-host=$FLEET_DESKTOP_ALTERNATIVE_BROWSER_HOST} \ + ${ENABLE_SCRIPTS:+--enable-scripts} \ + --update-url=$RPM_TUF_URL + + echo "Generating rpm (arm64)..." + ./build/fleetctl package \ + --type=rpm \ + --arch=arm64 \ ${FLEET_DESKTOP:+--fleet-desktop} \ --fleet-url=$RPM_FLEET_URL \ --enroll-secret=$ENROLL_SECRET \ @@ -133,4 +179,4 @@ echo "Packages generated." if [[ $OSTYPE == 'darwin'* && -n "$INSTALL_PKG" ]]; then sudo installer -pkg fleet-osquery.pkg -target / -fi \ No newline at end of file +fi diff --git a/tools/tuf/test/main.sh b/tools/tuf/test/main.sh index 4b357107e6..2f5d8f20a5 100755 --- a/tools/tuf/test/main.sh +++ b/tools/tuf/test/main.sh @@ -1,6 +1,6 @@ #!/bin/bash -set -e +set -ex export FLEET_ROOT_PASSPHRASE=p4ssphr4s3 export FLEET_TARGETS_PASSPHRASE=p4ssphr4s3 @@ -30,5 +30,5 @@ if [ -z "$SKIP_SERVER" ]; then fi if [ -n "$GENERATE_PKG" ] || [ -n "$GENERATE_DEB" ] || [ -n "$GENERATE_RPM" ] || [ -n "$GENERATE_MSI" ]; then - ./tools/tuf/test/gen_pkgs.sh + bash ./tools/tuf/test/gen_pkgs.sh fi