mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 00:45:19 +00:00
added package command from orbit as fleetctl command (#1802)
* added package command from orbit as fleetctl command * update deployment docs * add changes file * added tests for package command, run go mod tidy & go mod verify * validate that package files exist * comment out msi packaging test until we can investigate github runner permission issues
This commit is contained in:
parent
f6627c4cae
commit
823775844e
3
.gitignore
vendored
3
.gitignore
vendored
@ -49,3 +49,6 @@ backup.sql.gz
|
||||
# Common mistake for new developers to run npm install and then end up
|
||||
# committing a package-lock.json. Fleet app uses Yarn with yarn.lock.
|
||||
package-lock.json
|
||||
|
||||
# generated installers
|
||||
orbit-osquery*
|
||||
|
1
changes/issue-541-fleetctl-package
Normal file
1
changes/issue-541-fleetctl-package
Normal file
@ -0,0 +1 @@
|
||||
* added `fleetctl package` command -- originally from the orbit package/project this simply enables one to run package with fleetctl
|
@ -61,6 +61,7 @@ func createApp(reader io.Reader, writer io.Writer, exitErrHandler cli.ExitErrHan
|
||||
previewCommand(),
|
||||
eefleetctl.UpdatesCommand(),
|
||||
hostsCommand(),
|
||||
packageCommand(),
|
||||
}
|
||||
return app
|
||||
}
|
||||
|
125
cmd/fleetctl/package.go
Normal file
125
cmd/fleetctl/package.go
Normal file
@ -0,0 +1,125 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/packaging"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var opt packaging.Options
|
||||
|
||||
func packageCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "package",
|
||||
Aliases: nil,
|
||||
Usage: "Create an Orbit installer package",
|
||||
Description: "An easy way to create fully boot-strapped installer packages for Windows, macOS, or Linux",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "type",
|
||||
Usage: "Type of package to build",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "enroll-secret",
|
||||
Usage: "Enroll secret for authenticating to Fleet server",
|
||||
Destination: &opt.EnrollSecret,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "fleet-url",
|
||||
Usage: "URL (host:port) of Fleet server",
|
||||
Destination: &opt.FleetURL,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "fleet-certificate",
|
||||
Usage: "Path to server cerificate bundle",
|
||||
Destination: &opt.FleetCertificate,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "identifier",
|
||||
Usage: "Identifier for package product",
|
||||
Value: "com.fleetdm.orbit",
|
||||
Destination: &opt.Identifier,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "version",
|
||||
Usage: "Version for package product",
|
||||
Value: "0.0.3",
|
||||
Destination: &opt.Version,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "insecure",
|
||||
Usage: "Disable TLS certificate verification",
|
||||
Destination: &opt.Insecure,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "service",
|
||||
Usage: "Install orbit/osquery with a persistence service (launchd, systemd, etc.)",
|
||||
Value: true,
|
||||
Destination: &opt.StartService,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "sign-identity",
|
||||
Usage: "Identity to use for macOS codesigning",
|
||||
Destination: &opt.SignIdentity,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "notarize",
|
||||
Usage: "Whether to notarize macOS packages",
|
||||
Destination: &opt.Notarize,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "osqueryd-channel",
|
||||
Usage: "Update channel of osqueryd to use",
|
||||
Value: "stable",
|
||||
Destination: &opt.OsquerydChannel,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "orbit-channel",
|
||||
Usage: "Update channel of Orbit to use",
|
||||
Value: "stable",
|
||||
Destination: &opt.OrbitChannel,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "update-url",
|
||||
Usage: "URL for update server",
|
||||
Value: "https://tuf.fleetctl.com",
|
||||
Destination: &opt.UpdateURL,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "update-roots",
|
||||
Usage: "Root key JSON metadata for update server (from fleetctl updates roots)",
|
||||
Destination: &opt.UpdateRoots,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "Enable debug logging",
|
||||
Destination: &opt.Debug,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
if opt.FleetURL != "" || opt.EnrollSecret != "" {
|
||||
if opt.FleetURL == "" || opt.EnrollSecret == "" {
|
||||
return errors.New("--enroll-secret and --fleet-url must be provided together")
|
||||
}
|
||||
}
|
||||
|
||||
if opt.Insecure && opt.FleetCertificate != "" {
|
||||
return errors.New("--insecure and --fleet-certificate may not be provided together")
|
||||
}
|
||||
|
||||
switch c.String("type") {
|
||||
case "pkg":
|
||||
return packaging.BuildPkg(opt)
|
||||
case "deb":
|
||||
return packaging.BuildDeb(opt)
|
||||
case "rpm":
|
||||
return packaging.BuildRPM(opt)
|
||||
case "msi":
|
||||
return packaging.BuildMSI(opt)
|
||||
default:
|
||||
return errors.New("type must be one of ('pkg', 'deb', 'rpm', 'msi')")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
40
cmd/fleetctl/package_test.go
Normal file
40
cmd/fleetctl/package_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPackage(t *testing.T) {
|
||||
|
||||
// --type is required
|
||||
runAppCheckErr(t, []string{"package", "deb"}, "Required flag \"type\" not set")
|
||||
|
||||
// if you provide -fleet-url & --enroll-secret are required together
|
||||
runAppCheckErr(t, []string{"package", "--type=deb", "--fleet-url=https://localhost:8080"}, "--enroll-secret and --fleet-url must be provided together")
|
||||
runAppCheckErr(t, []string{"package", "--type=deb", "--enroll-secret=foobar"}, "--enroll-secret and --fleet-url must be provided together")
|
||||
|
||||
// --insecure and --fleet-certificate are mutually exclusive
|
||||
runAppCheckErr(t, []string{"package", "--type=deb", "--insecure", "--fleet-certificate=test123"}, "--insecure and --fleet-certificate may not be provided together")
|
||||
|
||||
// run package tests, each should output their respective package type
|
||||
// orbit-osquery_0.0.3_amd64.deb
|
||||
runAppForTest(t, []string{"package", "--type=deb", "--insecure"})
|
||||
info, err := os.Stat("orbit-osquery_0.0.3_amd64.deb")
|
||||
require.NoError(t, err)
|
||||
require.Greater(t, info.Size(), int64(0)) // TODO verify contents
|
||||
// orbit-osquery-0.0.3.x86_64.rpm
|
||||
runAppForTest(t, []string{"package", "--type=rpm", "--insecure"})
|
||||
info, err = os.Stat("orbit-osquery-0.0.3.x86_64.rpm")
|
||||
require.NoError(t, err)
|
||||
require.Greater(t, info.Size(), int64(0)) // TODO verify contents
|
||||
// orbit-osquery_0.0.3.msi
|
||||
//runAppForTest(t, []string{"package", "--type=msi", "--insecure"}) TODO: this is currently failing on Github runners due to permission issues
|
||||
//info, err = os.Stat("orbit-osquery_0.0.3.msi")
|
||||
//require.NoError(t, err)
|
||||
//require.Greater(t, info.Size(), int64(0))
|
||||
|
||||
//runAppForTest(t, []string{"package", "--type=pkg", "--insecure"}) TODO: had a hard time getting xar installed on Ubuntu
|
||||
|
||||
}
|
@ -128,8 +128,12 @@ fleetctl updates roots
|
||||
|
||||
This output is _not sensitive_ and will be shared in agent deployments to verify the contents of updates and metadata. Provide the JSON output in the `--update-roots` flag of the [Orbit packager](https://github.com/fleetdm/orbit#packaging):
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
go run ./cmd/package --type pkg --enroll-secret=ZB3QfaItRRUjlGo+LctfOMzLTjjyxLdg --fleet-url=https://localhost:8080 --update-url=http://localhost:8000 --update-roots='[{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"9aac6f59f0e3f2f4ef6f789e4eff058af27db3743eaa6a47a228f23e5a1ad4d7"}}]' --insecure
|
||||
```
|
||||
### Packaging with Orbit
|
||||
|
||||
See [Orbit Docs](https://github.com/fleetdm/fleet/blob/main/orbit/README.md) for more details
|
||||
|
||||
You can use `fleetctl package` to generate installer packages of Orbit (a bootstrapped OSQuery wrapper) to integrate with your Fleet instance.
|
||||
|
||||
For example running `fleetctl package --type deb --fleet-url=<fleet url> --enroll-secret=<enroll secret>` will build a `.deb` installer with everything needed
|
||||
to communicate with your fleet instance.
|
||||
|
@ -1,142 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/packaging"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var opt packaging.Options
|
||||
log.Logger = log.Output(
|
||||
zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339Nano},
|
||||
)
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "Orbit osquery"
|
||||
app.Usage = "A powered-up, (near) drop-in replacement for osquery"
|
||||
app.Commands = []*cli.Command{}
|
||||
app.Flags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "type",
|
||||
Usage: "Type of package to build",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "enroll-secret",
|
||||
Usage: "Enroll secret for authenticating to Fleet server",
|
||||
Destination: &opt.EnrollSecret,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "fleet-url",
|
||||
Usage: "URL (host:port) of Fleet server",
|
||||
Destination: &opt.FleetURL,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "fleet-certificate",
|
||||
Usage: "Path to server cerificate bundle",
|
||||
Destination: &opt.FleetCertificate,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "identifier",
|
||||
Usage: "Identifier for package product",
|
||||
Value: "com.fleetdm.orbit",
|
||||
Destination: &opt.Identifier,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "version",
|
||||
Usage: "Version for package product",
|
||||
Value: "0.0.3",
|
||||
Destination: &opt.Version,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "insecure",
|
||||
Usage: "Disable TLS certificate verification",
|
||||
Destination: &opt.Insecure,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "service",
|
||||
Usage: "Install orbit/osquery with a persistence service (launchd, systemd, etc.)",
|
||||
Value: true,
|
||||
Destination: &opt.StartService,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "sign-identity",
|
||||
Usage: "Identity to use for macOS codesigning",
|
||||
Destination: &opt.SignIdentity,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "notarize",
|
||||
Usage: "Whether to notarize macOS packages",
|
||||
Destination: &opt.Notarize,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "osqueryd-channel",
|
||||
Usage: "Update channel of osqueryd to use",
|
||||
Value: "stable",
|
||||
Destination: &opt.OsquerydChannel,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "orbit-channel",
|
||||
Usage: "Update channel of Orbit to use",
|
||||
Value: "stable",
|
||||
Destination: &opt.OrbitChannel,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "update-url",
|
||||
Usage: "URL for update server",
|
||||
Value: "https://tuf.fleetctl.com",
|
||||
Destination: &opt.UpdateURL,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "update-roots",
|
||||
Usage: "Root key JSON metadata for update server (from fleetctl updates roots)",
|
||||
Destination: &opt.UpdateRoots,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "Enable debug logging",
|
||||
Destination: &opt.Debug,
|
||||
},
|
||||
}
|
||||
app.Before = func(c *cli.Context) error {
|
||||
if opt.Debug {
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
app.Action = func(c *cli.Context) error {
|
||||
if opt.FleetURL != "" || opt.EnrollSecret != "" {
|
||||
if opt.FleetURL == "" || opt.EnrollSecret == "" {
|
||||
return errors.New("--enroll-secret and --fleet-url must be provided together")
|
||||
}
|
||||
}
|
||||
|
||||
if opt.Insecure && opt.FleetCertificate != "" {
|
||||
return errors.New("--insecure and --fleet-certificate may not be provided together")
|
||||
}
|
||||
|
||||
switch c.String("type") {
|
||||
case "pkg":
|
||||
return packaging.BuildPkg(opt)
|
||||
case "deb":
|
||||
return packaging.BuildDeb(opt)
|
||||
case "rpm":
|
||||
return packaging.BuildRPM(opt)
|
||||
case "msi":
|
||||
return packaging.BuildMSI(opt)
|
||||
default:
|
||||
return errors.New("type must be one of ('pkg', 'deb', 'rpm', 'msi')")
|
||||
}
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal().Err(err).Msg("package failed")
|
||||
}
|
||||
}
|
@ -18,7 +18,6 @@ import (
|
||||
|
||||
func buildNFPM(opt Options, pkger nfpm.Packager) error {
|
||||
// Initialize directories
|
||||
|
||||
tmpDir, err := ioutil.TempDir("", "orbit-package")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create temp dir")
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
// Linux.
|
||||
func BuildPkg(opt Options) error {
|
||||
// Initialize directories
|
||||
|
||||
tmpDir, err := ioutil.TempDir("", "orbit-package")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create temp dir")
|
||||
|
@ -1,4 +1,4 @@
|
||||
// package packaging provides tools for buildin Orbit installation packages.
|
||||
// Package packaging provides tools for building Orbit installation packages.
|
||||
package packaging
|
||||
|
||||
import (
|
||||
|
@ -65,7 +65,7 @@ func (s *fileStore) readData() error {
|
||||
return errors.New("expected file store to be regular file")
|
||||
}
|
||||
|
||||
f, err := os.Open(s.filename)
|
||||
f, err := secure.OpenFile(s.filename, os.O_RDWR|os.O_CREATE, constant.DefaultFileMode)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "open file store")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user