Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Agent configuration encryption #398

Merged
merged 39 commits into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c10b579
Agent configuration encryption
aleksmaus May 2, 2022
6afad66
Make linter happy
aleksmaus May 2, 2022
17214e0
Address code review feedback
aleksmaus May 2, 2022
750d0a4
Make linux linter happy
aleksmaus May 2, 2022
e94ccc7
Encode created on date/time with the vault key/value
aleksmaus May 3, 2022
5922e7b
Check .seed file owner is root on load
aleksmaus May 3, 2022
73da02a
Update upgrade code paths, rename configuration files fleet.yml and s…
aleksmaus May 4, 2022
a00e7f9
Make linter happy again
aleksmaus May 4, 2022
0ea9f6c
Disable storage encryption for Darwin unit tests that do not run with…
aleksmaus May 4, 2022
4e0d215
Make linter happy for the last commit touched files
aleksmaus May 4, 2022
332cd63
Make check happy
aleksmaus May 4, 2022
bfaa47f
Fix Winderz linter: Error: naked return in func with 7 lines of code…
aleksmaus May 4, 2022
05dcce7
Fix Winderz linter: internal/pkg/agent/vault/vault_windows.go#L57
aleksmaus May 4, 2022
2bff2cb
Remove .seed file root owner check, makes it impossible to unit test …
aleksmaus May 4, 2022
bf54d72
Remove unused import
aleksmaus May 4, 2022
20f6478
Add secret initialiation to non-darwin unit tests
aleksmaus May 5, 2022
fceee17
Add SkipCreateSecret to enroll_cmd, in order to pass run the unit tes…
aleksmaus May 5, 2022
35eca70
Put the root owner check back with a hook that allows to disable it f…
aleksmaus May 5, 2022
0fd625d
Fix disabling root check for tests on darwin
aleksmaus May 5, 2022
23c0b48
Addressed code review comments
aleksmaus May 8, 2022
32a6ff2
Replace ```os.IsNotExist(err)``` with ```errors.Is(err, fs.ErrNotExis…
aleksmaus May 9, 2022
306f6b4
Add missing imports for windows implementation
aleksmaus May 9, 2022
5f43096
Address the latest set of code review comments
aleksmaus May 9, 2022
1f5d81c
Adjust paths for darwin to make linter happy
aleksmaus May 9, 2022
d8fc776
Additional unit test coverage
aleksmaus May 9, 2022
4a53602
Add vault unit tests
aleksmaus May 10, 2022
5745c97
Merge branch 'main' into feature/vault
aleksmaus May 10, 2022
5a9db4e
Improve unit test coverage of vault package
aleksmaus May 10, 2022
46f3a7d
Set Administrator permissions correctly on the vault directory to pro…
aleksmaus May 11, 2022
5d3a388
Address code review feedback
aleksmaus May 11, 2022
a8a8be0
Address the licensing blocker for vault_darwin.c. Updated the default…
aleksmaus May 19, 2022
9b0d1d5
Merge branch 'main' into feature/vault
aleksmaus May 19, 2022
c6cbaaf
Update imports order
aleksmaus May 20, 2022
5f6fb6d
Adjusted the copyright header based on the latest feedback
aleksmaus May 20, 2022
7311aad
Update the CHANGELOG with this PR change
aleksmaus May 20, 2022
3f85788
Fix the issue on install. If the encrypted configuration file doesn't…
aleksmaus May 21, 2022
6909b8f
Merge branch 'main' into feature/vault
aleksmaus May 23, 2022
9442d6e
Update NOTICE.txt generation for the mDNSResponder open source project
aleksmaus May 23, 2022
427a2e1
Addressed the latest round of code review
aleksmaus May 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,37 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


--------------------------------------------------------------------------------
Dependency : github.com/billgraziano/dpapi
Version: v0.4.0
Licence type (autodetected): MIT
--------------------------------------------------------------------------------

Contents of probable licence file $GOMODCACHE/github.com/billgraziano/[email protected]/LICENSE:

MIT License

Copyright (c) 2019 Bill Graziano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


--------------------------------------------------------------------------------
Dependency : github.com/blakesmith/ar
Version: v0.0.0-20150311145944-8bd4349a67f2
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.17
require (
github.com/Microsoft/go-winio v0.5.2
github.com/antlr/antlr4 v0.0.0-20200820155224-be881fa6b91d
github.com/billgraziano/dpapi v0.4.0
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
github.com/cavaliercoder/go-rpm v0.0.0-20190131055624-7a9c54e3d83e
github.com/coreos/go-systemd/v22 v22.3.2
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bi-zone/go-winio v0.4.15 h1:viLHm+U7bzIkfVHuWgc3Wp/sT5zaLoRG7XdOEy1b12w=
github.com/bi-zone/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/billgraziano/dpapi v0.4.0 h1:t39THI1Ld1hkkLVrhkOX6u5TUxwzRddOffq4jcwh2AE=
github.com/billgraziano/dpapi v0.4.0/go.mod h1:gi1Lin0jvovT53j0EXITkY6UPb3hTfI92POaZgj9JBA=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
Expand Down Expand Up @@ -1506,6 +1508,7 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200828161417-c663848e9a16/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/agent/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func createApplication(

func mergeFleetConfig(rawConfig *config.Config) (storage.Store, *configuration.Configuration, error) {
path := paths.AgentConfigFile()
store := storage.NewDiskStore(path)
store := storage.NewEncryptedDiskStore(path)
reader, err := store.Load()
if err != nil {
return store, nil, errors.New(err, "could not initialize config store",
Expand Down
3 changes: 3 additions & 0 deletions internal/pkg/agent/application/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import (
"github.com/stretchr/testify/require"

"github.com/elastic/elastic-agent/internal/pkg/config"
"github.com/elastic/elastic-agent/internal/pkg/testutils"
)

func TestMergeFleetConfig(t *testing.T) {
testutils.InitStorage(t)

cfg := map[string]interface{}{
"fleet": map[string]interface{}{
"enabled": true,
Expand Down
8 changes: 5 additions & 3 deletions internal/pkg/agent/application/info/agent_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func updateLogLevel(level string) error {
}

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

ai.LogLevel = level
return updateAgentInfo(diskStore, ai)
Expand Down Expand Up @@ -189,10 +189,12 @@ func loadAgentInfo(forceUpdate bool, logLevel string, createAgentID bool) (*pers
if err := idLock.TryLock(); err != nil {
return nil, err
}
defer idLock.Unlock()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add //nolint:errcheck // comment 😛

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, same issue as you stumbled upon with your PR earlier, will update

defer func() {
_ = idLock.Unlock()
}()

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

agentinfo, err := getInfoFromStore(diskStore, logLevel)
if err != nil {
Expand Down
49 changes: 44 additions & 5 deletions internal/pkg/agent/application/paths/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,50 @@ package paths
import (
"fmt"
"path/filepath"
"runtime"

"github.com/elastic/elastic-agent/internal/pkg/agent/application/filelock"
)

// defaultAgentCapabilitiesFile is a name of file used to store agent capabilities
const defaultAgentCapabilitiesFile = "capabilities.yml"

// defaultAgentFleetFile is a name of file used to store agent information
const defaultAgentFleetFile = "fleet.yml"
// defaultAgentFleetYmlFile is a name of file used to store agent information
const defaultAgentFleetYmlFile = "fleet.yml"

// defaultAgentFleetFile is a name of file used to store agent information encrypted
const defaultAgentFleetFile = "fleet.enc"

// defaultAgentEnrollFile is a name of file used to enroll agent on first-start
const defaultAgentEnrollFile = "enroll.yml"

// defaultAgentActionStoreFile is the file that will contain the action that can be replayed after restart.
const defaultAgentActionStoreFile = "action_store.yml"

// defaultAgentStateStoreFile is the file that will contain the action that can be replayed after restart.
const defaultAgentStateStoreFile = "state.yml"
// defaultAgentStateStoreYmlFile is the file that will contain the action that can be replayed after restart.
const defaultAgentStateStoreYmlFile = "state.yml"

// defaultAgentStateStoreFile is the file that will contain the action that can be replayed after restart encrypted.
const defaultAgentStateStoreFile = "state.enc"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch on this file


// defaultAgentVaultName is keychain item name for mac
const defaultAgentVaultName = "co.elastic.agent"

// defaultAgentVaultPath is the directory for windows and linux where the vault store is located or the
const defaultAgentVaultPath = "vault"

// AgentConfigYmlFile is a name of file used to store agent information
func AgentConfigYmlFile() string {
return filepath.Join(Config(), defaultAgentFleetYmlFile)
}

// AgentConfigYmlFileLock is a locker for agent config file updates.
func AgentConfigYmlFileLock() *filelock.AppLocker {
return filelock.NewAppLocker(
Config(),
fmt.Sprintf("%s.lock", defaultAgentFleetYmlFile),
)
}

// AgentConfigFile is a name of file used to store agent information
func AgentConfigFile() string {
Expand Down Expand Up @@ -54,7 +80,20 @@ func AgentActionStoreFile() string {
return filepath.Join(Home(), defaultAgentActionStoreFile)
}

// AgentStateStoreFile is the file that contains the persisted state of the agent including the action that can be replayed after restart.
// AgentStateStoreYmlFile is the file that contains the persisted state of the agent including the action that can be replayed after restart.
func AgentStateStoreYmlFile() string {
return filepath.Join(Home(), defaultAgentStateStoreYmlFile)
}

// AgentStateStoreFile is the file that contains the persisted state of the agent including the action that can be replayed after restart encrypted.
func AgentStateStoreFile() string {
return filepath.Join(Home(), defaultAgentStateStoreFile)
}

// AgentVaultPath is the directory that contains all the files for the value for windows and linux
func AgentVaultPath() string {
if runtime.GOOS == "darwin" {
return defaultAgentVaultName
}
return filepath.Join(Home(), defaultAgentVaultPath)
}
AndersonQ marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -11,93 +11,42 @@ import (
"github.com/elastic/elastic-agent/internal/pkg/agent/application/info"
"github.com/elastic/elastic-agent/internal/pkg/agent/program"
"github.com/elastic/elastic-agent/internal/pkg/agent/transpiler"
"github.com/elastic/elastic-agent/internal/pkg/testutils"
)

func TestMonitoringInjection(t *testing.T) {
agentInfo, err := info.NewAgentInfo(true)
if err != nil {
t.Fatal(err)
}
ast, err := transpiler.NewAST(inputConfigMap)
if err != nil {
t.Fatal(err)
}

programsToRun, err := program.Programs(agentInfo, ast)
if err != nil {
t.Fatal(err)
tests := []struct {
name string
inputConfig map[string]interface{}
uname string
}{
{
name: "testMonitoringInjection",
inputConfig: inputConfigMap,
uname: "monitoring-uname",
},
{
name: "testMonitoringInjectionDefaults",
inputConfig: inputConfigMapDefaults,
uname: "xxx",
},
}

if len(programsToRun) != 1 {
t.Fatal(fmt.Errorf("programsToRun expected to have %d entries", 1))
}

GROUPLOOP:
for group, ptr := range programsToRun {
programsCount := len(ptr)
newPtr, err := InjectMonitoring(agentInfo, group, ast, ptr)
if err != nil {
t.Error(err)
continue GROUPLOOP
}

if programsCount+1 != len(newPtr) {
t.Errorf("incorrect programs to run count, expected: %d, got %d", programsCount+1, len(newPtr))
continue GROUPLOOP
}

for _, p := range newPtr {
if p.Spec.Name != MonitoringName {
continue
}

cm, err := p.Config.Map()
if err != nil {
t.Error(err)
continue GROUPLOOP
}

outputCfg, found := cm[outputKey]
if !found {
t.Errorf("output not found for '%s'", group)
continue GROUPLOOP
}

outputMap, ok := outputCfg.(map[string]interface{})
if !ok {
t.Errorf("output is not a map for '%s'", group)
continue GROUPLOOP
}

esCfg, found := outputMap["elasticsearch"]
if !found {
t.Errorf("elasticsearch output not found for '%s'", group)
continue GROUPLOOP
}

esMap, ok := esCfg.(map[string]interface{})
if !ok {
t.Errorf("output.elasticsearch is not a map for '%s'", group)
continue GROUPLOOP
}

if uname, found := esMap["username"]; !found {
t.Errorf("output.elasticsearch.username output not found for '%s'", group)
continue GROUPLOOP
} else if uname != "monitoring-uname" {
t.Errorf("output.elasticsearch.username has incorrect value expected '%s', got '%s for %s", "monitoring-uname", uname, group)
continue GROUPLOOP
}
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
testMonitoringInjection(t, tc.inputConfig, tc.uname)
})
}
}

func TestMonitoringInjectionDefaults(t *testing.T) {
func testMonitoringInjection(t *testing.T, inputConfig map[string]interface{}, testUname string) {
testutils.InitStorage(t)

agentInfo, err := info.NewAgentInfo(true)
if err != nil {
t.Fatal(err)
}
ast, err := transpiler.NewAST(inputConfigMapDefaults)
ast, err := transpiler.NewAST(inputConfig)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -163,7 +112,7 @@ GROUPLOOP:
if uname, found := esMap["username"]; !found {
t.Errorf("output.elasticsearch.username output not found for '%s'", group)
continue GROUPLOOP
} else if uname != "xxx" {
} else if uname != testUname {
t.Errorf("output.elasticsearch.username has incorrect value expected '%s', got '%s for %s", "monitoring-uname", uname, group)
continue GROUPLOOP
}
Expand All @@ -172,6 +121,8 @@ GROUPLOOP:
}

func TestMonitoringToLogstashInjection(t *testing.T) {
testutils.InitStorage(t)

agentInfo, err := info.NewAgentInfo(true)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -251,6 +202,8 @@ GROUPLOOP:
}

func TestMonitoringInjectionDisabled(t *testing.T) {
testutils.InitStorage(t)

agentInfo, err := info.NewAgentInfo(true)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -340,6 +293,8 @@ GROUPLOOP:
}

func TestChangeInMonitoringWithChangeInInput(t *testing.T) {
testutils.InitStorage(t)

agentInfo, err := info.NewAgentInfo(true)
if err != nil {
t.Fatal(err)
Expand Down
Loading