Skip to content

Commit 53ebe67

Browse files
authoredMay 16, 2024··
Pass namespaces to Fleet Server managed documents (#3535)
1 parent da02802 commit 53ebe67

12 files changed

+499
-193
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Kind can be one of:
2+
# - breaking-change: a change to previously-documented behavior
3+
# - deprecation: functionality that is being removed in a later release
4+
# - bug-fix: fixes a problem in a previous version
5+
# - enhancement: extends functionality but does not break or fix existing behavior
6+
# - feature: new functionality
7+
# - known-issue: problems that we are aware of in a given version
8+
# - security: impacts on the security of a product or a user’s deployment.
9+
# - upgrade: important information for someone upgrading from a prior version
10+
# - other: does not fit into any of the other categories
11+
kind: feature
12+
13+
# Change summary; a 80ish characters long description of the change.
14+
summary: support-namespaces
15+
16+
# Long description; in case the summary is not enough to describe the change
17+
# this field accommodate a description without length limits.
18+
# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment.
19+
description: Add suport for namespaces, Fleet server will now add the Namespaces property to created .fleet-* documennts.
20+
21+
# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc.
22+
component: "fleet-server"
23+
# PR URL; optional; the PR number that added the changeset.
24+
# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added.
25+
# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number.
26+
# Please provide it if you are adding a fragment for a different PR.
27+
pr: https://github.com/elastic/fleet-server/pull/3535

‎internal/pkg/api/handleAck.go

+14-11
Original file line numberDiff line numberDiff line change
@@ -163,23 +163,25 @@ func (ack *AckT) validateRequest(zlog zerolog.Logger, w http.ResponseWriter, r *
163163
return &req, nil
164164
}
165165

166-
func eventToActionResult(agentID, aType string, ev AckRequest_Events_Item) (acr model.ActionResult) {
166+
func eventToActionResult(agentID, aType string, namespaces []string, ev AckRequest_Events_Item) (acr model.ActionResult) {
167167
switch aType {
168168
case string(REQUESTDIAGNOSTICS):
169169
event, _ := ev.AsDiagnosticsEvent()
170170
p, _ := json.Marshal(event.Data)
171171
return model.ActionResult{
172-
ActionID: event.ActionId,
173-
AgentID: agentID,
174-
Data: p,
175-
Error: fromPtr(event.Error),
176-
Timestamp: event.Timestamp.Format(time.RFC3339Nano),
172+
ActionID: event.ActionId,
173+
AgentID: agentID,
174+
Namespaces: namespaces,
175+
Data: p,
176+
Error: fromPtr(event.Error),
177+
Timestamp: event.Timestamp.Format(time.RFC3339Nano),
177178
}
178179
case string(INPUTACTION):
179180
event, _ := ev.AsInputEvent()
180181
return model.ActionResult{
181182
ActionID: event.ActionId,
182183
AgentID: agentID,
184+
Namespaces: namespaces,
183185
ActionInputType: event.ActionInputType,
184186
StartedAt: event.StartedAt.Format(time.RFC3339Nano),
185187
CompletedAt: event.CompletedAt.Format(time.RFC3339Nano),
@@ -191,10 +193,11 @@ func eventToActionResult(agentID, aType string, ev AckRequest_Events_Item) (acr
191193
default: // UPGRADE action acks are also handled by handelUpgrade (deprecated func)
192194
event, _ := ev.AsGenericEvent()
193195
return model.ActionResult{
194-
ActionID: event.ActionId,
195-
AgentID: agentID,
196-
Error: fromPtr(event.Error),
197-
Timestamp: event.Timestamp.Format(time.RFC3339Nano),
196+
ActionID: event.ActionId,
197+
Namespaces: namespaces,
198+
AgentID: agentID,
199+
Error: fromPtr(event.Error),
200+
Timestamp: event.Timestamp.Format(time.RFC3339Nano),
198201
}
199202
}
200203
}
@@ -358,7 +361,7 @@ func (ack *AckT) handleActionResult(ctx context.Context, zlog zerolog.Logger, ag
358361
defer span.End()
359362

360363
// Convert ack event to action result document
361-
acr := eventToActionResult(agent.Id, action.Type, ev)
364+
acr := eventToActionResult(agent.Id, action.Type, action.Namespaces, ev)
362365

363366
// Save action result document
364367
if err := dl.CreateActionResult(ctx, ack.bulk, acr); err != nil {

‎internal/pkg/api/handleAck_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func TestMakeUpdatePolicyBody(t *testing.T) {
6161
func TestEventToActionResult(t *testing.T) {
6262
agentID := "6e9b6655-8cfe-4eb6-9b2f-c10aefae7517"
6363
t.Run("generic", func(t *testing.T) {
64-
r := eventToActionResult(agentID, "UPGRADE", AckRequest_Events_Item{json.RawMessage(`{
64+
r := eventToActionResult(agentID, "UPGRADE", []string{}, AckRequest_Events_Item{json.RawMessage(`{
6565
"action_id": "test-action-id",
6666
"message": "action message",
6767
"timestamp": "2022-02-23T18:26:08.506128Z"
@@ -72,7 +72,7 @@ func TestEventToActionResult(t *testing.T) {
7272
assert.Empty(t, r.Error)
7373
})
7474
t.Run("with error", func(t *testing.T) {
75-
r := eventToActionResult(agentID, "UPGRADE", AckRequest_Events_Item{json.RawMessage(`{
75+
r := eventToActionResult(agentID, "UPGRADE", []string{}, AckRequest_Events_Item{json.RawMessage(`{
7676
"action_id": "test-action-id",
7777
"message": "action message",
7878
"timestamp": "2022-02-23T18:26:08.506128Z",
@@ -84,7 +84,7 @@ func TestEventToActionResult(t *testing.T) {
8484
assert.Equal(t, "error message", r.Error)
8585
})
8686
t.Run("request diagnostics", func(t *testing.T) {
87-
r := eventToActionResult(agentID, "REQUEST_DIAGNOSTICS", AckRequest_Events_Item{json.RawMessage(`{
87+
r := eventToActionResult(agentID, "REQUEST_DIAGNOSTICS", []string{}, AckRequest_Events_Item{json.RawMessage(`{
8888
"action_id": "test-action-id",
8989
"message": "action message",
9090
"timestamp": "2022-02-23T18:26:08.506128Z",
@@ -98,7 +98,7 @@ func TestEventToActionResult(t *testing.T) {
9898
assert.Equal(t, "error message", r.Error)
9999
})
100100
t.Run("input action", func(t *testing.T) {
101-
r := eventToActionResult(agentID, "INPUT_ACTION", AckRequest_Events_Item{json.RawMessage(`{
101+
r := eventToActionResult(agentID, "INPUT_ACTION", []string{}, AckRequest_Events_Item{json.RawMessage(`{
102102
"action_id": "test-action-id",
103103
"message": "action message",
104104
"timestamp": "2022-02-23T18:26:08.506128Z",

‎internal/pkg/api/handleEnroll.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func (et *EnrollerT) processRequest(zlog zerolog.Logger, w http.ResponseWriter,
132132

133133
cntEnroll.bodyIn.Add(readCounter.Count())
134134

135-
return et._enroll(r.Context(), rb, zlog, req, enrollAPI.PolicyID, ver)
135+
return et._enroll(r.Context(), rb, zlog, req, enrollAPI.PolicyID, enrollAPI.Namespaces, ver)
136136
}
137137

138138
// retrieveStaticTokenEnrollmentToken fetches the enrollment key record from the config static tokens.
@@ -190,7 +190,8 @@ func (et *EnrollerT) _enroll(
190190
rb *rollback.Rollback,
191191
zlog zerolog.Logger,
192192
req *EnrollRequest,
193-
policyID,
193+
policyID string,
194+
namespaces []string,
194195
ver string,
195196
) (*EnrollResponse, error) {
196197
var agent model.Agent
@@ -272,6 +273,7 @@ func (et *EnrollerT) _enroll(
272273
agentData := model.Agent{
273274
Active: true,
274275
PolicyID: policyID,
276+
Namespaces: namespaces,
275277
Type: string(req.Type),
276278
EnrolledAt: now.UTC().Format(time.RFC3339),
277279
LocalMetadata: localMeta,

‎internal/pkg/api/handleEnroll_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func TestEnroll(t *testing.T) {
9090
}, nil)
9191
bulker.On("Create", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(
9292
"", nil)
93-
resp, _ := et._enroll(ctx, rb, zlog, req, "1234", "8.9.0")
93+
resp, _ := et._enroll(ctx, rb, zlog, req, "1234", []string{}, "8.9.0")
9494

9595
if resp.Action != "created" {
9696
t.Fatal("enroll failed")

‎internal/pkg/api/handleUpload.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,13 @@ func (ut *UploadT) handleUploadBegin(_ zerolog.Logger, w http.ResponseWriter, r
9595
return err
9696
}
9797

98-
_, err = ut.authAgent(r, &agentID, ut.bulker, ut.cache)
98+
agent, err := ut.authAgent(r, &agentID, ut.bulker, ut.cache)
9999
if err != nil {
100100
return err
101101
}
102102

103103
// validate payload, enrich with additional fields, and write metadata doc to ES
104-
info, err := ut.uploader.Begin(r.Context(), payload)
104+
info, err := ut.uploader.Begin(r.Context(), agent.Namespaces, payload)
105105
if err != nil {
106106
return err
107107
}

‎internal/pkg/file/file.go

+26-23
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,13 @@ type Hash struct {
4545
}
4646

4747
type MetaDoc struct {
48-
ActionID string `json:"action_id"`
49-
AgentID string `json:"agent_id"`
50-
Source string `json:"src"`
51-
File FileData `json:"file"`
52-
UploadID string `json:"upload_id"`
53-
Start time.Time `json:"upload_start"`
48+
ActionID string `json:"action_id"`
49+
AgentID string `json:"agent_id"`
50+
Source string `json:"src"`
51+
File FileData `json:"file"`
52+
UploadID string `json:"upload_id"`
53+
Start time.Time `json:"upload_start"`
54+
Namespaces []string `json:"namespaces"`
5455
}
5556

5657
// custom unmarshaller to make unix-epoch values work
@@ -71,26 +72,28 @@ func (m *MetaDoc) UnmarshalJSON(b []byte) error {
7172
}
7273

7374
type ChunkInfo struct {
74-
Pos int // Ordered chunk position in file
75-
Last bool // Is this the final chunk in the file
76-
SHA2 string
77-
Size int
78-
BID string // base id, matches metadata doc's _id
79-
Index string
80-
ID string // chunk _id
75+
Pos int // Ordered chunk position in file
76+
Last bool // Is this the final chunk in the file
77+
SHA2 string
78+
Size int
79+
BID string // base id, matches metadata doc's _id
80+
Index string
81+
ID string // chunk _id
82+
Namespaces []string
8183
}
8284

8385
type Info struct {
84-
ID string // upload operation identifier. Used to identify the upload process
85-
DocID string // document ID of the uploaded file and chunks
86-
Source string // which integration is performing the upload
87-
AgentID string
88-
ActionID string
89-
ChunkSize int64
90-
Total int64
91-
Count int
92-
Start time.Time
93-
Status Status
86+
ID string // upload operation identifier. Used to identify the upload process
87+
DocID string // document ID of the uploaded file and chunks
88+
Source string // which integration is performing the upload
89+
AgentID string
90+
ActionID string
91+
Namespaces []string
92+
ChunkSize int64
93+
Total int64
94+
Count int
95+
Start time.Time
96+
Status Status
9497
}
9598

9699
// convenience functions for computing current "Status" based on the fields

‎internal/pkg/file/uploader/upload.go

+14-10
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func New(chunkClient *elasticsearch.Client, bulker bulk.Bulk, cache cache.Cache,
5555
}
5656

5757
// Start an upload operation
58-
func (u *Uploader) Begin(ctx context.Context, data JSDict) (file.Info, error) {
58+
func (u *Uploader) Begin(ctx context.Context, namespaces []string, data JSDict) (file.Info, error) {
5959
vSpan, _ := apm.StartSpan(ctx, "validateFileInfo", "validate")
6060
if data == nil {
6161
vSpan.End()
@@ -92,15 +92,16 @@ func (u *Uploader) Begin(ctx context.Context, data JSDict) (file.Info, error) {
9292
docID := fmt.Sprintf("%s.%s", actionID, agentID)
9393

9494
info := file.Info{
95-
ID: id,
96-
DocID: docID,
97-
AgentID: agentID,
98-
ActionID: actionID,
99-
ChunkSize: file.MaxChunkSize,
100-
Source: source,
101-
Total: size,
102-
Status: file.StatusAwaiting,
103-
Start: time.Now(),
95+
ID: id,
96+
DocID: docID,
97+
AgentID: agentID,
98+
ActionID: actionID,
99+
Namespaces: namespaces,
100+
ChunkSize: file.MaxChunkSize,
101+
Source: source,
102+
Total: size,
103+
Status: file.StatusAwaiting,
104+
Start: time.Now(),
104105
}
105106
chunkCount := info.Total / info.ChunkSize
106107
if info.Total%info.ChunkSize > 0 {
@@ -127,6 +128,9 @@ func (u *Uploader) Begin(ctx context.Context, data JSDict) (file.Info, error) {
127128
if err := data.Put(info.Start.UnixMilli(), "@timestamp"); err != nil {
128129
return file.Info{}, err
129130
}
131+
if err := data.Put(info.Namespaces, "namespaces"); err != nil {
132+
return file.Info{}, err
133+
}
130134

131135
/*
132136
Write to storage

‎internal/pkg/file/uploader/upload_test.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func TestUploadBeginReturnsCorrectInfo(t *testing.T) {
8484
c, err := cache.New(config.Cache{NumCounters: 100, MaxCost: 100000})
8585
require.NoError(t, err)
8686
u := New(nil, fakeBulk, c, int64(size), time.Hour)
87-
info, err := u.Begin(context.Background(), data)
87+
info, err := u.Begin(context.Background(), []string{}, data)
8888
assert.NoError(t, err)
8989

9090
assert.Equal(t, int64(size), info.Total)
@@ -128,7 +128,7 @@ func TestUploadBeginWritesDocumentFromInputs(t *testing.T) {
128128
c, err := cache.New(config.Cache{NumCounters: 100, MaxCost: 100000})
129129
require.NoError(t, err)
130130
u := New(nil, fakeBulk, c, int64(size), time.Hour)
131-
_, err = u.Begin(context.Background(), data)
131+
_, err = u.Begin(context.Background(), []string{}, data)
132132
assert.NoError(t, err)
133133

134134
payload, ok := fakeBulk.Calls[0].Arguments[3].([]byte)
@@ -172,7 +172,7 @@ func TestUploadBeginCalculatesCorrectChunkCount(t *testing.T) {
172172
data := makeUploadRequestDict(map[string]interface{}{
173173
"file.size": tc.FileSize,
174174
})
175-
info, err := u.Begin(context.Background(), data)
175+
info, err := u.Begin(context.Background(), []string{}, data)
176176
assert.NoError(t, err)
177177
assert.Equal(t, tc.ExpectedCount, info.Count)
178178
})
@@ -211,7 +211,7 @@ func TestUploadBeginMaxFileSize(t *testing.T) {
211211
data := makeUploadRequestDict(map[string]interface{}{
212212
"file.size": tc.FileSize,
213213
})
214-
_, err := u.Begin(context.Background(), data)
214+
_, err := u.Begin(context.Background(), []string{}, data)
215215
if tc.ShouldError {
216216
assert.ErrorIs(t, err, ErrFileSizeTooLarge)
217217
} else {
@@ -265,7 +265,7 @@ func TestUploadRejectsMissingRequiredFields(t *testing.T) {
265265
}
266266
}
267267

268-
_, err = u.Begin(context.Background(), data)
268+
_, err = u.Begin(context.Background(), []string{}, data)
269269
assert.Errorf(t, err, "%s is a required field and should error if not provided", field)
270270
})
271271

@@ -343,7 +343,7 @@ func TestChunkMarksFinal(t *testing.T) {
343343
"file.size": tc.FileSize,
344344
})
345345

346-
info, err := u.Begin(context.Background(), data)
346+
info, err := u.Begin(context.Background(), []string{}, data)
347347
assert.NoError(t, err)
348348

349349
// for anything larger than 1-chunk, check for off-by-ones

‎internal/pkg/model/schema.go

+18-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
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 server
8+
9+
import (
10+
"bytes"
11+
"context"
12+
"encoding/json"
13+
"fmt"
14+
"io"
15+
"net/http"
16+
"strings"
17+
"testing"
18+
"text/template"
19+
"time"
20+
21+
"github.com/elastic/fleet-server/v7/internal/pkg/apikey"
22+
"github.com/elastic/fleet-server/v7/internal/pkg/dl"
23+
"github.com/elastic/fleet-server/v7/internal/pkg/model"
24+
"github.com/gofrs/uuid"
25+
"github.com/hashicorp/go-cleanhttp"
26+
"github.com/stretchr/testify/require"
27+
)
28+
29+
func AgentCheckin(t *testing.T, ctx context.Context, srv *tserver, agentID, key string) string {
30+
cli := cleanhttp.DefaultClient()
31+
var obj map[string]interface{}
32+
33+
t.Logf("Fake a checkin for agent %s", agentID)
34+
req, err := http.NewRequestWithContext(ctx, "POST", srv.baseURL()+"/api/fleet/agents/"+agentID+"/checkin", strings.NewReader(checkinBody))
35+
require.NoError(t, err)
36+
req.Header.Set("Authorization", "ApiKey "+key)
37+
req.Header.Set("User-Agent", "elastic agent "+serverVersion)
38+
req.Header.Set("Content-Type", "application/json")
39+
res, err := cli.Do(req)
40+
require.NoError(t, err)
41+
42+
require.Equal(t, http.StatusOK, res.StatusCode)
43+
t.Log("Checkin successful, verify body")
44+
p, _ := io.ReadAll(res.Body)
45+
res.Body.Close()
46+
err = json.Unmarshal(p, &obj)
47+
require.NoError(t, err)
48+
49+
actionsRaw, ok := obj["actions"]
50+
require.True(t, ok, "expected actions is missing")
51+
actions, ok := actionsRaw.([]interface{})
52+
require.True(t, ok, "expected actions to be an array")
53+
require.Equal(t, len(actions), 1, "expected 1 action")
54+
action, ok := actions[0].(map[string]interface{})
55+
require.True(t, ok, "expected action to be an object")
56+
57+
aIDRaw, ok := action["id"]
58+
require.True(t, ok, "expected action id attribute missing")
59+
actionID, ok := aIDRaw.(string)
60+
require.True(t, ok, "expected action id to be string")
61+
62+
return actionID
63+
}
64+
65+
func AgentAck(t *testing.T, ctx context.Context, srv *tserver, actionID, agentID, key string) {
66+
t.Logf("Fake an ack for action %s for agent %s", actionID, agentID)
67+
body := fmt.Sprintf(`{
68+
"events": [{
69+
"action_id": "%s",
70+
"agent_id": "%s",
71+
"message": "test-message",
72+
"type": "ACTION_RESULT",
73+
"subtype": "ACKNOWLEDGED"
74+
}]
75+
}`, actionID, agentID)
76+
req, err := http.NewRequestWithContext(ctx, "POST", srv.baseURL()+"/api/fleet/agents/"+agentID+"/acks", strings.NewReader(body))
77+
require.NoError(t, err)
78+
req.Header.Set("Authorization", "ApiKey "+key)
79+
req.Header.Set("Content-Type", "application/json")
80+
cli := cleanhttp.DefaultClient()
81+
res, err := cli.Do(req)
82+
require.NoError(t, err)
83+
defer res.Body.Close()
84+
85+
require.Equal(t, http.StatusOK, res.StatusCode)
86+
t.Log("Ack successful, verify body")
87+
}
88+
89+
type GetAgentResponse struct {
90+
Agent model.Agent `json:"_source"`
91+
}
92+
93+
func AssertAgentDocContainNamespace(t *testing.T, ctx context.Context, srv *tserver, agentID string, namespace string) {
94+
res, err := srv.bulker.Client().Get(".fleet-agents", agentID)
95+
require.NoError(t, err)
96+
97+
defer res.Body.Close()
98+
var getAgentRes GetAgentResponse
99+
err = json.NewDecoder(res.Body).Decode(&getAgentRes)
100+
require.NoError(t, err)
101+
102+
require.EqualValues(t, getAgentRes.Agent.Namespaces, []string{namespace})
103+
}
104+
105+
func CreateActionDocument(t *testing.T, ctx context.Context, srv *tserver, action model.Action) {
106+
body, err := json.Marshal(action)
107+
require.NoError(t, err)
108+
_, err = srv.bulker.Client().Index(".fleet-actions", bytes.NewReader(body))
109+
require.NoError(t, err)
110+
}
111+
112+
type GetActionResults struct {
113+
Hits struct {
114+
Hits []struct {
115+
Result model.ActionResult `json:"_source"`
116+
} `json:"hits"`
117+
} `json:"hits"`
118+
}
119+
120+
func CheckActionResultsNamespace(t *testing.T, ctx context.Context, srv *tserver, actionID string, namespace string) {
121+
queryTmpl := `{
122+
"query": {
123+
"bool" : {
124+
"must" : {
125+
"terms": {
126+
"action_id": [ "{{.}}" ]
127+
}
128+
}
129+
}
130+
}
131+
}`
132+
queryBuff := bytes.Buffer{}
133+
tmpl, err := template.New("").Parse(queryTmpl)
134+
require.NoError(t, err)
135+
err = tmpl.Execute(&queryBuff, actionID)
136+
require.NoError(t, err)
137+
138+
client := srv.bulker.Client()
139+
140+
res, err := client.Search(
141+
client.Search.WithIndex(".fleet-actions-results"),
142+
client.Search.WithBody(strings.NewReader(queryBuff.String())),
143+
)
144+
defer res.Body.Close()
145+
require.NoError(t, err)
146+
147+
var getActionResultsRes GetActionResults
148+
err = json.NewDecoder(res.Body).Decode(&getActionResultsRes)
149+
require.NoError(t, err)
150+
151+
require.Len(t, getActionResultsRes.Hits.Hits, 1)
152+
require.EqualValues(t, getActionResultsRes.Hits.Hits[0].Result.Namespaces, []string{namespace})
153+
}
154+
155+
func Test_Agent_Namespace_test1(t *testing.T) {
156+
testNamespace := "test1"
157+
ctx, cancel := context.WithCancel(context.Background())
158+
defer cancel()
159+
160+
// Start test server
161+
srv, err := startTestServer(t, ctx, policyData)
162+
require.NoError(t, err)
163+
164+
t.Log("Create policy with namespace test1")
165+
var policyRemoteID = uuid.Must(uuid.NewV4()).String()
166+
var policyDataNamespaceTest = model.PolicyData{
167+
Outputs: map[string]map[string]interface{}{
168+
"default": {
169+
"type": "elasticsearch",
170+
},
171+
},
172+
OutputPermissions: json.RawMessage(`{"default": {} }`),
173+
Inputs: []map[string]interface{}{},
174+
Agent: json.RawMessage(`{"monitoring": {"use_output":"default"}}`),
175+
}
176+
177+
_, err = dl.CreatePolicy(ctx, srv.bulker, model.Policy{
178+
PolicyID: policyRemoteID,
179+
Namespaces: []string{testNamespace},
180+
RevisionIdx: 1,
181+
DefaultFleetServer: false,
182+
Data: &policyDataNamespaceTest,
183+
})
184+
if err != nil {
185+
t.Fatal(err)
186+
}
187+
188+
t.Log("Create API key and enrollment key for new policy")
189+
newKey, err := apikey.Create(ctx, srv.bulker.Client(), "default", "", "true", []byte(`{
190+
"fleet-apikey-enroll": {
191+
"cluster": [],
192+
"index": [],
193+
"applications": [{
194+
"application": "fleet",
195+
"privileges": ["no-privileges"],
196+
"resources": ["*"]
197+
}]
198+
}
199+
}`), map[string]interface{}{
200+
"managed_by": "fleet",
201+
"managed": true,
202+
"type": "enroll",
203+
"policy_id": policyRemoteID,
204+
})
205+
if err != nil {
206+
t.Fatal(err)
207+
}
208+
209+
_, err = dl.CreateEnrollmentAPIKey(ctx, srv.bulker, model.EnrollmentAPIKey{
210+
Name: "TestNamespace1",
211+
Namespaces: []string{testNamespace},
212+
APIKey: newKey.Key,
213+
APIKeyID: newKey.ID,
214+
PolicyID: policyRemoteID,
215+
Active: true,
216+
})
217+
if err != nil {
218+
t.Fatal(err)
219+
}
220+
221+
t.Log("Enroll agent")
222+
srvCopy := srv
223+
srvCopy.enrollKey = newKey.Token()
224+
agentID, key := EnrollAgent(enrollBody, t, ctx, srvCopy)
225+
226+
AssertAgentDocContainNamespace(t, ctx, srv, agentID, testNamespace)
227+
// cleanup
228+
defer func() {
229+
err = srv.bulker.Delete(ctx, dl.FleetAgents, agentID)
230+
if err != nil {
231+
t.Log("could not clean up agent")
232+
}
233+
}()
234+
235+
actionID := AgentCheckin(t, ctx, srvCopy, agentID, key)
236+
AgentAck(t, ctx, srvCopy, actionID, agentID, key)
237+
238+
t.Log("Create SETTINGS Action")
239+
newActionID, _ := uuid.NewV4()
240+
var actionData = model.Action{
241+
Agents: []string{agentID},
242+
Expiration: time.Now().Add(time.Hour * 2000).Format(time.RFC3339),
243+
ActionID: newActionID.String(),
244+
Namespaces: []string{"test1"},
245+
Type: "SETTINGS",
246+
Data: []byte("{\"log_level\": \"debug\"}"),
247+
}
248+
249+
CreateActionDocument(t, ctx, srv, actionData)
250+
251+
t.Log("Checkin so that agent gets the SETTINGS action")
252+
actionID = AgentCheckin(t, ctx, srvCopy, agentID, key)
253+
254+
t.Log("Ack so that fleet create the action results")
255+
AgentAck(t, ctx, srvCopy, actionID, agentID, key)
256+
257+
t.Log("Check action results has the correct namespace")
258+
CheckActionResultsNamespace(t, ctx, srv, actionID, "test1")
259+
}

‎model/schema.json

+124-131
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.