Add Notarization for Fleet Desktop (#4720)

This commit is contained in:
Zach Wasserman 2022-03-21 15:01:50 -07:00 committed by GitHub
parent d60ee47545
commit cc687d9d1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 7 deletions

View File

@ -54,6 +54,7 @@ jobs:
AC_USERNAME=$AC_USERNAME \
AC_PASSWORD=$AC_PASSWORD \
FLEET_DESKTOP_APPLE_AUTHORITY=$CODESIGN_IDENTITY \
FLEET_DESKTOP_NOTARIZE=true \
FLEET_DESKTOP_VERSION=$FLEET_DESKTOP_VERSION \
make desktop-app-tar-gz
- name: Upload desktop.app.tar.gz

View File

@ -117,7 +117,7 @@ func BuildPkg(opt Options) (string, error) {
}
if opt.Notarize {
if err := notarizePkg(generatedPath); err != nil {
if err := NotarizeStaple(generatedPath, "com.fleetdm.orbit"); err != nil {
return "", err
}
}

View File

@ -13,7 +13,8 @@ import (
"github.com/rs/zerolog/log"
)
func notarizePkg(pkgPath string) error {
// Notarize will do the Notarization step. Note that the provided path must be a .zip or a .dmg.
func Notarize(path, bundleIdentifier string) error {
username, ok := os.LookupEnv("AC_USERNAME")
if !ok {
return errors.New("AC_USERNAME must be set in environment")
@ -27,8 +28,8 @@ func notarizePkg(pkgPath string) error {
info, err := notarize.Notarize(
context.Background(),
&notarize.Options{
File: pkgPath,
BundleId: "com.fleetdm.orbit",
File: path,
BundleId: bundleIdentifier,
Username: username,
Password: password,
Status: &statusHuman{
@ -42,13 +43,32 @@ func notarizePkg(pkgPath string) error {
log.Info().Str("logs", info.LogFileURL).Msg("notarization completed")
if err := staple.Staple(context.Background(), &staple.Options{File: pkgPath}); err != nil {
return nil
}
// Staple will do the "stapling" step of Notarization. Note that this only works on .app and .dmg
// (not .zip or plain binaries).
func Staple(path string) error {
if err := staple.Staple(context.Background(), &staple.Options{File: path}); err != nil {
return fmt.Errorf("staple notarization: %w", err)
}
return nil
}
// NotarizeStaple will notarize and staple a macOS artifact.
func NotarizeStaple(path, bundleIdentifier string) error {
if err := Notarize(path, bundleIdentifier); err != nil {
return err
}
if err := Staple(path); err != nil {
return err
}
return nil
}
// This status plugin copied from
// https://github.com/mitchellh/gon/blob/v0.2.3/cmd/gon/status_human.go since it
// is not exposed from the gon library.

View File

@ -3,6 +3,7 @@ package main
import (
"archive/tar"
"compress/gzip"
"context"
"errors"
"fmt"
"io"
@ -13,8 +14,10 @@ import (
"runtime"
"github.com/fleetdm/fleet/v4/orbit/pkg/constant"
"github.com/fleetdm/fleet/v4/orbit/pkg/packaging"
"github.com/fleetdm/fleet/v4/pkg/secure"
"github.com/kolide/kit/version"
"github.com/mitchellh/gon/package/zip"
"github.com/rs/zerolog"
zlog "github.com/rs/zerolog/log"
"github.com/urfave/cli/v2"
@ -75,17 +78,22 @@ func macos() *cli.Command {
Usage: "Authority to use on the codesign invocation (if not set, app is not signed)",
EnvVars: []string{"FLEET_DESKTOP_APPLE_AUTHORITY"},
},
&cli.BoolFlag{
Name: "notarize",
Usage: "If true, the generated application will be notarized and stapled. Requires the `AC_USERNAME` and `AC_PASSWORD` to be set in the environment",
EnvVars: []string{"FLEET_DESKTOP_NOTARIZE"},
},
},
Action: func(c *cli.Context) error {
if !c.Bool("verbose") {
zlog.Logger = zerolog.Nop()
}
return createMacOSApp(c.String("version"), c.String("authority"))
return createMacOSApp(c.String("version"), c.String("authority"), c.Bool("notarize"))
},
}
}
func createMacOSApp(version, authority string) error {
func createMacOSApp(version, authority string, notarize bool) error {
const (
appDir = "Fleet Desktop.app"
bundleIdentifier = "com.fleetdm.desktop"
@ -162,6 +170,25 @@ func createMacOSApp(version, authority string) error {
}
}
if notarize {
const notarizationZip = "desktop.zip"
// Note that the app needs to be zipped in order to upload to Apple for Notarization, but
// the Stapling has to happen on just the app (not zipped). Apple is a bit inconsistent here.
if err := zip.Zip(context.Background(), &zip.Options{Files: []string{appDir}, OutputPath: notarizationZip}); err != nil {
return fmt.Errorf("zip app for notarization: %w", err)
}
defer os.Remove(notarizationZip)
if err := packaging.Notarize(notarizationZip, "com.fleetdm.desktop"); err != nil {
return err
}
if err := packaging.Staple(appDir); err != nil {
return err
}
}
const tarGzName = "desktop.app.tar.gz"
if err := compressDir(tarGzName, appDir); err != nil {
return fmt.Errorf("compress app: %w", err)