Skip to content

Commit 37d2fa6

Browse files
committed
[Elastic Agent] Enroll with Fleet Server (#23865)
* Add test and changelog. * Add ability to enroll through a local Fleet Server started by the running Elastic Agent daemon. * Fix tests. * Fix changelog. * Fixes from code review. * Cleanup from merge into master. (cherry picked from commit ae0f29e)
1 parent 7085358 commit 37d2fa6

46 files changed

Lines changed: 1335 additions & 503 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

x-pack/elastic-agent/CHANGELOG.next.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,4 @@
6969
- Push log level downstream {pull}22815[22815]
7070
- Add metrics collection for Agent {pull}22793[22793]
7171
- Add support for Fleet Server {pull}23736[23736]
72+
- Add support for enrollment with local bootstrap of Fleet Server {pull}23865[23865]

x-pack/elastic-agent/pkg/agent/application/application.go

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ package application
66

77
import (
88
"context"
9+
"fmt"
10+
11+
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors"
12+
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/storage"
13+
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/status"
914

1015
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/info"
1116
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/upgrade"
@@ -31,7 +36,7 @@ type upgraderControl interface {
3136
}
3237

3338
// New creates a new Agent and bootstrap the required subsystem.
34-
func New(log *logger.Logger, pathConfigFile string, reexec reexecManager, uc upgraderControl, agentInfo *info.AgentInfo) (Application, error) {
39+
func New(log *logger.Logger, pathConfigFile string, reexec reexecManager, statusCtrl status.Controller, uc upgraderControl, agentInfo *info.AgentInfo) (Application, error) {
3540
// Load configuration from disk to understand in which mode of operation
3641
// we must start the elastic-agent, the mode of operation cannot be changed without restarting the
3742
// elastic-agent.
@@ -44,14 +49,15 @@ func New(log *logger.Logger, pathConfigFile string, reexec reexecManager, uc upg
4449
return nil, err
4550
}
4651

47-
return createApplication(log, pathConfigFile, rawConfig, reexec, uc, agentInfo)
52+
return createApplication(log, pathConfigFile, rawConfig, reexec, statusCtrl, uc, agentInfo)
4853
}
4954

5055
func createApplication(
5156
log *logger.Logger,
5257
pathConfigFile string,
5358
rawConfig *config.Config,
5459
reexec reexecManager,
60+
statusCtrl status.Controller,
5561
uc upgraderControl,
5662
agentInfo *info.AgentInfo,
5763
) (Application, error) {
@@ -66,14 +72,72 @@ func createApplication(
6672

6773
if IsStandalone(cfg.Fleet) {
6874
log.Info("Agent is managed locally")
69-
return newLocal(ctx, log, pathConfigFile, rawConfig, reexec, uc, agentInfo)
75+
return newLocal(ctx, log, pathConfigFile, rawConfig, reexec, statusCtrl, uc, agentInfo)
76+
}
77+
78+
// not in standalone; both modes require reading the fleet.yml configuration file
79+
var store storage.Store
80+
store, cfg, err = mergeFleetConfig(rawConfig)
81+
82+
if IsFleetServerBootstrap(cfg.Fleet) {
83+
log.Info("Agent is in Fleet Server bootstrap mode")
84+
return newFleetServerBootstrap(ctx, log, pathConfigFile, rawConfig, statusCtrl, agentInfo)
7085
}
7186

7287
log.Info("Agent is managed by Fleet")
73-
return newManaged(ctx, log, rawConfig, reexec, agentInfo)
88+
return newManaged(ctx, log, store, cfg, rawConfig, reexec, statusCtrl, agentInfo)
7489
}
7590

7691
// IsStandalone decides based on missing of fleet.enabled: true or fleet.{access_token,kibana} will place Elastic Agent into standalone mode.
7792
func IsStandalone(cfg *configuration.FleetAgentConfig) bool {
7893
return cfg == nil || !cfg.Enabled
7994
}
95+
96+
// IsFleetServerBootstrap decides if Elastic Agent is started in bootstrap mode.
97+
func IsFleetServerBootstrap(cfg *configuration.FleetAgentConfig) bool {
98+
return cfg != nil && cfg.Server != nil && cfg.Server.Bootstrap
99+
}
100+
101+
func mergeFleetConfig(rawConfig *config.Config) (storage.Store, *configuration.Configuration, error) {
102+
path := info.AgentConfigFile()
103+
store := storage.NewDiskStore(path)
104+
reader, err := store.Load()
105+
if err != nil {
106+
return store, nil, errors.New(err, "could not initialize config store",
107+
errors.TypeFilesystem,
108+
errors.M(errors.MetaKeyPath, path))
109+
}
110+
config, err := config.NewConfigFrom(reader)
111+
if err != nil {
112+
return store, nil, errors.New(err,
113+
fmt.Sprintf("fail to read configuration %s for the elastic-agent", path),
114+
errors.TypeFilesystem,
115+
errors.M(errors.MetaKeyPath, path))
116+
}
117+
118+
// merge local configuration and configuration persisted from fleet.
119+
err = rawConfig.Merge(config)
120+
if err != nil {
121+
return store, nil, errors.New(err,
122+
fmt.Sprintf("fail to merge configuration with %s for the elastic-agent", path),
123+
errors.TypeConfig,
124+
errors.M(errors.MetaKeyPath, path))
125+
}
126+
127+
cfg, err := configuration.NewFromConfig(rawConfig)
128+
if err != nil {
129+
return store, nil, errors.New(err,
130+
fmt.Sprintf("fail to unpack configuration from %s", path),
131+
errors.TypeFilesystem,
132+
errors.M(errors.MetaKeyPath, path))
133+
}
134+
135+
if err := cfg.Fleet.Valid(); err != nil {
136+
return store, nil, errors.New(err,
137+
"fleet configuration is invalid",
138+
errors.TypeFilesystem,
139+
errors.M(errors.MetaKeyPath, path))
140+
}
141+
142+
return store, cfg, nil
143+
}

x-pack/elastic-agent/pkg/agent/application/config.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,26 @@ func createFleetConfigFromEnroll(accessAPIKey string, kbn *kibana.Config) (*conf
2626
}
2727
return cfg, nil
2828
}
29+
30+
func createFleetServerBootstrapConfig(connStr string, policyID string) (*configuration.FleetAgentConfig, error) {
31+
es, err := configuration.ElasticsearchFromConnStr(connStr)
32+
if err != nil {
33+
return nil, err
34+
}
35+
cfg := configuration.DefaultFleetAgentConfig()
36+
cfg.Enabled = true
37+
cfg.Server = &configuration.FleetServerConfig{
38+
Bootstrap: true,
39+
Output: configuration.FleetServerOutputConfig{
40+
Elasticsearch: es,
41+
},
42+
}
43+
if policyID != "" {
44+
cfg.Server.Policy = &configuration.FleetServerPolicyConfig{ID: policyID}
45+
}
46+
47+
if err := cfg.Valid(); err != nil {
48+
return nil, errors.New(err, "invalid enrollment options", errors.TypeConfig)
49+
}
50+
return cfg, nil
51+
}

0 commit comments

Comments
 (0)