[EDR Workflows] Add cross-project search read-path support for osquery#280273
Draft
szwarckonrad wants to merge 16 commits into
Draft
[EDR Workflows] Add cross-project search read-path support for osquery#280273szwarckonrad wants to merge 16 commits into
szwarckonrad wants to merge 16 commits into
Conversation
Gate osquery read paths on cpsEnabled: scoped asCurrentUser with projectRouting space on serverless CPS, unchanged asInternalUser elsewhere. Includes search strategy, routes, export PIT, roles mirror, and picker registration.
Correct getStartServices typing, Option B index routing (internal for fleet/actions metadata, scoped for result/response data), legacy responses role grant, and test/type fixes.
|
🤖 Jobs for this PR can be triggered through checkboxes. 🚧
ℹ️ To trigger the CI, please tick the checkbox below 👇
|
… flag Flips the crossProjectSearch experimental flag default to true so the PR serverless image ships with the flag on for QAF-based CPS e2e testing on QA. Revert before marking this PR ready for review or merging; the feature must land dark (default off) so QA can flip it on a BC.
Contributor
Author
|
@elasticmachine merge upstream |
Contributor
Author
|
/ci |
The CPS read-only project picker registration increases the osquery public bundle past the previous 48128 limit. Raise it to 48500 to cover the current size with a small buffer.
Contributor
Author
|
@elasticmachine merge upstream |
Contributor
|
There are no new commits on the base branch. |
Contributor
Author
|
/ci |
Under cross-project search the osquery History list and detail views read action metadata from .logs-osquery_manager.actions-*, which was pinned to the internal user and therefore origin-only. That made a linked project's queries unreachable from the origin project, so the result and response data that does fan out had no UI surface to appear on. Route osquery-owned indices (action metadata, results, action responses) through the request user so CPS fans them out, and keep only Fleet-owned indices (.fleet-actions*, .fleet-actions-results*, .fleet-agents*) on the internal client. The action dispatch path is unchanged and stays origin-only. The serverless security roles now grant read on .logs-osquery_manager.actions-* in a dedicated read-only block alongside the legacy .logs-osquery_manager.action.responses-* pattern, which until now was granted together with write on six of the twelve roles. Index existence checks stay on the internal client because a read-only grant cannot perform index admin actions, and the history routes fall back to the internal client when the Fleet actions index is the target. Tagging an action still resolves it origin-only, since tags are a write and cross-project writes are not supported this milestone.
Contributor
Author
|
@elasticmachine merge upstream |
Contributor
Author
|
/ci |
Scheduled history rows and Status tab agent names were rendered only from project-local sources, so a row fanned in from a linked project showed a blank Query column and a raw agent UUID. Both labels already exist on the response documents, so fall back to them when the local lookup misses: pack_id, pack_name and query_name via size-1 terms sub-aggregations on the scheduled_executions buckets, and agent.name or host.name for the agent display name. The pack saved object and the Fleet agent lookup still win whenever they resolve, so same-project behaviour is unchanged, and rows whose labels are absent degrade to today's blank/UUID rendering rather than failing. The sub-aggregations run on keyword fields and cost +6ms at 500 buckets, +140ms at the 10k bucket ceiling.
Contributor
Author
|
/ci |
Contributor
💔 Build Failed
Failed CI StepsMetrics [docs]Module Count
Async chunks
Page load bundle
History
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On serverless with Cross-Project Search (CPS) enabled, this lets osquery read its query results and responses across all linked projects, so a user in a central project can investigate their whole fleet in one place. It is read-only and fully gated: when CPS is off, or on stateful Kibana, osquery behaves exactly as before.
Cross-project reads run as the logged-in user, which is the only identity Elasticsearch allows to fan out across projects. Action metadata and Fleet indices stay on the internal user and remain origin-only.
Test plan
cps_local(origin plus one linked project), signed in as a stock role user (for example soc_manager or t2_analyst, not the operator user): osquery results and responses from the linked project appear in the origin project.LLM description
What and why
Adds CPS read-path support to the osquery server plugin, gated behind the platform
cps.cpsEnabledconfig (serverless only, default false). When enabled, osquery data reads fan out across linked projects using the end-user identity; otherwise every path is byte-identical to today.Gate
cpsadded to osqueryoptionalPluginsinkibana.jsonc.cpsEnabledis derived fromplugins.cps?.getCpsEnabled() ?? falseinserver/plugin.tsand stored on the osquery app context.Client selection (Option B)
Two helpers under
server/utils:getReadEsClient: whencpsEnabled, returnsclusterClient.asScoped(request, { projectRouting: 'space' }).asCurrentUser; otherwiseasInternalUser.getScopedSearch: whencpsEnabled, returnsdata.search.asScoped(request, { projectRouting: 'space' }); otherwisecontext.search.cps_read_routing.tsclassifies indices and decides which client the search strategy uses.Option B means only osquery result and response data reads fan out as the current user. Fleet indices and osquery action metadata reads stay on
asInternalUserand remain origin-only, for two reasons: action metadata is origin-only for this milestone, and two stock roles (editor, platform_engineer) have no Fleet index grants, so flipping those reads to the current user would break them.Roles mirror
The kbn-es serverless roles mirror grants read on the legacy dotted
.logs-osquery_manager.action.responses-*to the twelve stock security roles. The existinglogs-*grant already covers results and modern responses, and these roles already have theread_project_routingcluster privilege. The.logs-osquery_manager.actions-*(action metadata) pattern is intentionally not granted, because under Option B the current user never reads it. The reserved-role grant for QA and production is a separate elasticsearch-controller change.Picker
Registers osquery as read-only app access through
plugins.cps?.cpsManager?.registerAppAccess.Tests
Unit tests cover the index classification, the read client selection, and the search strategy client choice, plus updates to affected route tests.
tscand the relevant jest suites pass.Made with Cursor