From 13a6da8355318da25054e4d8f4ca77fec0229235 Mon Sep 17 00:00:00 2001 From: Zachary Wasserman Date: Thu, 22 Feb 2018 12:41:02 -0800 Subject: [PATCH] Add packaging support for specifying root CAs (#263) Closes #231. --- cmd/package-builder/package-builder.go | 7 +++- tools/packaging/packaging.go | 51 +++++++++++++++++++++----- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/cmd/package-builder/package-builder.go b/cmd/package-builder/package-builder.go index 574ea7068..4abd25f47 100644 --- a/cmd/package-builder/package-builder.go +++ b/cmd/package-builder/package-builder.go @@ -89,6 +89,11 @@ func runMake(args []string) error { env.String("CERT_PINS", ""), "Comma separated, hex encoded SHA256 hashes of pinned subject public key info", ) + flRootPEM = flagset.String( + "root_pem", + env.String("ROOT_PEM", ""), + "Path to PEM file including root certificates to verify against", + ) ) flagset.Usage = usageFor(flagset, "package-builder make [flags]") @@ -126,7 +131,7 @@ func runMake(args []string) error { } } - paths, err := packaging.CreatePackages(osqueryVersion, *flHostname, *flEnrollSecret, macPackageSigningKey, *flInsecure, *flInsecureGrpc, *flAutoupdate, *flUpdateChannel, *flIdentifier, *flOmitSecret, *flSystemd, *flCertPins) + paths, err := packaging.CreatePackages(osqueryVersion, *flHostname, *flEnrollSecret, macPackageSigningKey, *flInsecure, *flInsecureGrpc, *flAutoupdate, *flUpdateChannel, *flIdentifier, *flOmitSecret, *flSystemd, *flCertPins, *flRootPEM) if err != nil { return errors.Wrap(err, "could not generate packages") } diff --git a/tools/packaging/packaging.go b/tools/packaging/packaging.go index 55e0feaec..a29ed8cf2 100644 --- a/tools/packaging/packaging.go +++ b/tools/packaging/packaging.go @@ -31,13 +31,13 @@ type PackagePaths struct { // CreatePackages will create a launcher macOS package. The output paths of the // packages are returned and an error if the operation was not successful. -func CreatePackages(osqueryVersion, hostname, secret, macPackageSigningKey string, insecure, insecureGrpc, autoupdate bool, updateChannel string, identifier string, omitSecret bool, systemd bool, certPins string) (*PackagePaths, error) { - macPkgDestinationPath, err := CreateMacPackage(osqueryVersion, hostname, secret, macPackageSigningKey, insecure, insecureGrpc, autoupdate, updateChannel, identifier, omitSecret, certPins) +func CreatePackages(osqueryVersion, hostname, secret, macPackageSigningKey string, insecure, insecureGrpc, autoupdate bool, updateChannel string, identifier string, omitSecret bool, systemd bool, certPins, rootPEM string) (*PackagePaths, error) { + macPkgDestinationPath, err := CreateMacPackage(osqueryVersion, hostname, secret, macPackageSigningKey, insecure, insecureGrpc, autoupdate, updateChannel, identifier, omitSecret, certPins, rootPEM) if err != nil { return nil, errors.Wrap(err, "could not generate macOS package") } - debDestinationPath, rpmDestinationPath, err := CreateLinuxPackages(osqueryVersion, hostname, secret, insecure, insecureGrpc, autoupdate, updateChannel, identifier, omitSecret, systemd, certPins) + debDestinationPath, rpmDestinationPath, err := CreateLinuxPackages(osqueryVersion, hostname, secret, insecure, insecureGrpc, autoupdate, updateChannel, identifier, omitSecret, systemd, certPins, rootPEM) if err != nil { return nil, errors.Wrap(err, "could not generate linux packages") } @@ -81,7 +81,7 @@ func createInitFiles(opts *initTemplateOptions, serviceDirectory string, initFil return nil } -func CreateLinuxPackages(osqueryVersion, hostname, secret string, insecure, insecureGrpc, autoupdate bool, updateChannel, identifier string, omitSecret bool, systemd bool, certPins string) (string, string, error) { +func CreateLinuxPackages(osqueryVersion, hostname, secret string, insecure, insecureGrpc, autoupdate bool, updateChannel, identifier string, omitSecret bool, systemd bool, certPins, rootPEM string) (string, string, error) { postInstallScript := "launcher-installer" // first, we have to create a local temp directory on disk that we will use as // a packaging root, but will delete once the generated package is created and @@ -141,6 +141,18 @@ func CreateLinuxPackages(osqueryVersion, hostname, secret string, insecure, inse } } + var rootPEMPath string + if rootPEM != "" { + rootPEMPath = filepath.Join(configurationDirectory, "roots.pem") + + if err := fs.CopyFile(rootPEM, filepath.Join(packageRoot, rootPEMPath)); err != nil { + return "", "", errors.Wrap(err, "copy root PEM") + } + if err := os.Chmod(filepath.Join(packageRoot, rootPEMPath), 0600); err != nil { + return "", "", errors.Wrap(err, "chmod root PEM") + } + } + if updateChannel == "" { updateChannel = "stable" } @@ -157,6 +169,7 @@ func CreateLinuxPackages(osqueryVersion, hostname, secret string, insecure, inse Autoupdate: autoupdate, UpdateChannel: updateChannel, CertPins: certPins, + RootPEM: rootPEMPath, } if systemd { @@ -260,7 +273,7 @@ sudo service launcher restart` return debOutputPath, rpmOutputPath, nil } -func CreateMacPackage(osqueryVersion, hostname, secret, macPackageSigningKey string, insecure, insecureGrpc, autoupdate bool, updateChannel, identifier string, omitSecret bool, certPins string) (string, error) { +func CreateMacPackage(osqueryVersion, hostname, secret, macPackageSigningKey string, insecure, insecureGrpc, autoupdate bool, updateChannel, identifier string, omitSecret bool, certPins, rootPEM string) (string, error) { // first, we have to create a local temp directory on disk that we will use as // a packaging root, but will delete once the generated package is created and // stored on disk @@ -330,6 +343,19 @@ func CreateMacPackage(osqueryVersion, hostname, secret, macPackageSigningKey str return "", errors.Wrap(err, "could not copy the osquery-extension binary to the packaging root") } + var rootPEMPath string + if rootPEM != "" { + rootPEMPath = filepath.Join(configurationDirectory, "roots.pem") + + if err := fs.CopyFile(rootPEM, filepath.Join(packageRoot, rootPEMPath)); err != nil { + return "", errors.Wrap(err, "copy root PEM") + } + + if err := os.Chmod(filepath.Join(packageRoot, rootPEMPath), 0600); err != nil { + return "", errors.Wrap(err, "chmod root PEM") + } + } + // The LaunchDaemon which will connect the launcher to the cloud launchDaemonFile, err := os.Create(filepath.Join(packageRoot, launchDaemonDirectory, fmt.Sprintf("%s.plist", launchDaemonName))) if err != nil { @@ -353,9 +379,10 @@ func CreateMacPackage(osqueryVersion, hostname, secret, macPackageSigningKey str Autoupdate: autoupdate, UpdateChannel: updateChannel, CertPins: certPins, + RootPEM: rootPEMPath, } if err := renderLaunchDaemon(launchDaemonFile, opts); err != nil { - return "", errors.Wrap(err, "could not write LaunchDeamon content to file") + return "", errors.Wrap(err, "could not write LaunchDaemon content to file") } // The secret which the user will use to authenticate to the server @@ -431,6 +458,7 @@ type initTemplateOptions struct { Autoupdate bool UpdateChannel string CertPins string + RootPEM string } //renderInitService renders an init service to start and schedule the launcher @@ -446,7 +474,8 @@ DAEMON_OPTS="--root_directory={{.RootDirectory}} \ --insecure \{{end}}{{if .Autoupdate}} --autoupdate \ --update_channel={{.UpdateChannel}} \{{end}}{{if .CertPins}} ---cert_pins={{.CertPins}} \{{end}} +--cert_pins={{.CertPins}} \{{end}}{{if .RootPEM}} +--root_pem={{.RootPEM}} \{{end}} --osqueryd_path={{.OsquerydPath}}" export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" @@ -507,7 +536,8 @@ ExecStart={{.LauncherPath}} \ --insecure \{{end}}{{if .Autoupdate}} --autoupdate \ --update_channel={{.UpdateChannel}} \{{end}}{{if .CertPins }} ---cert_pins={{.CertPins}} \{{end}} +--cert_pins={{.CertPins}} \{{end}}{{if .RootPEM}} +--root_pem={{.RootPEM}} \{{end}} --osqueryd_path={{.OsquerydPath}} Restart=on-failure RestartSec=3 @@ -536,6 +566,7 @@ type launchDaemonTemplateOptions struct { Autoupdate bool UpdateChannel string CertPins string + RootPEM string } // renderLaunchDaemon renders a LaunchDaemon to start and schedule the launcher. @@ -560,7 +591,9 @@ func renderLaunchDaemon(w io.Writer, options *launchDaemonTemplateOptions) error KOLIDE_LAUNCHER_UPDATE_CHANNEL {{.UpdateChannel}}{{end}}{{if .CertPins }} KOLIDE_LAUNCHER_CERT_PINS - {{.CertPins}}{{end}} + {{.CertPins}}{{end}}{{if .RootPEM }} + KOLIDE_LAUNCHER_ROOT_PEM + {{.RootPEM}}{{end}} KeepAlive