Skip to content

Commit df0160a

Browse files
committed
Add integration tests for switching between unprivileged and privileged mode.
1 parent ee26696 commit df0160a

File tree

4 files changed

+319
-13
lines changed

4 files changed

+319
-13
lines changed

testing/integration/install_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,17 @@ func checkInstallSuccess(t *testing.T, f *atesting.Fixture, topPath string, unpr
249249
// Specific checks depending on the platform.
250250
checkPlatformUnprivileged(t, f, topPath)
251251
}
252+
253+
var output atesting.AgentStatusOutput
254+
require.Eventuallyf(t, func() bool {
255+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
256+
defer cancel()
257+
output, err = f.ExecStatus(ctx)
258+
return err == nil
259+
}, 3*time.Minute, 10*time.Second, "never got the status")
260+
261+
require.False(t, output.IsZero(), "must have an agent ID")
262+
require.Equal(t, unprivileged, output.Info.Unprivileged, "unprivileged state doesn't match")
252263
}
253264

254265
func randStr(length int) string {

testing/integration/install_windows_test.go

-13
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
package integration
88

99
import (
10-
"context"
1110
"testing"
12-
"time"
1311

1412
"github.com/stretchr/testify/require"
1513

@@ -23,15 +21,4 @@ func checkPlatformUnprivileged(t *testing.T, f *atesting.Fixture, topPath string
2321
require.NoErrorf(t, err, "failed to find %s user", install.ElasticUsername)
2422
_, err = install.FindGID(install.ElasticGroupName)
2523
require.NoError(t, err, "failed to find %s group", install.ElasticGroupName)
26-
27-
var output atesting.AgentStatusOutput
28-
require.Eventuallyf(t, func() bool {
29-
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
30-
defer cancel()
31-
output, err = f.ExecStatus(ctx)
32-
return err == nil
33-
}, 3*time.Minute, 10*time.Second, "never got the status")
34-
35-
require.False(t, output.IsZero(), "must have an agent ID")
36-
require.True(t, output.Info.Unprivileged, "must be unprivileged")
3724
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
//go:build integration
6+
7+
package integration
8+
9+
import (
10+
"context"
11+
"os"
12+
"path/filepath"
13+
"runtime"
14+
"strings"
15+
"testing"
16+
"time"
17+
18+
atesting "github.com/elastic/elastic-agent/pkg/testing"
19+
"github.com/elastic/elastic-agent/pkg/testing/define"
20+
"github.com/elastic/elastic-agent/pkg/testing/tools/testcontext"
21+
22+
"github.com/stretchr/testify/require"
23+
)
24+
25+
func TestSwitchPrivilegedWithoutBasePath(t *testing.T) {
26+
define.Require(t, define.Requirements{
27+
Group: Default,
28+
// We require sudo for this test to run
29+
// `elastic-agent install`.
30+
Sudo: true,
31+
32+
// It's not safe to run this test locally as it
33+
// installs Elastic Agent.
34+
Local: false,
35+
})
36+
37+
// Get path to Elastic Agent executable
38+
fixture, err := define.NewFixture(t, define.Version())
39+
require.NoError(t, err)
40+
41+
ctx, cancel := testcontext.WithDeadline(t, context.Background(), time.Now().Add(10*time.Minute))
42+
defer cancel()
43+
44+
// Prepare the Elastic Agent so the binary is extracted and ready to use.
45+
err = fixture.Prepare(ctx)
46+
require.NoError(t, err)
47+
48+
// Check that default base path is clean
49+
var defaultBasePath string
50+
switch runtime.GOOS {
51+
case "darwin":
52+
defaultBasePath = `/Library`
53+
case "linux":
54+
defaultBasePath = `/opt`
55+
case "windows":
56+
defaultBasePath = `C:\Program Files`
57+
}
58+
59+
topPath := filepath.Join(defaultBasePath, "Elastic", "Agent")
60+
err = os.RemoveAll(topPath)
61+
require.NoError(t, err, "failed to remove %q. The test requires this path not to exist.")
62+
63+
// Run `elastic-agent install`. We use `--force` to prevent interactive
64+
// execution.
65+
opts := &atesting.InstallOpts{Force: true, Privileged: false}
66+
out, err := fixture.Install(ctx, opts)
67+
if err != nil {
68+
t.Logf("install output: %s", out)
69+
require.NoError(t, err)
70+
}
71+
72+
// Check that Agent was installed in default base path in unprivileged mode
73+
checkInstallSuccess(t, fixture, topPath, true)
74+
75+
// Switch to privileged mode
76+
out, err = fixture.Exec(ctx, []string{"privileged", "-f"})
77+
if err != nil {
78+
t.Logf("privileged output: %s", out)
79+
require.NoError(t, err)
80+
}
81+
82+
// Check that Agent is running in default base path in privileged mode
83+
checkInstallSuccess(t, fixture, topPath, false)
84+
}
85+
86+
func TestSwitchPrivilegedWithBasePath(t *testing.T) {
87+
define.Require(t, define.Requirements{
88+
Group: Default,
89+
// We require sudo for this test to run
90+
// `elastic-agent install`.
91+
Sudo: true,
92+
93+
// It's not safe to run this test locally as it
94+
// installs Elastic Agent.
95+
Local: false,
96+
})
97+
98+
// Get path to Elastic Agent executable
99+
fixture, err := define.NewFixture(t, define.Version())
100+
require.NoError(t, err)
101+
102+
ctx, cancel := testcontext.WithDeadline(t, context.Background(), time.Now().Add(10*time.Minute))
103+
defer cancel()
104+
105+
// Prepare the Elastic Agent so the binary is extracted and ready to use.
106+
err = fixture.Prepare(ctx)
107+
require.NoError(t, err)
108+
109+
// When running in unprivileged using a base path the
110+
// base needs to be accessible by the `elastic-agent-user` user that will be
111+
// executing the process, but is not created yet. Using a base that exists
112+
// and is known to be accessible by standard users, ensures this tests
113+
// works correctly and will not hit a permission issue when spawning the
114+
// elastic-agent service.
115+
var basePath string
116+
switch runtime.GOOS {
117+
case define.Linux:
118+
basePath = `/usr`
119+
case define.Windows:
120+
basePath = `C:\`
121+
default:
122+
// Set up random temporary directory to serve as base path for Elastic Agent
123+
// installation.
124+
tmpDir := t.TempDir()
125+
basePath = filepath.Join(tmpDir, strings.ToLower(randStr(8)))
126+
}
127+
128+
// Run `elastic-agent install`. We use `--force` to prevent interactive
129+
// execution.
130+
opts := &atesting.InstallOpts{
131+
BasePath: basePath,
132+
Force: true,
133+
Privileged: false,
134+
}
135+
out, err := fixture.Install(ctx, opts)
136+
if err != nil {
137+
t.Logf("install output: %s", out)
138+
require.NoError(t, err)
139+
}
140+
141+
// Check that Agent was installed in the custom base path in unprivileged mode
142+
topPath := filepath.Join(basePath, "Elastic", "Agent")
143+
checkInstallSuccess(t, fixture, topPath, true)
144+
145+
// Switch to privileged mode
146+
out, err = fixture.Exec(ctx, []string{"privileged", "-f"})
147+
if err != nil {
148+
t.Logf("privileged output: %s", out)
149+
require.NoError(t, err)
150+
}
151+
152+
// Check that Agent is running in the custom base path in privileged mode
153+
checkInstallSuccess(t, fixture, topPath, false)
154+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
//go:build integration
6+
7+
package integration
8+
9+
import (
10+
"context"
11+
"os"
12+
"path/filepath"
13+
"runtime"
14+
"strings"
15+
"testing"
16+
"time"
17+
18+
atesting "github.com/elastic/elastic-agent/pkg/testing"
19+
"github.com/elastic/elastic-agent/pkg/testing/define"
20+
"github.com/elastic/elastic-agent/pkg/testing/tools/testcontext"
21+
22+
"github.com/stretchr/testify/require"
23+
)
24+
25+
func TestSwitchUnprivilegedWithoutBasePath(t *testing.T) {
26+
define.Require(t, define.Requirements{
27+
Group: Default,
28+
// We require sudo for this test to run
29+
// `elastic-agent install`.
30+
Sudo: true,
31+
32+
// It's not safe to run this test locally as it
33+
// installs Elastic Agent.
34+
Local: false,
35+
})
36+
37+
// Get path to Elastic Agent executable
38+
fixture, err := define.NewFixture(t, define.Version())
39+
require.NoError(t, err)
40+
41+
ctx, cancel := testcontext.WithDeadline(t, context.Background(), time.Now().Add(10*time.Minute))
42+
defer cancel()
43+
44+
// Prepare the Elastic Agent so the binary is extracted and ready to use.
45+
err = fixture.Prepare(ctx)
46+
require.NoError(t, err)
47+
48+
// Check that default base path is clean
49+
var defaultBasePath string
50+
switch runtime.GOOS {
51+
case "darwin":
52+
defaultBasePath = `/Library`
53+
case "linux":
54+
defaultBasePath = `/opt`
55+
case "windows":
56+
defaultBasePath = `C:\Program Files`
57+
}
58+
59+
topPath := filepath.Join(defaultBasePath, "Elastic", "Agent")
60+
err = os.RemoveAll(topPath)
61+
require.NoError(t, err, "failed to remove %q. The test requires this path not to exist.")
62+
63+
// Run `elastic-agent install`. We use `--force` to prevent interactive
64+
// execution.
65+
opts := &atesting.InstallOpts{Force: true, Privileged: true}
66+
out, err := fixture.Install(ctx, opts)
67+
if err != nil {
68+
t.Logf("install output: %s", out)
69+
require.NoError(t, err)
70+
}
71+
72+
// Check that Agent was installed in default base path in privileged mode
73+
checkInstallSuccess(t, fixture, topPath, false)
74+
75+
// Switch to unprivileged mode
76+
out, err = fixture.Exec(ctx, []string{"unprivileged", "-f"})
77+
if err != nil {
78+
t.Logf("unprivileged output: %s", out)
79+
require.NoError(t, err)
80+
}
81+
82+
// Check that Agent is running in default base path in unprivileged mode
83+
checkInstallSuccess(t, fixture, topPath, true)
84+
}
85+
86+
func TestSwitchUnprivilegedWithBasePath(t *testing.T) {
87+
define.Require(t, define.Requirements{
88+
Group: Default,
89+
// We require sudo for this test to run
90+
// `elastic-agent install`.
91+
Sudo: true,
92+
93+
// It's not safe to run this test locally as it
94+
// installs Elastic Agent.
95+
Local: false,
96+
})
97+
98+
// Get path to Elastic Agent executable
99+
fixture, err := define.NewFixture(t, define.Version())
100+
require.NoError(t, err)
101+
102+
ctx, cancel := testcontext.WithDeadline(t, context.Background(), time.Now().Add(10*time.Minute))
103+
defer cancel()
104+
105+
// Prepare the Elastic Agent so the binary is extracted and ready to use.
106+
err = fixture.Prepare(ctx)
107+
require.NoError(t, err)
108+
109+
// When running in unprivileged using a base path the
110+
// base needs to be accessible by the `elastic-agent-user` user that will be
111+
// executing the process, but is not created yet. Using a base that exists
112+
// and is known to be accessible by standard users, ensures this tests
113+
// works correctly and will not hit a permission issue when spawning the
114+
// elastic-agent service.
115+
var basePath string
116+
switch runtime.GOOS {
117+
case define.Linux:
118+
basePath = `/usr`
119+
case define.Windows:
120+
basePath = `C:\`
121+
default:
122+
// Set up random temporary directory to serve as base path for Elastic Agent
123+
// installation.
124+
tmpDir := t.TempDir()
125+
basePath = filepath.Join(tmpDir, strings.ToLower(randStr(8)))
126+
}
127+
128+
// Run `elastic-agent install`. We use `--force` to prevent interactive
129+
// execution.
130+
opts := &atesting.InstallOpts{
131+
BasePath: basePath,
132+
Force: true,
133+
Privileged: true,
134+
}
135+
out, err := fixture.Install(ctx, opts)
136+
if err != nil {
137+
t.Logf("install output: %s", out)
138+
require.NoError(t, err)
139+
}
140+
141+
// Check that Agent was installed in the custom base path in privileged mode
142+
topPath := filepath.Join(basePath, "Elastic", "Agent")
143+
checkInstallSuccess(t, fixture, topPath, false)
144+
145+
// Switch to unprivileged mode
146+
out, err = fixture.Exec(ctx, []string{"unprivileged", "-f"})
147+
if err != nil {
148+
t.Logf("unprivileged output: %s", out)
149+
require.NoError(t, err)
150+
}
151+
152+
// Check that Agent is running in the custom base path in unprivileged mode
153+
checkInstallSuccess(t, fixture, topPath, true)
154+
}

0 commit comments

Comments
 (0)