Skip to content

Commit 532af40

Browse files
[9.3] Fix DHQ checkPermissions error handling (#257882) (#257941)
# Backport This will backport the following commits from `main` to `9.3`: - [Fix DHQ checkPermissions error handling (#257882)](#257882) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Sebastián Zaffarano","email":"sebastian.zaffarano@elastic.co"},"sourceCommit":{"committedDate":"2026-03-16T15:03:35Z","message":"Fix DHQ checkPermissions error handling (#257882)\n\n## Summary\n\nhttps://github.com//pull/256956 introduced a regression\nbecause it checks read permissions on indices resolved by the `index`\nexpression. Example, a query for `logs-apache.access-*` ends up querying\nthe datastream backing indices, e.g.,\n`.ds-logs-apache.access-default-2026.03.16-000001`. The read permission\nis assigned to `logs-apache.access-default` but not\n`.ds-logs-apache.access*`. This PR checks the permissions on the query\ndescription index expression rather than the resolved/effective indices.\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [ ] Any text added follows [EUI's writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\nsentence case text and includes [i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n- [ ]\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\nwas added for features that require explanation or tutorials\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [ ] If a plugin configuration key changed, check if it needs to be\nallowlisted in the cloud and added to the [docker\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\n- [ ] This was checked for breaking HTTP API changes, and any breaking\nchanges have been approved by the breaking-change committee. The\n`release_note:breaking` label should be applied in these situations.\n- [ ] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [ ] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n- [ ] Review the [backport\nguidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)\nand apply applicable `backport:*` labels.\n\n### Identify risks\n\nDoes this PR introduce any risks? For example, consider risks like hard\nto test bugs, performance regression, potential of data loss.\n\nDescribe the risk, its severity, and mitigation for each identified\nrisk. Invite stakeholders and evaluate how to proceed before merging.\n\n- [ ] [See some risk\nexamples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)\n- [ ] ...","sha":"a477ef728b0d8a297afba6147ad770cc97b01b06","branchLabelMapping":{"^v9.4.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","ci:build-cloud-image","ci:build-serverless-image","backport:version","v9.4.0","v9.3.2","v9.2.8"],"title":"Fix DHQ checkPermissions error handling","number":257882,"url":"https://github.com/elastic/kibana/pull/257882","mergeCommit":{"message":"Fix DHQ checkPermissions error handling (#257882)\n\n## Summary\n\nhttps://github.com//pull/256956 introduced a regression\nbecause it checks read permissions on indices resolved by the `index`\nexpression. Example, a query for `logs-apache.access-*` ends up querying\nthe datastream backing indices, e.g.,\n`.ds-logs-apache.access-default-2026.03.16-000001`. The read permission\nis assigned to `logs-apache.access-default` but not\n`.ds-logs-apache.access*`. This PR checks the permissions on the query\ndescription index expression rather than the resolved/effective indices.\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [ ] Any text added follows [EUI's writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\nsentence case text and includes [i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n- [ ]\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\nwas added for features that require explanation or tutorials\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [ ] If a plugin configuration key changed, check if it needs to be\nallowlisted in the cloud and added to the [docker\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\n- [ ] This was checked for breaking HTTP API changes, and any breaking\nchanges have been approved by the breaking-change committee. The\n`release_note:breaking` label should be applied in these situations.\n- [ ] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [ ] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n- [ ] Review the [backport\nguidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)\nand apply applicable `backport:*` labels.\n\n### Identify risks\n\nDoes this PR introduce any risks? For example, consider risks like hard\nto test bugs, performance regression, potential of data loss.\n\nDescribe the risk, its severity, and mitigation for each identified\nrisk. Invite stakeholders and evaluate how to proceed before merging.\n\n- [ ] [See some risk\nexamples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)\n- [ ] ...","sha":"a477ef728b0d8a297afba6147ad770cc97b01b06"}},"sourceBranch":"main","suggestedTargetBranches":["9.3","9.2"],"targetPullRequestStates":[{"branch":"main","label":"v9.4.0","branchLabelMappingKey":"^v9.4.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/257882","number":257882,"mergeCommit":{"message":"Fix DHQ checkPermissions error handling (#257882)\n\n## Summary\n\nhttps://github.com//pull/256956 introduced a regression\nbecause it checks read permissions on indices resolved by the `index`\nexpression. Example, a query for `logs-apache.access-*` ends up querying\nthe datastream backing indices, e.g.,\n`.ds-logs-apache.access-default-2026.03.16-000001`. The read permission\nis assigned to `logs-apache.access-default` but not\n`.ds-logs-apache.access*`. This PR checks the permissions on the query\ndescription index expression rather than the resolved/effective indices.\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [ ] Any text added follows [EUI's writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\nsentence case text and includes [i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n- [ ]\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\nwas added for features that require explanation or tutorials\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [ ] If a plugin configuration key changed, check if it needs to be\nallowlisted in the cloud and added to the [docker\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\n- [ ] This was checked for breaking HTTP API changes, and any breaking\nchanges have been approved by the breaking-change committee. The\n`release_note:breaking` label should be applied in these situations.\n- [ ] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [ ] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n- [ ] Review the [backport\nguidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)\nand apply applicable `backport:*` labels.\n\n### Identify risks\n\nDoes this PR introduce any risks? For example, consider risks like hard\nto test bugs, performance regression, potential of data loss.\n\nDescribe the risk, its severity, and mitigation for each identified\nrisk. Invite stakeholders and evaluate how to proceed before merging.\n\n- [ ] [See some risk\nexamples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)\n- [ ] ...","sha":"a477ef728b0d8a297afba6147ad770cc97b01b06"}},{"branch":"9.3","label":"v9.3.2","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"9.2","label":"v9.2.8","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Sebastián Zaffarano <sebastian.zaffarano@elastic.co>
1 parent 58559ac commit 532af40

2 files changed

Lines changed: 50 additions & 50 deletions

File tree

x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/diagnostic/health_diagnostic_receiver.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,11 +473,11 @@ describe('Security Solution - Health Diagnostic Queries - CircuitBreakingQueryEx
473473
queryExecutor.search({ query, circuitBreakers: [circuitBreaker] }),
474474
() => {
475475
expect(mockEsClient.indices.exists).toHaveBeenCalledWith({
476-
index: ['test-index'],
476+
index: 'test-index',
477477
allow_no_indices: false,
478478
});
479479
expect(mockEsClient.security.hasPrivileges).toHaveBeenCalledWith({
480-
index: [{ names: ['test-index'], privileges: ['read'] }],
480+
index: [{ names: 'test-index', privileges: ['read'] }],
481481
});
482482
expect(mockEsClient.openPointInTime).toHaveBeenCalled();
483483
done();

x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/diagnostic/health_diagnostic_receiver.ts

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ export class CircuitBreakingQueryExecutorImpl implements CircuitBreakingQueryExe
6969
streamEsql<T>(diagnosticQuery: HealthDiagnosticQuery, abortSignal: AbortSignal): Observable<T> {
7070
const regex = /^[\s\r\n]*FROM/;
7171

72-
return from(this.indicesFor(diagnosticQuery)).pipe(
73-
mergeMap((index) =>
74-
from(this.checkPermissions(index)).pipe(
75-
mergeMap(() => {
72+
return from(this.checkPermissions(diagnosticQuery.index)).pipe(
73+
mergeMap(() =>
74+
from(this.indicesFor(diagnosticQuery)).pipe(
75+
mergeMap((index) => {
7676
const query = regex.test(diagnosticQuery.query)
7777
? diagnosticQuery.query
7878
: `FROM ${index} | ${diagnosticQuery.query}`;
@@ -91,10 +91,10 @@ export class CircuitBreakingQueryExecutorImpl implements CircuitBreakingQueryExe
9191
}
9292

9393
streamEql<T>(diagnosticQuery: HealthDiagnosticQuery, abortSignal: AbortSignal): Observable<T> {
94-
return from(this.indicesFor(diagnosticQuery)).pipe(
95-
mergeMap((index) =>
96-
from(this.checkPermissions(index)).pipe(
97-
mergeMap(() => {
94+
return from(this.checkPermissions(diagnosticQuery.index)).pipe(
95+
mergeMap(() =>
96+
from(this.indicesFor(diagnosticQuery)).pipe(
97+
mergeMap((index) => {
9898
const request: EqlSearchRequest = {
9999
index,
100100
query: diagnosticQuery.query,
@@ -173,52 +173,52 @@ export class CircuitBreakingQueryExecutorImpl implements CircuitBreakingQueryExe
173173
return this.client.search<T>(paginatedRequest, { signal: abortSignal });
174174
};
175175

176-
return from(this.indicesFor(diagnosticQuery)).pipe(
177-
mergeMap((index) =>
178-
from(this.checkPermissions(index)).pipe(
179-
mergeMap(() => {
180-
return from(this.client.openPointInTime({ index, keep_alive: pitKeepAlive }));
181-
})
182-
)
183-
),
184-
map((res) => res.id),
176+
return from(this.checkPermissions(diagnosticQuery.index)).pipe(
177+
mergeMap(() =>
178+
from(this.indicesFor(diagnosticQuery)).pipe(
179+
mergeMap((index) =>
180+
from(this.client.openPointInTime({ index, keep_alive: pitKeepAlive }))
181+
),
182+
map((res) => res.id),
185183

186-
mergeMap((id) => {
187-
pitId = id;
188-
return from(fetchPage());
189-
}),
190-
expand((searchResponse) => {
191-
const returnedPitId = (searchResponse as { pit_id?: string }).pit_id;
192-
if (returnedPitId) {
193-
pitId = returnedPitId;
194-
}
184+
mergeMap((id) => {
185+
pitId = id;
186+
return from(fetchPage());
187+
}),
188+
expand((searchResponse) => {
189+
const returnedPitId = (searchResponse as { pit_id?: string }).pit_id;
190+
if (returnedPitId) {
191+
pitId = returnedPitId;
192+
}
195193

196-
const hits = searchResponse.hits.hits;
197-
const aggrs = searchResponse.aggregations;
194+
const hits = searchResponse.hits.hits;
195+
const aggrs = searchResponse.aggregations;
198196

199-
if (aggrs || hits.length === 0) {
200-
return EMPTY;
201-
}
197+
if (aggrs || hits.length === 0) {
198+
return EMPTY;
199+
}
202200

203-
searchAfter = hits[hits.length - 1].sort;
204-
return from(fetchPage());
205-
}),
201+
searchAfter = hits[hits.length - 1].sort;
202+
return from(fetchPage());
203+
}),
206204

207-
mergeMap((searchResponse) => {
208-
if (searchResponse.aggregations) {
209-
return [searchResponse.aggregations as T];
210-
} else {
211-
return searchResponse.hits.hits.map((h) => h._source as T);
212-
}
213-
}),
205+
mergeMap((searchResponse) => {
206+
if (searchResponse.aggregations) {
207+
return [searchResponse.aggregations as T];
208+
} else {
209+
return searchResponse.hits.hits.map((h) => h._source as T);
210+
}
211+
}),
214212

215-
finalize(() => {
216-
if (pitId !== undefined) {
217-
this.client.closePointInTime({ id: pitId }).catch((error) => {
218-
this.logger.warn('>> closePointInTime error', withErrorMessage(error));
219-
});
220-
}
221-
})
213+
finalize(() => {
214+
if (pitId !== undefined) {
215+
this.client.closePointInTime({ id: pitId }).catch((error) => {
216+
this.logger.warn('>> closePointInTime error', withErrorMessage(error));
217+
});
218+
}
219+
})
220+
)
221+
)
222222
);
223223
}
224224

0 commit comments

Comments
 (0)