[Fleet] Write policy_base_id field at agent enrollment - #7422
Conversation
|
This pull request does not have a backport label. Could you fix it @juliaElastic? 🙏
|
This comment has been minimized.
This comment has been minimized.
|
This pull request is now in conflicts. Could you fix it @juliaElastic? 🙏 |
This comment has been minimized.
This comment has been minimized.
TL;DRThe Remediation
Investigation detailsRoot Cause
Evidence
VerificationThe supplied Buildkite log was inspected locally. The PR checkout was not available in the workspace, so no PR-specific rerun was performed. What is this? | From workflow: PR Buildkite Detective Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not. |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces a denormalized policy_base_id field on agent documents to enable efficient term/terms queries for “base policy ID” lookups when policy_id may include a #major.minor version suffix.
Changes:
- Adds
policy_base_idto the Agent schema/model and corresponding DL constant. - Populates
PolicyBaseIDduring agent creation in the enrollment handler via apolicyBaseID()helper. - Adds a unit test for the
policyBaseID()helper and a changelog fragment.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| model/schema.json | Adds policy_base_id to the agent schema definition. |
| internal/pkg/model/schema.go | Regenerates model output to include Agent.PolicyBaseID. |
| internal/pkg/dl/constants.go | Adds FieldPolicyBaseID constant for ES field naming. |
| internal/pkg/api/handleEnroll.go | Writes PolicyBaseID on agent creation and adds policyBaseID() helper. |
| internal/pkg/api/handleEnroll_test.go | Adds unit coverage for policyBaseID() helper behavior. |
| changelog/fragments/1784718180-write-policy-base-id-on-enrollment.yaml | Records the feature in the changelog. |
Files not reviewed (1)
- internal/pkg/model/schema.go: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
internal/pkg/api/handleEnroll_test.go — TestEnrollWithAgentIDExistingActive (lines 382–410)
TestEnrollWithAgentIDExistingActive exercises the re-enrollment UpdateFields path — the exact path where the original omission was caught by Copilot review. The mock accepts any args on Update, so a missing FieldPolicyBaseID would pass silently. Suggested change: use a versioned policy ID and assert the field is written.
// before (lines 382–410)
source := fmt.Sprintf(`{"active":true,"agent":{"id":"1234","version":"8.9.0"},"type":"PERMANENT","policy_id":"1234","replace_token":"%s"}`, replaceHash)
// ... bulker mock setup ...
resp, _ := et._enroll(ctx, rb, zlog, req, "1234", []string{}, "8.9.0")
// only resp.Action and resp.Item.Id are asserted
}// after
policyID := "my-policy#9.2"
source := fmt.Sprintf(`{"active":true,"agent":{"id":"1234","version":"8.9.0"},"type":"PERMANENT","policy_id":"%s","replace_token":"%s"}`, policyID, replaceHash)
// ... bulker mock setup unchanged ...
resp, _ := et._enroll(ctx, rb, zlog, req, policyID, []string{}, "8.9.0")
if resp.Action != "created" {
t.Fatal("enroll failed")
}
if resp.Item.Id != agentID {
t.Fatalf("agent ID should have been %s (not %s)", agentID, resp.Item.Id)
}
var updateBody []byte
for _, c := range bulker.Calls {
if c.Method == "Update" {
updateBody = c.Arguments.Get(3).([]byte)
break
}
}
var updateDoc struct {
Doc map[string]any `json:"doc"`
}
assert.NoError(t, json.Unmarshal(updateBody, &updateDoc))
assert.Equal(t, "my-policy", updateDoc.Doc[dl.FieldPolicyBaseID])
}|
While this PR handles the enrollment path, my concern was around the policy reassignment path. But it looks like the companion Kibana PR takes care of setting both |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@ycombinator thanks for the review, updated the test If you ready to approve, can you help with the merge too? I don't have access. |
…olicy queries (B2) (#279716) ## Summary Adds a denormalized `policy_base_id` field to `fleet-agents` and `.fleet-policies` Elasticsearch indices so readers can use cheap `term`/`terms` queries instead of `bool.should[term, prefix]` for version-specific policy lookups. ### Background Fleet supports version-specific agent policies where `policy_id` gets a `#major.minor` suffix (e.g. `my-policy#9.2`). Every "find agents on this policy" query currently requires: ```json { "bool": { "should": [{ "term": { "policy_id": "my-policy" } }, { "prefix": { "policy_id": "my-policy#" } }] } } ``` `prefix` queries are expensive and incompatible with `search.allow_expensive_queries: false`. `policy_base_id` stores the canonical base ID (suffix stripped), enabling `{ "term": { "policy_base_id": "my-policy" } }` instead. **Mixed-version rollout fallback** (`buildPolicyBaseIdWithFallbackEsFilter` / `buildPolicyBaseIdsWithFallbackEsFilter`): Agents enrolled via an older fleet-server during a rollout will lack `policy_base_id`. The four ES DSL query sites use a transitional fallback: ``` policy_base_id:<id> OR (NOT _exists_:policy_base_id AND policy_id:<id>) ``` The fallback uses exact `term`/`terms` on `policy_id` only — no `prefix` — to remain compatible with `search.allow_expensive_queries: false`. Versioned `policy_id` values (e.g. `policy-id#9.3`) without `policy_base_id` can only arise in the narrow overlap of a mixed-version upgrade; the startup backfill covers all pre-existing documents. Both helpers carry a TODO to remove once all fleet-server versions in use populate the field. ### Deployment order This PR must be deployed together with (or after): 1. **elastic/elasticsearch#154521** — mapping for `policy_base_id` field 2. **elastic/fleet-server#7422** — writes `policy_base_id` at agent enrollment Closes [elastic/ingest-dev#8624](elastic/ingest-dev#8624) (Workstream B2). ### Screenshots <img width="1586" height="539" alt="image" src="https://github.com/user-attachments/assets/a4e8e305-c918-43c8-9702-da20abc9897e" /> <img width="655" height="991" alt="image" src="https://github.com/user-attachments/assets/e3d899fc-b084-4b14-973f-785d1350243c" /> <img width="619" height="611" alt="image" src="https://github.com/user-attachments/assets/e58c0e70-1c55-4d9d-a9b1-e6d72fe645b7" /> Example output from Kibana logs during Fleet setup when there are docs missing `policy_base_id` e.g. enrolled previously or with old fleet-server version. ``` # first run [2026-07-22T11:26:38.363+02:00][DEBUG][plugins.fleet] Backfilling policy_base_id on fleet-agents and fleet-policies [2026-07-22T11:26:38.402+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 2 fleet-agents documents (0 noops) [2026-07-22T11:26:38.456+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 12 fleet-policies documents (0 noops) # second run [2026-07-22T12:38:45.848+02:00][DEBUG][plugins.fleet] Backfilling policy_base_id on fleet-agents and fleet-policies [2026-07-22T12:38:45.850+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 0 fleet-agents documents (0 noops) [2026-07-22T12:38:45.850+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 0 fleet-policies documents (0 noops) ``` --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…gent policy queries (B2) (#279716) (#281330) # Backport This will backport the following commits from `main` to `9.5`: - [[Fleet] Add policy_base_id field to eliminate prefix/wildcard agent policy queries (B2) (#279716)](#279716) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Julia Bardi","email":"90178898+juliaElastic@users.noreply.github.com"},"sourceCommit":{"committedDate":"2026-07-28T16:25:20Z","message":"[Fleet] Add policy_base_id field to eliminate prefix/wildcard agent policy queries (B2) (#279716)\n\n## Summary\n\nAdds a denormalized `policy_base_id` field to `fleet-agents` and\n`.fleet-policies` Elasticsearch indices so readers can use cheap\n`term`/`terms` queries instead of `bool.should[term, prefix]` for\nversion-specific policy lookups.\n\n### Background\n\nFleet supports version-specific agent policies where `policy_id` gets a\n`#major.minor` suffix (e.g. `my-policy#9.2`). Every \"find agents on this\npolicy\" query currently requires:\n\n```json\n{ \"bool\": { \"should\": [{ \"term\": { \"policy_id\": \"my-policy\" } }, { \"prefix\": { \"policy_id\": \"my-policy#\" } }] } }\n```\n\n`prefix` queries are expensive and incompatible with\n`search.allow_expensive_queries: false`. `policy_base_id` stores the\ncanonical base ID (suffix stripped), enabling `{ \"term\": {\n\"policy_base_id\": \"my-policy\" } }` instead.\n\n**Mixed-version rollout fallback**\n(`buildPolicyBaseIdWithFallbackEsFilter` /\n`buildPolicyBaseIdsWithFallbackEsFilter`):\n\nAgents enrolled via an older fleet-server during a rollout will lack\n`policy_base_id`. The four ES DSL query sites use a transitional\nfallback:\n\n```\npolicy_base_id:<id>\nOR (NOT _exists_:policy_base_id AND policy_id:<id>)\n```\n\nThe fallback uses exact `term`/`terms` on `policy_id` only — no `prefix`\n— to remain compatible with `search.allow_expensive_queries: false`.\nVersioned `policy_id` values (e.g. `policy-id#9.3`) without\n`policy_base_id` can only arise in the narrow overlap of a mixed-version\nupgrade; the startup backfill covers all pre-existing documents. Both\nhelpers carry a TODO to remove once all fleet-server versions in use\npopulate the field.\n\n### Deployment order\n\nThis PR must be deployed together with (or after):\n1. **elastic/elasticsearch#154521** — mapping for `policy_base_id` field\n2. **elastic/fleet-server#7422** — writes `policy_base_id` at agent\nenrollment\n\nCloses\n[elastic/ingest-dev#8624](https://github.com/elastic/ingest-dev/issues/8624)\n(Workstream B2).\n\n### Screenshots\n\n<img width=\"1586\" height=\"539\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/a4e8e305-c918-43c8-9702-da20abc9897e\"\n/>\n<img width=\"655\" height=\"991\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/e3d899fc-b084-4b14-973f-785d1350243c\"\n/>\n<img width=\"619\" height=\"611\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/e58c0e70-1c55-4d9d-a9b1-e6d72fe645b7\"\n/>\n\nExample output from Kibana logs during Fleet setup when there are docs\nmissing `policy_base_id` e.g. enrolled previously or with old\nfleet-server version.\n```\n# first run\n[2026-07-22T11:26:38.363+02:00][DEBUG][plugins.fleet] Backfilling policy_base_id on fleet-agents and fleet-policies\n[2026-07-22T11:26:38.402+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 2 fleet-agents documents (0 noops)\n[2026-07-22T11:26:38.456+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 12 fleet-policies documents (0 noops)\n\n# second run\n[2026-07-22T12:38:45.848+02:00][DEBUG][plugins.fleet] Backfilling policy_base_id on fleet-agents and fleet-policies\n[2026-07-22T12:38:45.850+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 0 fleet-agents documents (0 noops)\n[2026-07-22T12:38:45.850+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 0 fleet-policies documents (0 noops)\n```\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>","sha":"83bf19763c00e563edd02e6ffcb9282e8be5d522","branchLabelMapping":{"^v9.6.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Fleet","backport:version","v9.6.0","v9.4.5","v9.5.1"],"title":"[Fleet] Add policy_base_id field to eliminate prefix/wildcard agent policy queries (B2)","number":279716,"url":"https://github.com/elastic/kibana/pull/279716","mergeCommit":{"message":"[Fleet] Add policy_base_id field to eliminate prefix/wildcard agent policy queries (B2) (#279716)\n\n## Summary\n\nAdds a denormalized `policy_base_id` field to `fleet-agents` and\n`.fleet-policies` Elasticsearch indices so readers can use cheap\n`term`/`terms` queries instead of `bool.should[term, prefix]` for\nversion-specific policy lookups.\n\n### Background\n\nFleet supports version-specific agent policies where `policy_id` gets a\n`#major.minor` suffix (e.g. `my-policy#9.2`). Every \"find agents on this\npolicy\" query currently requires:\n\n```json\n{ \"bool\": { \"should\": [{ \"term\": { \"policy_id\": \"my-policy\" } }, { \"prefix\": { \"policy_id\": \"my-policy#\" } }] } }\n```\n\n`prefix` queries are expensive and incompatible with\n`search.allow_expensive_queries: false`. `policy_base_id` stores the\ncanonical base ID (suffix stripped), enabling `{ \"term\": {\n\"policy_base_id\": \"my-policy\" } }` instead.\n\n**Mixed-version rollout fallback**\n(`buildPolicyBaseIdWithFallbackEsFilter` /\n`buildPolicyBaseIdsWithFallbackEsFilter`):\n\nAgents enrolled via an older fleet-server during a rollout will lack\n`policy_base_id`. The four ES DSL query sites use a transitional\nfallback:\n\n```\npolicy_base_id:<id>\nOR (NOT _exists_:policy_base_id AND policy_id:<id>)\n```\n\nThe fallback uses exact `term`/`terms` on `policy_id` only — no `prefix`\n— to remain compatible with `search.allow_expensive_queries: false`.\nVersioned `policy_id` values (e.g. `policy-id#9.3`) without\n`policy_base_id` can only arise in the narrow overlap of a mixed-version\nupgrade; the startup backfill covers all pre-existing documents. Both\nhelpers carry a TODO to remove once all fleet-server versions in use\npopulate the field.\n\n### Deployment order\n\nThis PR must be deployed together with (or after):\n1. **elastic/elasticsearch#154521** — mapping for `policy_base_id` field\n2. **elastic/fleet-server#7422** — writes `policy_base_id` at agent\nenrollment\n\nCloses\n[elastic/ingest-dev#8624](https://github.com/elastic/ingest-dev/issues/8624)\n(Workstream B2).\n\n### Screenshots\n\n<img width=\"1586\" height=\"539\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/a4e8e305-c918-43c8-9702-da20abc9897e\"\n/>\n<img width=\"655\" height=\"991\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/e3d899fc-b084-4b14-973f-785d1350243c\"\n/>\n<img width=\"619\" height=\"611\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/e58c0e70-1c55-4d9d-a9b1-e6d72fe645b7\"\n/>\n\nExample output from Kibana logs during Fleet setup when there are docs\nmissing `policy_base_id` e.g. enrolled previously or with old\nfleet-server version.\n```\n# first run\n[2026-07-22T11:26:38.363+02:00][DEBUG][plugins.fleet] Backfilling policy_base_id on fleet-agents and fleet-policies\n[2026-07-22T11:26:38.402+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 2 fleet-agents documents (0 noops)\n[2026-07-22T11:26:38.456+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 12 fleet-policies documents (0 noops)\n\n# second run\n[2026-07-22T12:38:45.848+02:00][DEBUG][plugins.fleet] Backfilling policy_base_id on fleet-agents and fleet-policies\n[2026-07-22T12:38:45.850+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 0 fleet-agents documents (0 noops)\n[2026-07-22T12:38:45.850+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 0 fleet-policies documents (0 noops)\n```\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>","sha":"83bf19763c00e563edd02e6ffcb9282e8be5d522"}},"sourceBranch":"main","suggestedTargetBranches":["9.4","9.5"],"targetPullRequestStates":[{"branch":"main","label":"v9.6.0","branchLabelMappingKey":"^v9.6.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/279716","number":279716,"mergeCommit":{"message":"[Fleet] Add policy_base_id field to eliminate prefix/wildcard agent policy queries (B2) (#279716)\n\n## Summary\n\nAdds a denormalized `policy_base_id` field to `fleet-agents` and\n`.fleet-policies` Elasticsearch indices so readers can use cheap\n`term`/`terms` queries instead of `bool.should[term, prefix]` for\nversion-specific policy lookups.\n\n### Background\n\nFleet supports version-specific agent policies where `policy_id` gets a\n`#major.minor` suffix (e.g. `my-policy#9.2`). Every \"find agents on this\npolicy\" query currently requires:\n\n```json\n{ \"bool\": { \"should\": [{ \"term\": { \"policy_id\": \"my-policy\" } }, { \"prefix\": { \"policy_id\": \"my-policy#\" } }] } }\n```\n\n`prefix` queries are expensive and incompatible with\n`search.allow_expensive_queries: false`. `policy_base_id` stores the\ncanonical base ID (suffix stripped), enabling `{ \"term\": {\n\"policy_base_id\": \"my-policy\" } }` instead.\n\n**Mixed-version rollout fallback**\n(`buildPolicyBaseIdWithFallbackEsFilter` /\n`buildPolicyBaseIdsWithFallbackEsFilter`):\n\nAgents enrolled via an older fleet-server during a rollout will lack\n`policy_base_id`. The four ES DSL query sites use a transitional\nfallback:\n\n```\npolicy_base_id:<id>\nOR (NOT _exists_:policy_base_id AND policy_id:<id>)\n```\n\nThe fallback uses exact `term`/`terms` on `policy_id` only — no `prefix`\n— to remain compatible with `search.allow_expensive_queries: false`.\nVersioned `policy_id` values (e.g. `policy-id#9.3`) without\n`policy_base_id` can only arise in the narrow overlap of a mixed-version\nupgrade; the startup backfill covers all pre-existing documents. Both\nhelpers carry a TODO to remove once all fleet-server versions in use\npopulate the field.\n\n### Deployment order\n\nThis PR must be deployed together with (or after):\n1. **elastic/elasticsearch#154521** — mapping for `policy_base_id` field\n2. **elastic/fleet-server#7422** — writes `policy_base_id` at agent\nenrollment\n\nCloses\n[elastic/ingest-dev#8624](https://github.com/elastic/ingest-dev/issues/8624)\n(Workstream B2).\n\n### Screenshots\n\n<img width=\"1586\" height=\"539\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/a4e8e305-c918-43c8-9702-da20abc9897e\"\n/>\n<img width=\"655\" height=\"991\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/e3d899fc-b084-4b14-973f-785d1350243c\"\n/>\n<img width=\"619\" height=\"611\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/e58c0e70-1c55-4d9d-a9b1-e6d72fe645b7\"\n/>\n\nExample output from Kibana logs during Fleet setup when there are docs\nmissing `policy_base_id` e.g. enrolled previously or with old\nfleet-server version.\n```\n# first run\n[2026-07-22T11:26:38.363+02:00][DEBUG][plugins.fleet] Backfilling policy_base_id on fleet-agents and fleet-policies\n[2026-07-22T11:26:38.402+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 2 fleet-agents documents (0 noops)\n[2026-07-22T11:26:38.456+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 12 fleet-policies documents (0 noops)\n\n# second run\n[2026-07-22T12:38:45.848+02:00][DEBUG][plugins.fleet] Backfilling policy_base_id on fleet-agents and fleet-policies\n[2026-07-22T12:38:45.850+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 0 fleet-agents documents (0 noops)\n[2026-07-22T12:38:45.850+02:00][DEBUG][plugins.fleet] Backfilled policy_base_id on 0 fleet-policies documents (0 noops)\n```\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>","sha":"83bf19763c00e563edd02e6ffcb9282e8be5d522"}},{"branch":"9.4","label":"v9.4.5","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"9.5","label":"v9.5.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…ollment (#7498) * [Fleet] Write policy_base_id field at agent enrollment (#7422) * Add FieldPolicyBaseID constant * Add PolicyBaseID field to Agent model * Write policy_base_id at agent enrollment * Add policy_base_id to agent schema (source for go generate) * Regenerate schema.go (go generate ./...) * chore: add Elastic license headers to generated Go files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: add unit tests for policyBaseID Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: add changelog fragment for policy_base_id enrollment feature Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: set policy_base_id in re-enrollment UpdateFields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: assert policy_base_id written in re-enrollment UpdateFields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> (cherry picked from commit 761825e) # Conflicts: # model/schema.json * fix: resolve merge conflict in model/schema.json Keep expanded enum with "reenrolled" value from backport. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add FieldPolicyBaseID constant * Add PolicyBaseID field to Agent model * Write policy_base_id at agent enrollment * Add policy_base_id to agent schema (source for go generate) * Regenerate schema.go (go generate ./...) * chore: add Elastic license headers to generated Go files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: add unit tests for policyBaseID Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: add changelog fragment for policy_base_id enrollment feature Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: set policy_base_id in re-enrollment UpdateFields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: assert policy_base_id written in re-enrollment UpdateFields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> (cherry picked from commit 761825e)
* Add FieldPolicyBaseID constant * Add PolicyBaseID field to Agent model * Write policy_base_id at agent enrollment * Add policy_base_id to agent schema (source for go generate) * Regenerate schema.go (go generate ./...) * chore: add Elastic license headers to generated Go files * test: add unit tests for policyBaseID * chore: add changelog fragment for policy_base_id enrollment feature * fix: set policy_base_id in re-enrollment UpdateFields * test: assert policy_base_id written in re-enrollment UpdateFields --------- (cherry picked from commit 761825e) Co-authored-by: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Adds a denormalized
policy_base_idfield written at agent enrollment to enable cheapterm/termsqueries in place of expensive prefix/wildcard queries.Background
Fleet supports version-specific agent policies where
policy_idgets a#major.minorsuffix (e.g.my-policy#9.2). Querying agents by policy currently requires:{ "bool": { "should": [{ "term": { "policy_id": "my-policy" } }, { "prefix": { "policy_id": "my-policy#" } }] } }The
policy_base_idfield stores the canonical base ID (suffix stripped), enabling a singleterm: { policy_base_id: "my-policy" }query instead.Changes
internal/pkg/dl/constants.go: AddFieldPolicyBaseID = "policy_base_id"constantinternal/pkg/model/schema.go: AddPolicyBaseID string json:"policy_base_id,omitempty"field to theAgentmodelinternal/pkg/api/handleEnroll.go: SetPolicyBaseID: policyBaseID(policyID)in the agent struct at enrollment; addpolicyBaseIDhelper that strips the#versionsuffixNotes
agent_policy_idvia partial update — no change needed there;policy_base_idtrackspolicy_id, notagent_policy_idupdate_by_queryduring Fleet setup (companion PR: [Fleet] Add policy_base_id field to eliminate prefix/wildcard agent policy queries (B2) kibana#279716)Part of elastic/ingest-dev#8624 (Workstream B2).