Skip to content

Commit 53ebe67

Browse files
authored
Pass namespaces to Fleet Server managed documents (#3535)
1 parent da02802 commit 53ebe67

File tree

12 files changed

+499
-193
lines changed

12 files changed

+499
-193
lines changed
Lines changed: 27 additions & 0 deletions
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

Lines changed: 14 additions & 11 deletions
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

Lines changed: 4 additions & 4 deletions
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

Lines changed: 4 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 26 additions & 23 deletions
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

Lines changed: 14 additions & 10 deletions
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

Lines changed: 6 additions & 6 deletions
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

Lines changed: 18 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)