From 381a505fb95a1d225718dff0b6cef2916abb24f4 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 14 Dec 2021 16:51:29 -0800 Subject: [PATCH] elastic-agent elasticsearch CA fingerprint support (#29128) (#29428) * initial commit * Update Fingerprint method * Switch to using newly added CATrustedFingerprint attribute * rename flag * Fix broken flag * Add CHANGELOG * Add container support (cherry picked from commit fcb7b81faaece55703c443a32e26b94a1d1f6164) Co-authored-by: Michel Laterman <82832767+michel-laterman@users.noreply.github.com> --- x-pack/elastic-agent/CHANGELOG.next.asciidoc | 2 ++ .../elastic-agent/pkg/agent/cmd/container.go | 4 +++ x-pack/elastic-agent/pkg/agent/cmd/enroll.go | 8 ++++++ .../elastic-agent/pkg/agent/cmd/enroll_cmd.go | 17 +++++++++--- .../pkg/agent/cmd/setup_config.go | 26 ++++++++++--------- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/x-pack/elastic-agent/CHANGELOG.next.asciidoc b/x-pack/elastic-agent/CHANGELOG.next.asciidoc index 759fe4078537..9d4a5932ad40 100644 --- a/x-pack/elastic-agent/CHANGELOG.next.asciidoc +++ b/x-pack/elastic-agent/CHANGELOG.next.asciidoc @@ -150,3 +150,5 @@ - Add diagnostics collect command to gather beat metadata, config, policy, and logs and bundle it into an archive. {pull}28461[28461] - Add `KIBANA_FLEET_SERVICE_TOKEN` to Elastic Agent container. {pull}28096[28096] - Allow pprof endpoints for elastic-agent or beats if enabled. {pull}28983[28983] {pull}29155[29155] +- Add --fleet-server-es-ca-trusted-fingerprint flag to allow agent/fleet-server to work with elasticsearch clusters using self signed certs. {pull}29128[29128] +- Discover changes in Kubernetes nodes metadata as soon as they happen. {pull}23139[23139] diff --git a/x-pack/elastic-agent/pkg/agent/cmd/container.go b/x-pack/elastic-agent/pkg/agent/cmd/container.go index e0f9f3dcfb70..d72b0128430e 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/container.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/container.go @@ -96,6 +96,7 @@ The following actions are possible and grouped based on the actions. FLEET_SERVER_ELASTICSEARCH_USERNAME - elasticsearch username for Fleet Server [$ELASTICSEARCH_USERNAME] FLEET_SERVER_ELASTICSEARCH_PASSWORD - elasticsearch password for Fleet Server [$ELASTICSEARCH_PASSWORD] FLEET_SERVER_ELASTICSEARCH_CA - path to certificate authority to use with communicate with elasticsearch [$ELASTICSEARCH_CA] + FLEET_SERVER_ELASTICSEARCH_CA_TRUSTED_FINGERPRINT - The sha-256 fingerprint value of the certificate authority to trust FLEET_SERVER_ELASTICSEARCH_INSECURE - disables cert validation for communication with Elasticsearch FLEET_SERVER_SERVICE_TOKEN - service token to use for communication with elasticsearch FLEET_SERVER_POLICY_ID - policy ID for Fleet Server to use for itself ("Default Fleet Server policy" used when undefined) @@ -359,6 +360,9 @@ func buildEnrollArgs(cfg setupConfig, token string, policyID string) ([]string, if cfg.FleetServer.Elasticsearch.CA != "" { args = append(args, "--fleet-server-es-ca", cfg.FleetServer.Elasticsearch.CA) } + if cfg.FleetServer.Elasticsearch.CATrustedFingerprint != "" { + args = append(args, "--fleet-server-es-ca-trusted-fingerprint", cfg.FleetServer.Elasticsearch.CATrustedFingerprint) + } if cfg.FleetServer.Host != "" { args = append(args, "--fleet-server-host", cfg.FleetServer.Host) } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go index 126161fa4c4a..6a66b4fdfc1c 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go @@ -53,6 +53,7 @@ func addEnrollFlags(cmd *cobra.Command) { cmd.Flags().StringP("enrollment-token", "t", "", "Enrollment token to use to enroll Agent into Fleet") cmd.Flags().StringP("fleet-server-es", "", "", "Start and run a Fleet Server along side this Elastic Agent connecting to the provided elasticsearch") cmd.Flags().StringP("fleet-server-es-ca", "", "", "Path to certificate authority to use with communicate with elasticsearch") + cmd.Flags().StringP("fleet-server-es-ca-trusted-fingerprint", "", "", "Elasticsearch certificate authority's SHA256 fingerprint") cmd.Flags().BoolP("fleet-server-es-insecure", "", false, "Disables validation of certificates") cmd.Flags().StringP("fleet-server-service-token", "", "", "Service token to use for communication with elasticsearch") cmd.Flags().StringP("fleet-server-policy", "", "", "Start and run a Fleet Server on this specific policy") @@ -103,6 +104,7 @@ func buildEnrollmentFlags(cmd *cobra.Command, url string, token string) []string } 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") fServiceToken, _ := cmd.Flags().GetString("fleet-server-service-token") fPolicy, _ := cmd.Flags().GetString("fleet-server-policy") @@ -140,6 +142,10 @@ func buildEnrollmentFlags(cmd *cobra.Command, url string, token string) []string 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 fServiceToken != "" { args = append(args, "--fleet-server-service-token") args = append(args, fServiceToken) @@ -285,6 +291,7 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { enrollmentToken, _ := cmd.Flags().GetString("enrollment-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") fHeaders, _ := cmd.Flags().GetStringSlice("header") fServiceToken, _ := cmd.Flags().GetString("fleet-server-service-token") @@ -326,6 +333,7 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, args []string) error { FleetServer: enrollCmdFleetServerOption{ ConnStr: fServer, ElasticsearchCA: fElasticSearchCA, + ElasticsearchCASHA256: fElasticSearchCASHA256, ElasticsearchInsecure: fElasticSearchInsecure, ServiceToken: fServiceToken, PolicyID: fPolicy, diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go index 25365c9afe92..0023d83fde0d 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go @@ -77,6 +77,7 @@ type enrollCmd struct { type enrollCmdFleetServerOption struct { ConnStr string ElasticsearchCA string + ElasticsearchCASHA256 string ElasticsearchInsecure bool ServiceToken string PolicyID string @@ -110,6 +111,7 @@ type enrollCmdOption struct { FleetServer enrollCmdFleetServerOption `yaml:"-"` } +// remoteConfig returns the configuration used to connect the agent to a fleet process. func (e *enrollCmdOption) remoteConfig() (remote.Config, error) { cfg, err := remote.NewConfigFromURL(e.URL) if err != nil { @@ -311,7 +313,7 @@ func (c *enrollCmd) fleetServerBootstrap(ctx context.Context, persistentConfig m c.options.FleetServer.ConnStr, c.options.FleetServer.ServiceToken, c.options.FleetServer.PolicyID, c.options.FleetServer.Host, c.options.FleetServer.Port, c.options.FleetServer.InternalPort, - c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA, + c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA, c.options.FleetServer.ElasticsearchCASHA256, c.options.FleetServer.Headers, c.options.ProxyURL, c.options.ProxyDisabled, @@ -517,7 +519,7 @@ func (c *enrollCmd) enroll(ctx context.Context, persistentConfig map[string]inte c.options.FleetServer.ConnStr, c.options.FleetServer.ServiceToken, c.options.FleetServer.PolicyID, c.options.FleetServer.Host, c.options.FleetServer.Port, c.options.FleetServer.InternalPort, - c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA, + c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA, c.options.FleetServer.ElasticsearchCASHA256, c.options.FleetServer.Headers, c.options.ProxyURL, c.options.ProxyDisabled, c.options.ProxyHeaders, c.options.FleetServer.ElasticsearchInsecure, @@ -853,7 +855,7 @@ func storeAgentInfo(s saver, reader io.Reader) error { func createFleetServerBootstrapConfig( connStr, serviceToken, policyID, host string, port uint16, internalPort uint16, - cert, key, esCA string, + cert, key, esCA, esCASHA256 string, headers map[string]string, proxyURL string, proxyDisabled bool, @@ -875,6 +877,15 @@ func createFleetServerBootstrapConfig( es.TLS.CAs = []string{esCA} } } + if esCASHA256 != "" { + if es.TLS == nil { + es.TLS = &tlscommon.Config{ + CATrustedFingerprint: esCASHA256, + } + } else { + es.TLS.CATrustedFingerprint = esCASHA256 + } + } if host == "" { host = defaultFleetServerHost } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/setup_config.go b/x-pack/elastic-agent/pkg/agent/cmd/setup_config.go index 6b7e1edf8b3d..b33c0f8fa8ee 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/setup_config.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/setup_config.go @@ -40,12 +40,13 @@ type fleetServerConfig struct { } type elasticsearchConfig struct { - CA string `config:"ca"` - Host string `config:"host"` - Username string `config:"username"` - Password string `config:"password"` - ServiceToken string `config:"service_token"` - Insecure bool `config:"insecure"` + CA string `config:"ca"` + CATrustedFingerprint string `config:"ca_trusted_fingerprint"` + Host string `config:"host"` + Username string `config:"username"` + Password string `config:"password"` + ServiceToken string `config:"service_token"` + Insecure bool `config:"insecure"` } type kibanaConfig struct { @@ -91,12 +92,13 @@ func defaultAccessConfig() (setupConfig, error) { Cert: envWithDefault("", "FLEET_SERVER_CERT"), CertKey: envWithDefault("", "FLEET_SERVER_CERT_KEY"), Elasticsearch: elasticsearchConfig{ - Host: envWithDefault("http://elasticsearch:9200", "FLEET_SERVER_ELASTICSEARCH_HOST", "ELASTICSEARCH_HOST"), - Username: envWithDefault("elastic", "FLEET_SERVER_ELASTICSEARCH_USERNAME", "ELASTICSEARCH_USERNAME"), - Password: envWithDefault("changeme", "FLEET_SERVER_ELASTICSEARCH_PASSWORD", "ELASTICSEARCH_PASSWORD"), - ServiceToken: envWithDefault("", "FLEET_SERVER_SERVICE_TOKEN"), - CA: envWithDefault("", "FLEET_SERVER_ELASTICSEARCH_CA", "ELASTICSEARCH_CA"), - Insecure: envBool("FLEET_SERVER_ELASTICSEARCH_INSECURE"), + Host: envWithDefault("http://elasticsearch:9200", "FLEET_SERVER_ELASTICSEARCH_HOST", "ELASTICSEARCH_HOST"), + Username: envWithDefault("elastic", "FLEET_SERVER_ELASTICSEARCH_USERNAME", "ELASTICSEARCH_USERNAME"), + Password: envWithDefault("changeme", "FLEET_SERVER_ELASTICSEARCH_PASSWORD", "ELASTICSEARCH_PASSWORD"), + ServiceToken: envWithDefault("", "FLEET_SERVER_SERVICE_TOKEN"), + CA: envWithDefault("", "FLEET_SERVER_ELASTICSEARCH_CA", "ELASTICSEARCH_CA"), + CATrustedFingerprint: envWithDefault("", "FLEET_SERVER_ELASTICSEARCH_CA_TRUSTED_FINGERPRINT"), + Insecure: envBool("FLEET_SERVER_ELASTICSEARCH_INSECURE"), }, Enable: envBool("FLEET_SERVER_ENABLE"), Host: envWithDefault("", "FLEET_SERVER_HOST"),