diff --git a/x-pack/elastic-agent/CHANGELOG.next.asciidoc b/x-pack/elastic-agent/CHANGELOG.next.asciidoc index 805132d6bdc..302bd0d882b 100644 --- a/x-pack/elastic-agent/CHANGELOG.next.asciidoc +++ b/x-pack/elastic-agent/CHANGELOG.next.asciidoc @@ -75,3 +75,4 @@ - Add support for enrollment with local bootstrap of Fleet Server {pull}23865[23865] - Add TLS support for Fleet Server {pull}24142[24142] - Add support for Fleet Server running under Elastic Agent {pull}24220[24220] +- Add CA support to Elastic Agent docker image {pull}24486[24486] diff --git a/x-pack/elastic-agent/pkg/agent/application/config.go b/x-pack/elastic-agent/pkg/agent/application/config.go index 6c74b251ca0..cbb24018d30 100644 --- a/x-pack/elastic-agent/pkg/agent/application/config.go +++ b/x-pack/elastic-agent/pkg/agent/application/config.go @@ -28,11 +28,16 @@ func createFleetConfigFromEnroll(accessAPIKey string, kbn *kibana.Config) (*conf return cfg, nil } -func createFleetServerBootstrapConfig(connStr string, policyID string, host string, port uint16, cert string, key string) (*configuration.FleetAgentConfig, error) { +func createFleetServerBootstrapConfig(connStr string, policyID string, host string, port uint16, cert string, key string, esCA string) (*configuration.FleetAgentConfig, error) { es, err := configuration.ElasticsearchFromConnStr(connStr) if err != nil { return nil, err } + if esCA != "" { + es.TLS = &tlscommon.Config{ + CAs: []string{esCA}, + } + } cfg := configuration.DefaultFleetAgentConfig() cfg.Enabled = true cfg.Server = &configuration.FleetServerConfig{ diff --git a/x-pack/elastic-agent/pkg/agent/application/enroll_cmd.go b/x-pack/elastic-agent/pkg/agent/application/enroll_cmd.go index 7d33d9524b4..ff0b22a1159 100644 --- a/x-pack/elastic-agent/pkg/agent/application/enroll_cmd.go +++ b/x-pack/elastic-agent/pkg/agent/application/enroll_cmd.go @@ -81,14 +81,15 @@ type EnrollCmd struct { // EnrollCmdFleetServerOption define all the supported enrollment options for bootstrapping with Fleet Server. type EnrollCmdFleetServerOption struct { - ConnStr string - PolicyID string - Host string - Port uint16 - Cert string - CertKey string - Insecure bool - SpawnAgent bool + ConnStr string + ElasticsearchCA string + PolicyID string + Host string + Port uint16 + Cert string + CertKey string + Insecure bool + SpawnAgent bool } // EnrollCmdOption define all the supported enrollment option. @@ -227,7 +228,7 @@ func (c *EnrollCmd) fleetServerBootstrap(ctx context.Context) error { fleetConfig, err := createFleetServerBootstrapConfig( c.options.FleetServer.ConnStr, c.options.FleetServer.PolicyID, c.options.FleetServer.Host, c.options.FleetServer.Port, - c.options.FleetServer.Cert, c.options.FleetServer.CertKey) + c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA) configToStore := map[string]interface{}{ "fleet": fleetConfig, } @@ -388,7 +389,7 @@ func (c *EnrollCmd) enroll(ctx context.Context) error { serverConfig, err := createFleetServerBootstrapConfig( c.options.FleetServer.ConnStr, c.options.FleetServer.PolicyID, c.options.FleetServer.Host, c.options.FleetServer.Port, - c.options.FleetServer.Cert, c.options.FleetServer.CertKey) + c.options.FleetServer.Cert, c.options.FleetServer.CertKey, c.options.FleetServer.ElasticsearchCA) if err != nil { return err } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/container.go b/x-pack/elastic-agent/pkg/agent/cmd/container.go index cd4b3f7d79e..fdbbaa213a4 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/container.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/container.go @@ -18,6 +18,7 @@ import ( "github.com/spf13/cobra" + "github.com/elastic/beats/v7/libbeat/common/transport/tlscommon" "github.com/elastic/beats/v7/libbeat/kibana" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths" @@ -60,6 +61,7 @@ The following actions are possible and grouped based on the actions. KIBANA_FLEET_HOST - kibana host to enable Fleet on [$KIBANA_HOST] KIBANA_FLEET_USERNAME - kibana username to enable Fleet [$KIBANA_USERNAME] KIBANA_FLEET_PASSWORD - kibana password to enable Fleet [$KIBANA_PASSWORD] + KIBANA_FLEET_CA - path to certificate authority to use with communicate with Kibana [$KIBANA_CA] * Bootstrapping Fleet Server This bootstraps the Fleet Server to be run by this Elastic Agent. At least one Fleet Server is required in a Fleet @@ -69,6 +71,7 @@ The following actions are possible and grouped based on the actions. FLEET_SERVER_ELASTICSEARCH_HOST - elasticsearch host for Fleet Server to communicate with [$ELASTICSEARCH_HOST] 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_POLICY_NAME - name of policy for the Fleet Server to use for itself [$FLEET_TOKEN_POLICY_NAME] FLEET_SERVER_POLICY_ID - policy ID for Fleet Server to use for itself ("Default Fleet Server policy" used when undefined) FLEET_SERVER_HOST - binding host for Fleet Server HTTP (overrides the policy) @@ -86,6 +89,7 @@ The following actions are possible and grouped based on the actions. FLEET_ENROLLMENT_TOKEN - token to use for enrollment FLEET_TOKEN_NAME - token name to use for fetching token from Kibana FLEET_TOKEN_POLICY_NAME - token policy name to use for fetching token from Kibana + FLEET_CA - path to certificate authority to use with communicate with Fleet Server [$KIBANA_CA] FLEET_INSECURE - communicate with Fleet with either insecure HTTP or un-verified HTTPS KIBANA_FLEET_HOST - kibana host to enable create enrollment token on [$KIBANA_HOST] KIBANA_FLEET_USERNAME - kibana username to create enrollment token [$KIBANA_USERNAME] @@ -97,9 +101,11 @@ be used when the same credentials will be used across all the possible actions a ELASTICSEARCH_HOST - elasticsearch host [http://elasticsearch:9200] ELASTICSEARCH_USERNAME - elasticsearch username [elastic] ELASTICSEARCH_PASSWORD - elasticsearch password [changeme] + ELASTICSEARCH_CA - path to certificate authority to use with communicate with elasticsearch KIBANA_HOST - kibana host [http://kibana:5601] KIBANA_USERNAME - kibana username [$ELASTICSEARCH_USERNAME] KIBANA_PASSWORD - kibana password [$ELASTICSEARCH_PASSWORD] + KIBANA_CA - path to certificate authority to use with communicate with Kibana [$ELASTICSEARCH_CA] By default when this command starts it will check for an existing fleet.yml. If that file already exists then all the above actions will be skipped, because the Elastic Agent has already been enrolled. To ensure that enrollment @@ -199,6 +205,10 @@ func buildEnrollArgs(token string, policyID string) ([]string, error) { if policyID != "" { args = append(args, "--fleet-server-policy", policyID) } + ca := envWithDefault("", "FLEET_SERVER_ELASTICSEARCH_CA", "ELASTICSEARCH_CA") + if ca != "" { + args = append(args, "--fleet-server-elasticsearch-ca", ca) + } host := envWithDefault("", "FLEET_SERVER_HOST") if host != "" { args = append(args, "--fleet-server-host", host) @@ -228,6 +238,10 @@ func buildEnrollArgs(token string, policyID string) ([]string, error) { if envBool("FLEET_INSECURE") { args = append(args, "--insecure") } + ca := envWithDefault("", "FLEET_CA", "KIBANA_CA", "ELASTICSEARCH_CA") + if ca != "" { + args = append(args, "--certificate-authorities", ca) + } } args = append(args, "--enrollment-token", token) return args, nil @@ -291,11 +305,20 @@ func kibanaClient() (*kibana.Client, error) { host := envWithDefault(defaultKibanaHost, "KIBANA_FLEET_HOST", "KIBANA_HOST") username := envWithDefault(defaultUsername, "KIBANA_FLEET_USERNAME", "KIBANA_USERNAME", "ELASTICSEARCH_USERNAME") password := envWithDefault(defaultPassword, "KIBANA_FLEET_PASSWORD", "KIBANA_PASSWORD", "ELASTICSEARCH_PASSWORD") + + var tls *tlscommon.Config + ca := envWithDefault("", "KIBANA_FLEET_CA", "KIBANA_CA", "ELASTICSEARCH_CA") + if ca != "" { + tls = &tlscommon.Config{ + CAs: []string{ca}, + } + } return kibana.NewClientWithConfig(&kibana.ClientConfig{ Host: host, Username: username, Password: password, IgnoreVersion: true, + TLS: tls, }) } diff --git a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go index 15c362e9529..30f581331be 100644 --- a/x-pack/elastic-agent/pkg/agent/cmd/enroll.go +++ b/x-pack/elastic-agent/pkg/agent/cmd/enroll.go @@ -52,6 +52,7 @@ func addEnrollFlags(cmd *cobra.Command) { cmd.Flags().StringP("kibana-url", "k", "", "URL of Kibana to enroll Agent into Fleet") cmd.Flags().StringP("enrollment-token", "t", "", "Enrollment token to use to enroll Agent into Fleet") cmd.Flags().StringP("fleet-server", "", "", "Start and run a Fleet Server along side this Elastic Agent") + cmd.Flags().StringP("fleet-server-elasticsearch-ca", "", "", "Path to certificate authority to use with communicate 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)") @@ -75,6 +76,7 @@ func buildEnrollmentFlags(cmd *cobra.Command, url string, token string) []string token, _ = cmd.Flags().GetString("enrollment-token") } fServer, _ := cmd.Flags().GetString("fleet-server") + fElasticSearchCA, _ := cmd.Flags().GetString("fleet-server-elasticsearch-ca") fPolicy, _ := cmd.Flags().GetString("fleet-server-policy") fHost, _ := cmd.Flags().GetString("fleet-server-host") fPort, _ := cmd.Flags().GetUint16("fleet-server-port") @@ -99,6 +101,10 @@ func buildEnrollmentFlags(cmd *cobra.Command, url string, token string) []string args = append(args, "--fleet-server") args = append(args, fServer) } + if fElasticSearchCA != "" { + args = append(args, "--fleet-server-elasticsearch-ca") + args = append(args, fElasticSearchCA) + } if fPolicy != "" { args = append(args, "--fleet-server-policy") args = append(args, fPolicy) @@ -204,6 +210,7 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args } enrollmentToken, _ := cmd.Flags().GetString("enrollment-token") fServer, _ := cmd.Flags().GetString("fleet-server") + fElasticSearchCA, _ := cmd.Flags().GetString("fleet-server-elasticsearch-ca") fPolicy, _ := cmd.Flags().GetString("fleet-server-policy") fHost, _ := cmd.Flags().GetString("fleet-server-host") fPort, _ := cmd.Flags().GetUint16("fleet-server-port") @@ -228,14 +235,15 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args UserProvidedMetadata: make(map[string]interface{}), Staging: staging, FleetServer: application.EnrollCmdFleetServerOption{ - ConnStr: fServer, - PolicyID: fPolicy, - Host: fHost, - Port: fPort, - Cert: fCert, - CertKey: fCertKey, - Insecure: fInsecure, - SpawnAgent: !fromInstall, + ConnStr: fServer, + ElasticsearchCA: fElasticSearchCA, + PolicyID: fPolicy, + Host: fHost, + Port: fPort, + Cert: fCert, + CertKey: fCertKey, + Insecure: fInsecure, + SpawnAgent: !fromInstall, }, }