internal/pkg/agent/cmd/enroll.go (555 lines of code) (raw):
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License 2.0;
// you may not use this file except in compliance with the Elastic License 2.0.
package cmd
import (
"context"
"fmt"
"os"
"os/signal"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
"time"
"github.com/spf13/cobra"
"github.com/elastic/elastic-agent/internal/pkg/agent/application"
"github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
"github.com/elastic/elastic-agent/internal/pkg/agent/configuration"
"github.com/elastic/elastic-agent/internal/pkg/agent/errors"
"github.com/elastic/elastic-agent/internal/pkg/agent/storage"
"github.com/elastic/elastic-agent/internal/pkg/cli"
"github.com/elastic/elastic-agent/internal/pkg/config"
"github.com/elastic/elastic-agent/pkg/core/logger"
"github.com/elastic/elastic-agent/pkg/utils"
)
const (
fromInstallArg = "from-install"
fromInstallUserArg = "from-install-user"
fromInstallGroupArg = "from-install-group"
)
func newEnrollCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "enroll",
Short: "Enroll the Elastic Agent into Fleet",
Long: "This command will enroll the Elastic Agent into Fleet.",
Run: func(c *cobra.Command, args []string) {
if err := enroll(streams, c); err != nil {
fmt.Fprintf(streams.Err, "Error: %v\n%s\n", err, troubleshootMessage())
logExternal(fmt.Sprintf("%s enroll failed: %s", paths.BinaryName, err))
os.Exit(1)
}
},
}
addEnrollFlags(cmd)
cmd.Flags().BoolP("force", "f", false, "Force overwrite the current and do not prompt for confirmation")
// used by install command
cmd.Flags().BoolP(fromInstallArg, "", false, "Set by install command to signal this was executed from install")
cmd.Flags().MarkHidden(fromInstallArg) //nolint:errcheck //not required
// platform specific flags
addPlatformFlags(cmd)
return cmd
}
func addEnrollFlags(cmd *cobra.Command) {
cmd.Flags().StringP("url", "", "", "URL to enroll Agent into Fleet")
cmd.Flags().StringP("enrollment-token", "t", "", "Enrollment token to use to enroll Agent into Fleet")
cmd.Flags().StringP("id", "", "", "Agent ID to use for enrollment into Fleet")
cmd.Flags().StringP("replace-token", "", "", "Replace token that that allows the Agent to be replace with the provided --id as long as this token matches")
cmd.Flags().StringP("fleet-server-es", "", "", "Start and run a Fleet Server alongside this Elastic Agent connecting to the provided Elasticsearch")
cmd.Flags().StringP("fleet-server-es-ca", "", "", "Path to certificate authority for Fleet Server to use to communicate with Elasticsearch")
cmd.Flags().StringP("fleet-server-es-ca-trusted-fingerprint", "", "", "Elasticsearch certificate authority's SHA256 fingerprint for Fleet Server to use")
cmd.Flags().BoolP("fleet-server-es-insecure", "", false, "Disables validation of Elasticsearch certificates for Fleet Server")
cmd.Flags().StringP("fleet-server-es-cert", "", "", "Client certificate for Fleet Server to use when connecting to Elasticsearch")
cmd.Flags().StringP("fleet-server-es-cert-key", "", "", "Client private key for Fleet Server to use when connecting to Elasticsearch")
cmd.Flags().StringP("fleet-server-service-token", "", "", "Service token for Fleet Server to use for communication with Elasticsearch")
cmd.Flags().StringP("fleet-server-service-token-path", "", "", "Filepath for the service token secret file used by Fleet Server for communication with Elasticsearch")
cmd.Flags().StringP("fleet-server-policy", "", "", "Start and run a Fleet Server on this specific policy")
cmd.Flags().StringP("fleet-server-host", "", "", "Fleet Server HTTP binding host (overrides the policy)")
cmd.Flags().Uint16P("fleet-server-port", "", 0, "Fleet Server HTTP binding port (overrides the policy)")
cmd.Flags().StringP("fleet-server-cert", "", "", "Certificate for Fleet Server to use for exposed HTTPS endpoint")
cmd.Flags().StringP("fleet-server-cert-key", "", "", "Private key for the certificate used by Fleet Server for exposed HTTPS endpoint")
cmd.Flags().StringP("fleet-server-cert-key-passphrase", "", "", "Path for private key passphrase file used to decrypt Fleet Server certificate key")
cmd.Flags().StringP("fleet-server-client-auth", "", "none", "Fleet Server mTLS client authentication for connecting Elastic Agents. Must be one of [none, optional, required]")
cmd.Flags().StringSliceP("header", "", []string{}, "Headers used by Fleet Server when communicating with Elasticsearch")
cmd.Flags().BoolP("fleet-server-insecure-http", "", false, "Expose Fleet Server over HTTP (not recommended; insecure)")
cmd.Flags().StringP("certificate-authorities", "a", "", "Comma-separated list of root certificates for server verification used by Elastic Agent and Fleet Server")
cmd.Flags().StringP("ca-sha256", "p", "", "Comma-separated list of certificate authority hash pins for server verification used by Elastic Agent and Fleet Server")
cmd.Flags().StringP("elastic-agent-cert", "", "", "Elastic Agent client certificate to use with Fleet Server during mTLS authentication")
cmd.Flags().StringP("elastic-agent-cert-key", "", "", "Elastic Agent client private key to use with Fleet Server during mTLS authentication")
cmd.Flags().StringP("elastic-agent-cert-key-passphrase", "", "", "Path for private key passphrase file used to decrypt Elastic Agent client certificate key")
cmd.Flags().BoolP("insecure", "i", false, "Allow insecure connection made by the Elastic Agent. It's also required to use a Fleet Server on a HTTP endpoint")
cmd.Flags().StringP("staging", "", "", "Configures Elastic Agent to download artifacts from a staging build")
cmd.Flags().StringP("proxy-url", "", "", "Configures the proxy URL: when bootstrapping Fleet Server, it's the proxy used by Fleet Server to connect to Elasticsearch; when enrolling the Elastic Agent to Fleet Server, it's the proxy used by the Elastic Agent to connect to Fleet Server")
cmd.Flags().BoolP("proxy-disabled", "", false, "Disable proxy support including environment variables: when bootstrapping Fleet Server, it's the proxy used by Fleet Server to connect to Elasticsearch; when enrolling the Elastic Agent to Fleet Server, it's the proxy used by the Elastic Agent to connect to Fleet Server")
cmd.Flags().StringSliceP("proxy-header", "", []string{}, "Proxy headers used with CONNECT request: when bootstrapping Fleet Server, it's the proxy used by Fleet Server to connect to Elasticsearch; when enrolling the Elastic Agent to Fleet Server, it's the proxy used by the Elastic Agent to connect to Fleet Server")
cmd.Flags().BoolP("delay-enroll", "", false, "Delays enrollment to occur on first start of the Elastic Agent service")
cmd.Flags().DurationP("daemon-timeout", "", 0, "Timeout waiting for Elastic Agent daemon")
cmd.Flags().DurationP("enroll-timeout", "", 10*time.Minute, "Timeout waiting for Elastic Agent enroll command. A negative value disables the timeout.")
cmd.Flags().DurationP("fleet-server-timeout", "", 0, "When bootstrapping Fleet Server, timeout waiting for Fleet Server to be ready to start enrollment")
cmd.Flags().Bool("skip-daemon-reload", false, "Skip daemon reload after enrolling")
cmd.Flags().StringSliceP("tag", "", []string{}, "User-set tags")
cmd.Flags().MarkHidden("skip-daemon-reload") //nolint:errcheck // an error is only returned if the flag does not exist.
}
func validateEnrollFlags(cmd *cobra.Command) error {
ca, _ := cmd.Flags().GetString("certificate-authorities")
if ca != "" && !filepath.IsAbs(ca) {
return errors.New("--certificate-authorities must be provided as an absolute path", errors.M("path", ca), errors.TypeConfig)
}
cert, _ := cmd.Flags().GetString("elastic-agent-cert")
if cert != "" && !filepath.IsAbs(cert) {
return errors.New("--elastic-agent-cert must be provided as an absolute path", errors.M("path", cert), errors.TypeConfig)
}
key, _ := cmd.Flags().GetString("elastic-agent-cert-key")
if key != "" && !filepath.IsAbs(key) {
return errors.New("--elastic-agent-cert-key must be provided as an absolute path", errors.M("path", key), errors.TypeConfig)
}
keyPassphrase, _ := cmd.Flags().GetString("elastic-agent-cert-key-passphrase")
if keyPassphrase != "" {
if !filepath.IsAbs(keyPassphrase) {
return errors.New("--elastic-agent-cert-key-passphrase must be provided as an absolute path", errors.M("path", keyPassphrase), errors.TypeConfig)
}
if cert == "" || key == "" {
return errors.New("--elastic-agent-cert and --elastic-agent-cert-key must be provided when using --elastic-agent-cert-key-passphrase", errors.M("path", keyPassphrase), errors.TypeConfig)
}
}
esCa, _ := cmd.Flags().GetString("fleet-server-es-ca")
if esCa != "" && !filepath.IsAbs(esCa) {
return errors.New("--fleet-server-es-ca must be provided as an absolute path", errors.M("path", esCa), errors.TypeConfig)
}
esCert, _ := cmd.Flags().GetString("fleet-server-es-cert")
if esCert != "" && !filepath.IsAbs(esCert) {
return errors.New("--fleet-server-es-cert must be provided as an absolute path", errors.M("path", esCert), errors.TypeConfig)
}
esCertKey, _ := cmd.Flags().GetString("fleet-server-es-cert-key")
if esCertKey != "" && !filepath.IsAbs(esCertKey) {
return errors.New("--fleet-server-es-cert-key must be provided as an absolute path", errors.M("path", esCertKey), errors.TypeConfig)
}
fCert, _ := cmd.Flags().GetString("fleet-server-cert")
if fCert != "" && !filepath.IsAbs(fCert) {
return errors.New("--fleet-server-cert must be provided as an absolute path", errors.M("path", fCert), errors.TypeConfig)
}
fCertKey, _ := cmd.Flags().GetString("fleet-server-cert-key")
if fCertKey != "" && !filepath.IsAbs(fCertKey) {
return errors.New("--fleet-server-cert-key must be provided as an absolute path", errors.M("path", fCertKey), errors.TypeConfig)
}
fTokenPath, _ := cmd.Flags().GetString("fleet-server-service-token-path")
if fTokenPath != "" && !filepath.IsAbs(fTokenPath) {
return errors.New("--fleet-server-service-token-path must be provided as an absolute path", errors.M("path", fTokenPath), errors.TypeConfig)
}
fToken, _ := cmd.Flags().GetString("fleet-server-service-token")
if fToken != "" && fTokenPath != "" {
return errors.New("--fleet-server-service-token and --fleet-server-service-token-path are mutually exclusive", errors.TypeConfig)
}
fPassphrase, _ := cmd.Flags().GetString("fleet-server-cert-key-passphrase")
if fPassphrase != "" && !filepath.IsAbs(fPassphrase) {
return errors.New("--fleet-server-cert-key-passphrase must be provided as an absolute path", errors.M("path", fPassphrase), errors.TypeConfig)
}
fClientAuth, _ := cmd.Flags().GetString("fleet-server-client-auth")
switch fClientAuth {
case "none", "optional", "required":
// NOTE we can split this case if we want to do additional checks when optional or required is passed.
default:
return errors.New("--fleet-server-client-auth must be one of [none, optional, required]")
}
return nil
}
func buildEnrollmentFlags(cmd *cobra.Command, url string, token string) []string {
if url == "" {
url, _ = cmd.Flags().GetString("url")
}
if token == "" {
token, _ = cmd.Flags().GetString("enrollment-token")
}
id, _ := cmd.Flags().GetString("id")
replaceToken, _ := cmd.Flags().GetString("replace-token")
fServer, _ := cmd.Flags().GetString("fleet-server-es")
fElasticSearchCA, _ := cmd.Flags().GetString("fleet-server-es-ca")
fElasticSearchCASHA256, _ := cmd.Flags().GetString("fleet-server-es-ca-trusted-fingerprint")
fElasticSearchInsecure, _ := cmd.Flags().GetBool("fleet-server-es-insecure")
fElasticSearchClientCert, _ := cmd.Flags().GetString("fleet-server-es-cert")
fElasticSearchClientCertKey, _ := cmd.Flags().GetString("fleet-server-es-cert-key")
fServiceToken, _ := cmd.Flags().GetString("fleet-server-service-token")
fServiceTokenPath, _ := cmd.Flags().GetString("fleet-server-service-token-path")
fPolicy, _ := cmd.Flags().GetString("fleet-server-policy")
fHost, _ := cmd.Flags().GetString("fleet-server-host")
fPort, _ := cmd.Flags().GetUint16("fleet-server-port")
fCert, _ := cmd.Flags().GetString("fleet-server-cert")
fCertKey, _ := cmd.Flags().GetString("fleet-server-cert-key")
fPassphrase, _ := cmd.Flags().GetString("fleet-server-cert-key-passphrase")
fClientAuth, _ := cmd.Flags().GetString("fleet-server-client-auth")
fHeaders, _ := cmd.Flags().GetStringSlice("header")
fInsecure, _ := cmd.Flags().GetBool("fleet-server-insecure-http")
ca, _ := cmd.Flags().GetString("certificate-authorities")
cert, _ := cmd.Flags().GetString("elastic-agent-cert")
key, _ := cmd.Flags().GetString("elastic-agent-cert-key")
keyPassphrase, _ := cmd.Flags().GetString("elastic-agent-cert-key-passphrase")
sha256, _ := cmd.Flags().GetString("ca-sha256")
insecure, _ := cmd.Flags().GetBool("insecure")
staging, _ := cmd.Flags().GetString("staging")
fProxyURL, _ := cmd.Flags().GetString("proxy-url")
fProxyDisabled, _ := cmd.Flags().GetBool("proxy-disabled")
fProxyHeaders, _ := cmd.Flags().GetStringSlice("proxy-header")
delayEnroll, _ := cmd.Flags().GetBool("delay-enroll")
daemonTimeout, _ := cmd.Flags().GetDuration("daemon-timeout")
enrollTimeout, _ := cmd.Flags().GetDuration("enroll-timeout")
fTimeout, _ := cmd.Flags().GetDuration("fleet-server-timeout")
skipDaemonReload, _ := cmd.Flags().GetBool("skip-daemon-reload")
fTags, _ := cmd.Flags().GetStringSlice("tag")
args := []string{}
if url != "" {
args = append(args, "--url")
args = append(args, url)
}
if token != "" {
args = append(args, "--enrollment-token")
args = append(args, token)
}
if id != "" {
args = append(args, "--id")
args = append(args, id)
}
if replaceToken != "" {
args = append(args, "--replace-token")
args = append(args, replaceToken)
}
if fServer != "" {
args = append(args, "--fleet-server-es")
args = append(args, fServer)
}
if fElasticSearchCA != "" {
args = append(args, "--fleet-server-es-ca")
args = append(args, fElasticSearchCA)
}
if fElasticSearchCASHA256 != "" {
args = append(args, "--fleet-server-es-ca-trusted-fingerprint")
args = append(args, fElasticSearchCASHA256)
}
if fElasticSearchClientCert != "" {
args = append(args, "--fleet-server-es-cert")
args = append(args, fElasticSearchClientCert)
}
if fElasticSearchClientCertKey != "" {
args = append(args, "--fleet-server-es-cert-key")
args = append(args, fElasticSearchClientCertKey)
}
if fServiceToken != "" {
args = append(args, "--fleet-server-service-token")
args = append(args, fServiceToken)
}
if fServiceTokenPath != "" {
args = append(args, "--fleet-server-service-token-path")
args = append(args, fServiceTokenPath)
}
if fPolicy != "" {
args = append(args, "--fleet-server-policy")
args = append(args, fPolicy)
}
if fHost != "" {
args = append(args, "--fleet-server-host")
args = append(args, fHost)
}
if fPort > 0 {
args = append(args, "--fleet-server-port")
args = append(args, strconv.Itoa(int(fPort)))
}
if fCert != "" {
args = append(args, "--fleet-server-cert")
args = append(args, fCert)
}
if fCertKey != "" {
args = append(args, "--fleet-server-cert-key")
args = append(args, fCertKey)
}
if fPassphrase != "" {
args = append(args, "--fleet-server-cert-key-passphrase")
args = append(args, fPassphrase)
}
if fClientAuth != "" {
args = append(args, "--fleet-server-client-auth")
args = append(args, fClientAuth)
}
if daemonTimeout != 0 {
args = append(args, "--daemon-timeout")
args = append(args, daemonTimeout.String())
}
if enrollTimeout != 0 {
args = append(args, "--enroll-timeout")
args = append(args, enrollTimeout.String())
}
if fTimeout != 0 {
args = append(args, "--fleet-server-timeout")
args = append(args, fTimeout.String())
}
for k, v := range mapFromEnvList(fHeaders) {
args = append(args, "--header")
args = append(args, k+"="+v)
}
if fInsecure {
args = append(args, "--fleet-server-insecure-http")
}
if ca != "" {
args = append(args, "--certificate-authorities")
args = append(args, ca)
}
if cert != "" {
args = append(args, "--elastic-agent-cert")
args = append(args, cert)
}
if key != "" {
args = append(args, "--elastic-agent-cert-key")
args = append(args, key)
}
if keyPassphrase != "" {
args = append(args, "--elastic-agent-cert-key-passphrase")
args = append(args, keyPassphrase)
}
if sha256 != "" {
args = append(args, "--ca-sha256")
args = append(args, sha256)
}
if insecure {
args = append(args, "--insecure")
}
if staging != "" {
args = append(args, "--staging")
args = append(args, staging)
}
if fProxyURL != "" {
args = append(args, "--proxy-url")
args = append(args, fProxyURL)
}
if fProxyDisabled {
args = append(args, "--proxy-disabled")
args = append(args, "true")
}
for k, v := range mapFromEnvList(fProxyHeaders) {
args = append(args, "--proxy-header")
args = append(args, k+"="+v)
}
if delayEnroll {
args = append(args, "--delay-enroll")
}
if fElasticSearchInsecure {
args = append(args, "--fleet-server-es-insecure")
}
if skipDaemonReload {
args = append(args, "--skip-daemon-reload")
}
for _, v := range fTags {
args = append(args, "--tag", v)
}
return args
}
func enroll(streams *cli.IOStreams, cmd *cobra.Command) error {
err := validateEnrollFlags(cmd)
if err != nil {
return err
}
fromInstall, _ := cmd.Flags().GetBool(fromInstallArg)
hasRoot, err := utils.HasRoot()
if err != nil {
return fmt.Errorf("checking if running with root/Administrator privileges: %w", err)
}
if hasRoot && !fromInstall {
binPath, err := os.Executable()
if err != nil {
return fmt.Errorf("error while getting executable path: %w", err)
}
isOwner, err := isOwnerExec(binPath)
if err != nil {
return fmt.Errorf("ran into an error while figuring out if user is allowed to execute the enroll command: %w", err)
}
if !isOwner {
return UserOwnerMismatchError
}
}
pathConfigFile := paths.ConfigFile()
rawConfig, err := config.LoadFile(pathConfigFile)
if err != nil {
return errors.New(err,
fmt.Sprintf("could not read configuration file %s", pathConfigFile),
errors.TypeFilesystem,
errors.M(errors.MetaKeyPath, pathConfigFile))
}
cfg, err := configuration.NewFromConfig(rawConfig)
if err != nil {
return errors.New(err,
fmt.Sprintf("could not parse configuration file %s", pathConfigFile),
errors.TypeFilesystem,
errors.M(errors.MetaKeyPath, pathConfigFile))
}
staging, _ := cmd.Flags().GetString("staging")
if staging != "" {
if len(staging) < 8 {
return errors.New(fmt.Errorf("invalid staging build hash; must be at least 8 characters"), "Error")
}
}
force, _ := cmd.Flags().GetBool("force")
if fromInstall {
force = true
}
// prompt only when it is not forced and is already enrolled
if !force && (cfg.Fleet != nil && cfg.Fleet.Enabled) {
confirm, err := cli.Confirm("This will replace your current settings. Do you want to continue?", true)
if err != nil {
return errors.New(err, "problem reading prompt response")
}
if !confirm {
fmt.Fprintln(streams.Out, "Enrollment was cancelled by the user")
return nil
}
}
// enroll is invoked either manually or from install with redirected IO
// no need to log to file
cfg.Settings.LoggingConfig.ToFiles = false
cfg.Settings.LoggingConfig.ToStderr = true
logger, err := logger.NewFromConfig("", cfg.Settings.LoggingConfig, cfg.Settings.EventLoggingConfig, false)
if err != nil {
return err
}
insecure, _ := cmd.Flags().GetBool("insecure")
url, _ := cmd.Flags().GetString("url")
enrollmentToken, _ := cmd.Flags().GetString("enrollment-token")
id, _ := cmd.Flags().GetString("id")
replaceToken, _ := cmd.Flags().GetString("replace-token")
fServer, _ := cmd.Flags().GetString("fleet-server-es")
fElasticSearchCA, _ := cmd.Flags().GetString("fleet-server-es-ca")
fElasticSearchCASHA256, _ := cmd.Flags().GetString("fleet-server-es-ca-trusted-fingerprint")
fElasticSearchInsecure, _ := cmd.Flags().GetBool("fleet-server-es-insecure")
fElasticSearchClientCert, _ := cmd.Flags().GetString("fleet-server-es-cert")
fElasticSearchClientCertKey, _ := cmd.Flags().GetString("fleet-server-es-cert-key")
fHeaders, _ := cmd.Flags().GetStringSlice("header")
fServiceToken, _ := cmd.Flags().GetString("fleet-server-service-token")
fServiceTokenPath, _ := cmd.Flags().GetString("fleet-server-service-token-path")
fPolicy, _ := cmd.Flags().GetString("fleet-server-policy")
fHost, _ := cmd.Flags().GetString("fleet-server-host")
fPort, _ := cmd.Flags().GetUint16("fleet-server-port")
fInternalPort, _ := cmd.Flags().GetUint16("fleet-server-internal-port")
fCert, _ := cmd.Flags().GetString("fleet-server-cert")
fCertKey, _ := cmd.Flags().GetString("fleet-server-cert-key")
fPassphrase, _ := cmd.Flags().GetString("fleet-server-cert-key-passphrase")
fClientAuth, _ := cmd.Flags().GetString("fleet-server-client-auth")
fInsecure, _ := cmd.Flags().GetBool("fleet-server-insecure-http")
proxyURL, _ := cmd.Flags().GetString("proxy-url")
proxyDisabled, _ := cmd.Flags().GetBool("proxy-disabled")
proxyHeaders, _ := cmd.Flags().GetStringSlice("proxy-header")
delayEnroll, _ := cmd.Flags().GetBool("delay-enroll")
daemonTimeout, _ := cmd.Flags().GetDuration("daemon-timeout")
enrollTimeout, _ := cmd.Flags().GetDuration("enroll-timeout")
fTimeout, _ := cmd.Flags().GetDuration("fleet-server-timeout")
skipDaemonReload, _ := cmd.Flags().GetBool("skip-daemon-reload")
tags, _ := cmd.Flags().GetStringSlice("tag")
caStr, _ := cmd.Flags().GetString("certificate-authorities")
CAs := cli.StringToSlice(caStr)
caSHA256str, _ := cmd.Flags().GetString("ca-sha256")
caSHA256 := cli.StringToSlice(caSHA256str)
cert, _ := cmd.Flags().GetString("elastic-agent-cert")
key, _ := cmd.Flags().GetString("elastic-agent-cert-key")
keyPassphrase, _ := cmd.Flags().GetString("elastic-agent-cert-key-passphrase")
ctx := handleSignal(context.Background())
if enrollTimeout > 0 {
eCtx, cancel := context.WithTimeout(ctx, enrollTimeout)
defer cancel()
ctx = eCtx
}
// On MacOS Ventura and above, fixing the permissions on enrollment during installation fails with the error:
// Error: failed to fix permissions: chown /Library/Elastic/Agent/data/elastic-agent-c13f91/elastic-agent.app: operation not permitted
// This is because we are fixing permissions twice, once during installation and again during the enrollment step.
// When we are enrolling as part of installation on MacOS, skip the second attempt to fix permissions.
var fixPermissions *utils.FileOwner
if fromInstall {
perms, err := getFileOwnerFromCmd(cmd)
if err != nil {
// no context is added because the error is clear and user facing
return err
}
fixPermissions = &perms
}
if runtime.GOOS == "darwin" {
fixPermissions = nil
}
options := enrollCmdOption{
EnrollAPIKey: enrollmentToken,
ID: id,
ReplaceToken: replaceToken,
URL: url,
CAs: CAs,
CASha256: caSHA256,
Certificate: cert,
Key: key,
KeyPassphrasePath: keyPassphrase,
Insecure: insecure,
UserProvidedMetadata: make(map[string]interface{}),
Staging: staging,
FixPermissions: fixPermissions,
ProxyURL: proxyURL,
ProxyDisabled: proxyDisabled,
ProxyHeaders: mapFromEnvList(proxyHeaders),
DelayEnroll: delayEnroll,
DaemonTimeout: daemonTimeout,
SkipDaemonRestart: skipDaemonReload,
Tags: tags,
FleetServer: enrollCmdFleetServerOption{
ConnStr: fServer,
ElasticsearchCA: fElasticSearchCA,
ElasticsearchCASHA256: fElasticSearchCASHA256,
ElasticsearchInsecure: fElasticSearchInsecure,
ElasticsearchCert: fElasticSearchClientCert,
ElasticsearchCertKey: fElasticSearchClientCertKey,
ServiceToken: fServiceToken,
ServiceTokenPath: fServiceTokenPath,
PolicyID: fPolicy,
Host: fHost,
Port: fPort,
Cert: fCert,
CertKey: fCertKey,
CertKeyPassphrasePath: fPassphrase,
ClientAuth: fClientAuth,
Insecure: fInsecure,
SpawnAgent: !fromInstall,
Headers: mapFromEnvList(fHeaders),
Timeout: fTimeout,
InternalPort: fInternalPort,
},
}
var storeOpts []storage.ReplaceOnSuccessStoreOptionFunc
var encryptOpts []storage.EncryptedOptionFunc
if fixPermissions != nil {
storeOpts = append(storeOpts, storage.ReplaceOnSuccessStoreWithOwnership(*fixPermissions))
encryptOpts = append(encryptOpts, storage.EncryptedStoreWithOwnership(*fixPermissions))
}
encStore, err := storage.NewEncryptedDiskStore(ctx, paths.AgentConfigFile(), encryptOpts...)
if err != nil {
return fmt.Errorf("failed to create encrypted disk store: %w", err)
}
store := storage.NewReplaceOnSuccessStore(
pathConfigFile,
application.DefaultAgentFleetConfig,
encStore,
storeOpts...,
)
c, err := newEnrollCmd(
logger,
&options,
pathConfigFile,
store,
nil,
)
if err != nil {
return err
}
return c.Execute(ctx, streams)
}
func handleSignal(ctx context.Context) context.Context {
ctx, cfunc := context.WithCancel(ctx)
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() {
select {
case <-sigs:
cfunc()
case <-ctx.Done():
}
signal.Stop(sigs)
close(sigs)
}()
return ctx
}
func mapFromEnvList(envList []string) map[string]string {
m := make(map[string]string)
for _, kv := range envList {
keyValue := strings.SplitN(kv, "=", 2)
if len(keyValue) != 2 {
continue
}
m[keyValue[0]] = keyValue[1]
}
return m
}