Skip to content

Commit

Permalink
[Elastic Agent] Fix invalid log level sent to endpoint (elastic#25854)
Browse files Browse the repository at this point in the history
[Elastic Agent] Fix invalid log level sent to endpoint (elastic#25854)
  • Loading branch information
michalpristas committed May 28, 2021
1 parent 2bbc22e commit a969084
Show file tree
Hide file tree
Showing 14 changed files with 286 additions and 224 deletions.
1 change: 1 addition & 0 deletions x-pack/elastic-agent/CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
- Add error log entry when listener creation fails {issue}23483[23482]
- Handle case where policy doesn't contain Fleet connection information {pull}25707[25707]
- Fix fleet-server.yml spec to not overwrite existing keys {pull}25741[25741]
- Agent sends wrong log level to Endpoint {issue}25583[25583]

==== New features

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ func withGateway(agentInfo agentInfo, settings *fleetGatewaySettings, fn withGat

ctx, cancel := context.WithCancel(context.Background())

stateStore, err := store.NewStateStore(log, storage.NewDiskStore(paths.AgentStateStoreFile()))
diskStore := storage.NewDiskStore(paths.AgentStateStoreFile())
stateStore, err := store.NewStateStore(log, diskStore)
require.NoError(t, err)

gateway, err := newFleetGatewayWithScheduler(
Expand Down Expand Up @@ -256,7 +257,9 @@ func TestFleetGateway(t *testing.T) {

ctx, cancel := context.WithCancel(context.Background())
log, _ := logger.New("tst", false)
stateStore, err := store.NewStateStore(log, storage.NewDiskStore(paths.AgentStateStoreFile()))

diskStore := storage.NewDiskStore(paths.AgentStateStoreFile())
stateStore, err := store.NewStateStore(log, diskStore)
require.NoError(t, err)

gateway, err := newFleetGatewayWithScheduler(
Expand Down Expand Up @@ -346,7 +349,8 @@ func TestFleetGateway(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
log, _ := logger.New("tst", false)

stateStore, err := store.NewStateStore(log, storage.NewDiskStore(paths.AgentStateStoreFile()))
diskStore := storage.NewDiskStore(paths.AgentStateStoreFile())
stateStore, err := store.NewStateStore(log, diskStore)
require.NoError(t, err)

gateway, err := newFleetGatewayWithScheduler(
Expand Down
10 changes: 5 additions & 5 deletions x-pack/elastic-agent/pkg/agent/application/info/agent_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ func updateLogLevel(level string) error {
}

agentConfigFile := paths.AgentConfigFile()
s := storage.NewDiskStore(agentConfigFile)
diskStore := storage.NewDiskStore(agentConfigFile)

ai.LogLevel = level
return updateAgentInfo(s, ai)
return updateAgentInfo(diskStore, ai)
}

func generateAgentID() (string, error) {
Expand Down Expand Up @@ -191,9 +191,9 @@ func loadAgentInfo(forceUpdate bool, logLevel string, createAgentID bool) (*pers
defer idLock.Unlock()

agentConfigFile := paths.AgentConfigFile()
s := storage.NewDiskStore(agentConfigFile)
diskStore := storage.NewDiskStore(agentConfigFile)

agentinfo, err := getInfoFromStore(s, logLevel)
agentinfo, err := getInfoFromStore(diskStore, logLevel)
if err != nil {
return nil, err
}
Expand All @@ -202,7 +202,7 @@ func loadAgentInfo(forceUpdate bool, logLevel string, createAgentID bool) (*pers
return agentinfo, nil
}

if err := updateID(agentinfo, s); err != nil {
if err := updateID(agentinfo, diskStore); err != nil {
return nil, err
}

Expand Down
13 changes: 11 additions & 2 deletions x-pack/elastic-agent/pkg/agent/application/info/agent_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package info

import (
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/core/logger"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/release"
)

Expand Down Expand Up @@ -41,8 +42,16 @@ func NewAgentInfo(createAgentID bool) (*AgentInfo, error) {
return NewAgentInfoWithLog(defaultLogLevel, createAgentID)
}

// LogLevel updates log level of agent.
func (i *AgentInfo) LogLevel(level string) error {
// LogLevel retrieves a log level.
func (i *AgentInfo) LogLevel() string {
if i.logLevel == "" {
return logger.DefaultLogLevel.String()
}
return i.logLevel
}

// SetLogLevel updates log level of agent.
func (i *AgentInfo) SetLogLevel(level string) error {
if err := updateLogLevel(level); err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func (i *AgentInfo) ECSMetadata() (*ECSMeta, error) {
// only upgradeable if running from Agent installer and running under the
// control of the system supervisor (or built specifically with upgrading enabled)
Upgradeable: release.Upgradeable() || (RunningInstalled() && RunningUnderSupervisor()),
LogLevel: i.logLevel,
LogLevel: i.LogLevel(),
},
},
Host: &HostECSMeta{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (h *Settings) Handle(ctx context.Context, a fleetapi.Action, acker store.Fl
return fmt.Errorf("invalid log level, expected debug|info|warning|error and received '%s'", action.LogLevel)
}

if err := h.agentInfo.LogLevel(action.LogLevel); err != nil {
if err := h.agentInfo.SetLogLevel(action.LogLevel); err != nil {
return errors.New("failed to update log level", err)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ import (
// InjectFleet injects fleet metadata into a configuration.
func InjectFleet(cfg *config.Config, hostInfo types.HostInfo, agentInfo *info.AgentInfo) func(*logger.Logger, *transpiler.AST) error {
return func(logger *logger.Logger, rootAst *transpiler.AST) error {
ecsMeta, err := agentInfo.ECSMetadata()
if err != nil {
return err
}
logLevel := ecsMeta.Elastic.Agent.LogLevel

config, err := cfg.ToMapStr()
if err != nil {
return err
Expand All @@ -46,7 +40,7 @@ func InjectFleet(cfg *config.Config, hostInfo types.HostInfo, agentInfo *info.Ag

// ensure that the agent.logging.level is present
if _, found := transpiler.Lookup(ast, "agent.logging.level"); !found {
transpiler.Insert(ast, transpiler.NewKey("level", transpiler.NewStrVal(logLevel)), "agent.logging")
transpiler.Insert(ast, transpiler.NewKey("level", transpiler.NewStrVal(agentInfo.LogLevel())), "agent.logging")
}

// fleet.host to Agent can be the host to connect to Fleet Server, but to Applications it should
Expand Down
4 changes: 2 additions & 2 deletions x-pack/elastic-agent/pkg/agent/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,8 @@ func getOverwrites(rawConfig *config.Config) error {
return nil
}
path := paths.AgentConfigFile()

store := storage.NewDiskStore(path)

reader, err := store.Load()
if err != nil && errors.Is(err, os.ErrNotExist) {
// no fleet file ignore
Expand Down Expand Up @@ -262,7 +262,7 @@ func defaultLogLevel(cfg *configuration.Configuration) string {
return ""
}

defaultLogLevel := logger.DefaultLoggingConfig().Level.String()
defaultLogLevel := logger.DefaultLogLevel.String()
if configuredLevel := cfg.Settings.LoggingConfig.Level.String(); configuredLevel != "" && configuredLevel != defaultLogLevel {
// predefined log level
return configuredLevel
Expand Down
100 changes: 100 additions & 0 deletions x-pack/elastic-agent/pkg/agent/storage/disk_store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package storage

import (
"fmt"
"io"
"os"

"github.com/hectane/go-acl"

"github.com/elastic/beats/v7/libbeat/common/file"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors"
)

// NewDiskStore creates an unencrypted disk store.
func NewDiskStore(target string) *DiskStore {
return &DiskStore{target: target}
}

// Exists check if the store file exists on the disk
func (d *DiskStore) Exists() (bool, error) {
_, err := os.Stat(d.target)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
return true, nil
}

// Delete deletes the store file on the disk
func (d *DiskStore) Delete() error {
return os.Remove(d.target)
}

// Save accepts a persistedConfig and saved it to a target file, to do so we will
// make a temporary files if the write is successful we are replacing the target file with the
// original content.
func (d *DiskStore) Save(in io.Reader) error {
tmpFile := d.target + ".tmp"

fd, err := os.OpenFile(tmpFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, perms)
if err != nil {
return errors.New(err,
fmt.Sprintf("could not save to %s", tmpFile),
errors.TypeFilesystem,
errors.M(errors.MetaKeyPath, tmpFile))
}

// Always clean up the temporary file and ignore errors.
defer os.Remove(tmpFile)

if _, err := io.Copy(fd, in); err != nil {
_ = fd.Close()

return errors.New(err, "could not save content on disk",
errors.TypeFilesystem,
errors.M(errors.MetaKeyPath, tmpFile))
}

_ = fd.Sync()

if err := fd.Close(); err != nil {
return errors.New(err, "could not close temporary file",
errors.TypeFilesystem,
errors.M(errors.MetaKeyPath, tmpFile))
}

if err := file.SafeFileRotate(d.target, tmpFile); err != nil {
return errors.New(err,
fmt.Sprintf("could not replace target file %s", d.target),
errors.TypeFilesystem,
errors.M(errors.MetaKeyPath, d.target))
}

if err := acl.Chmod(d.target, perms); err != nil {
return errors.New(err,
fmt.Sprintf("could not set permissions target file %s", d.target),
errors.TypeFilesystem,
errors.M(errors.MetaKeyPath, d.target))
}

return nil
}

// Load return a io.ReadCloser for the target file.
func (d *DiskStore) Load() (io.ReadCloser, error) {
fd, err := os.OpenFile(d.target, os.O_RDONLY|os.O_CREATE, perms)
if err != nil {
return nil, errors.New(err,
fmt.Sprintf("could not open %s", d.target),
errors.TypeFilesystem,
errors.M(errors.MetaKeyPath, d.target))
}
return fd, nil
}
24 changes: 24 additions & 0 deletions x-pack/elastic-agent/pkg/agent/storage/handler_store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package storage

import "io"

type handlerFunc func(io.Reader) error

// HandlerStore take a function handler and wrap it into the store interface.
type HandlerStore struct {
fn handlerFunc
}

// NewHandlerStore takes a function and wrap it into an handlerStore.
func NewHandlerStore(fn handlerFunc) *HandlerStore {
return &HandlerStore{fn: fn}
}

// Save calls the handler.
func (h *HandlerStore) Save(in io.Reader) error {
return h.fn(in)
}
15 changes: 15 additions & 0 deletions x-pack/elastic-agent/pkg/agent/storage/null_store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package storage

import "io"

// NullStore this is only use to split the work into multiples PRs.
type NullStore struct{}

// Save takes the fleetConfig and persist it, will return an errors on failure.
func (m *NullStore) Save(_ io.Reader) error {
return nil
}
Loading

0 comments on commit a969084

Please sign in to comment.