From 52fff6c18b7c05558040aa108e08b51b6c5764a6 Mon Sep 17 00:00:00 2001 From: Michel Laterman <82832767+michel-laterman@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:29:42 -0300 Subject: [PATCH] Audit unenroll should not set unenrolled_at attribute (#4221) Do not set the unenrolled_at attribute when the audit/unenroll API is called. Remove the unenrolled_at attribute if it's set during checkin. (cherry picked from commit 8450b717986aac0cdb5b2f7b8a8229d897ca6c24) --- ...-does-not-set-unenrolled_at-attribute.yaml | 34 +++++++++++++++++++ internal/pkg/api/handleAudit.go | 1 - internal/pkg/api/handleCheckin.go | 4 ++- .../deleteAuditFieldsOnCheckin.painless | 2 +- internal/pkg/server/fleet_integration_test.go | 7 ++-- 5 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 changelog/fragments/1734380253-Audit-unenroll-does-not-set-unenrolled_at-attribute.yaml diff --git a/changelog/fragments/1734380253-Audit-unenroll-does-not-set-unenrolled_at-attribute.yaml b/changelog/fragments/1734380253-Audit-unenroll-does-not-set-unenrolled_at-attribute.yaml new file mode 100644 index 000000000..ccc37eedb --- /dev/null +++ b/changelog/fragments/1734380253-Audit-unenroll-does-not-set-unenrolled_at-attribute.yaml @@ -0,0 +1,34 @@ +# Kind can be one of: +# - breaking-change: a change to previously-documented behavior +# - deprecation: functionality that is being removed in a later release +# - bug-fix: fixes a problem in a previous version +# - enhancement: extends functionality but does not break or fix existing behavior +# - feature: new functionality +# - known-issue: problems that we are aware of in a given version +# - security: impacts on the security of a product or a user’s deployment. +# - upgrade: important information for someone upgrading from a prior version +# - other: does not fit into any of the other categories +kind: bug-fix + +# Change summary; a 80ish characters long description of the change. +summary: Audit/unenroll should not set unenrolled_at attribute + +# Long description; in case the summary is not enough to describe the change +# this field accommodate a description without length limits. +# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment. +description: | + The audit/unenroll endpoint should not set the unenrolled_at attribute as + it's used by the UI. + +# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc. +component: fleet-server + +# PR URL; optional; the PR number that added the changeset. +# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added. +# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number. +# Please provide it if you are adding a fragment for a different PR. +pr: https://github.com/elastic/fleet-server/pull/4221 + +# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of). +# If not present is automatically filled by the tooling with the issue linked to the PR number. +issue: https://github.com/elastic/elastic-agent/issues/6213 diff --git a/internal/pkg/api/handleAudit.go b/internal/pkg/api/handleAudit.go index 35781e02c..aa303a587 100644 --- a/internal/pkg/api/handleAudit.go +++ b/internal/pkg/api/handleAudit.go @@ -103,7 +103,6 @@ func (audit *AuditT) markUnenroll(ctx context.Context, zlog zerolog.Logger, req now := time.Now().UTC().Format(time.RFC3339) doc := bulk.UpdateFields{ - dl.FieldUnenrolledAt: now, dl.FieldUpdatedAt: now, dl.FieldAuditUnenrolledTime: req.Timestamp, dl.FieldAuditUnenrolledReason: req.Reason, diff --git a/internal/pkg/api/handleCheckin.go b/internal/pkg/api/handleCheckin.go index 8df658793..38cd78836 100644 --- a/internal/pkg/api/handleCheckin.go +++ b/internal/pkg/api/handleCheckin.go @@ -323,7 +323,9 @@ func (ct *CheckinT) ProcessRequest(zlog zerolog.Logger, w http.ResponseWriter, r defer longPoll.Stop() // Initial update on checkin, and any user fields that might have changed - err = ct.bc.CheckIn(agent.Id, string(req.Status), req.Message, rawMeta, rawComponents, seqno, ver, unhealthyReason, agent.AuditUnenrolledReason != "") + // Run a script to remove audit_unenrolled_* and unenrolled_at attributes if one is set on checkin. + // 8.16.x releases would incorrectly set unenrolled_at + err = ct.bc.CheckIn(agent.Id, string(req.Status), req.Message, rawMeta, rawComponents, seqno, ver, unhealthyReason, agent.AuditUnenrolledReason != "" || agent.UnenrolledAt != "") if err != nil { zlog.Error().Err(err).Str(logger.AgentID, agent.Id).Msg("checkin failed") } diff --git a/internal/pkg/checkin/deleteAuditFieldsOnCheckin.painless b/internal/pkg/checkin/deleteAuditFieldsOnCheckin.painless index 2840bab2e..6588cd1ce 100644 --- a/internal/pkg/checkin/deleteAuditFieldsOnCheckin.painless +++ b/internal/pkg/checkin/deleteAuditFieldsOnCheckin.painless @@ -17,4 +17,4 @@ if (params.SeqNoSet) { } ctx._source.remove('audit_unenrolled_reason'); ctx._source.remove('audit_unenrolled_time'); -ctx._source.remove('dl.unenrolled_at'); +ctx._source.remove('unenrolled_at'); // audit/unenroll no longer sets this but it did in the 8.16.x releases, so we need to clear it. diff --git a/internal/pkg/server/fleet_integration_test.go b/internal/pkg/server/fleet_integration_test.go index d4af0c089..4e474e596 100644 --- a/internal/pkg/server/fleet_integration_test.go +++ b/internal/pkg/server/fleet_integration_test.go @@ -1526,7 +1526,7 @@ func Test_SmokeTest_AuditUnenroll(t *testing.T) { err = json.Unmarshal(p, &obj) require.NoError(t, err) - require.Eventually(t, func() bool { + require.Eventuallyf(t, func() bool { req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:9200/.fleet-agents/_doc/"+id, nil) require.NoError(t, err) req.SetBasicAuth("elastic", "changeme") @@ -1546,8 +1546,9 @@ func Test_SmokeTest_AuditUnenroll(t *testing.T) { obj, ok := o.(map[string]interface{}) require.Truef(t, ok, "expected _source to be an object, was: %T", o) _, ok = obj["audit_unenrolled_reason"] - return !ok - }, time.Second*20, time.Second, "agent document should not have audit_unenrolled_reason attribute") + _, ok2 := obj["unenrolled_at"] + return !ok && !ok2 + }, time.Second*20, time.Second, "agent document should not have the audit_unenrolled_reason or unenrolled_at attributes. agent doc: %v", obj) cancel() srv.waitExit() //nolint:errcheck // test case }