[SecuritySolution] Add an option to search on alerts index without wildcard (#153439)

## Summary

Add an option to search alerts without wildcard to avoid seeing alerts
from other spaces with the same prefix.

Issue and steps to reproduce (or visit a [reproduced
environment](https://kibana.siem.estc.dev/s/test/app/security/alerts?sourcerer=(default:(id:security-solution-test,selectedPatterns:!(%27auditbeat-*%27,%27filebeat-*%27,%27logs-*%27,%27packetbeat-*%27,%27winlogbeat-*%27)))&timerange=(global:(linkTo:!(timeline),timerange:(from:%272023-03-15T00:00:00.000Z%27,fromStr:now-7d%2Fd,kind:relative,to:%272023-03-22T13:10:17.682Z%27,toStr:now)),timeline:(linkTo:!(global),timerange:(from:%272023-03-15T00:00:00.000Z%27,fromStr:now-7d%2Fd,kind:relative,to:%272023-03-22T13:10:17.682Z%27,toStr:now)))&filters=!((%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,field:_index,key:_index,negate:!f,params:(query:.alerts-security.alerts-test-2),type:phrase),query:(match_phrase:(_index:.alerts-security.alerts-test-2)))))):
1. In `x-pack/plugins/security_solution/common/experimental_features.ts`
, change `chartEmbeddablesEnabled` to `false`
2. Follow the steps in
https://github.com/elastic/security-team/issues/6231

### Checklist

Delete any items that are not applicable to this PR.


- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: Marshall Main <55718608+marshallmain@users.noreply.github.com>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Angela Chuang 2023-03-29 21:23:23 +01:00 committed by GitHub
parent e41cc7ad1c
commit 90b0c39c7c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 2 deletions

View file

@ -100,10 +100,33 @@ describe('RuleDataClient', () => {
expect(scopedClusterClient.search).toHaveBeenCalledWith({
body: query,
ignore_unavailable: true,
index: `.alerts-observability.apm.alerts*`,
});
});
test('getReader searchs an index pattern without a wildcard when the namespace is provided', async () => {
const ruleDataClient = new RuleDataClient(
getRuleDataClientOptions({
waitUntilReadyForReading: new Promise((resolve) =>
setTimeout(resolve, 3000, right(scopedClusterClient))
),
})
);
const query = { query: { bool: { filter: { range: { '@timestamp': { gte: 0 } } } } } };
const reader = ruleDataClient.getReader({ namespace: 'test' });
await reader.search({
body: query,
});
expect(scopedClusterClient.search).toHaveBeenCalledWith({
body: query,
ignore_unavailable: true,
index: `.alerts-observability.apm.alerts-test`,
});
});
test('re-throws error when search throws error', async () => {
scopedClusterClient.search.mockRejectedValueOnce(new Error('something went wrong!'));
const ruleDataClient = new RuleDataClient(getRuleDataClientOptions({}));

View file

@ -117,6 +117,7 @@ export class RuleDataClient implements IRuleDataClient {
return (await clusterClient.search({
...request,
index: indexPattern,
ignore_unavailable: true,
})) as unknown as ESSearchResponse<TAlertDoc, TSearchRequest>;
} catch (err) {
this.options.logger.error(`Error performing search in RuleDataClient - ${err.message}`);

View file

@ -114,10 +114,10 @@ export class IndexInfo {
* - include nested registration contexts eagerly
* - e.g. if baseName='.alerts-observability', include '.alerts-observability.apm'
*
* @example '.alerts-security.alerts-default*', '.alerts-security.alerts*'
* @example '.alerts-security.alerts-default', '.alerts-security.alerts*'
*/
public getPatternForReading(namespace?: string): string {
return `${joinWithDash(this.baseName, namespace)}*`;
return namespace ? `${joinWithDash(this.baseName, namespace)}` : `${this.baseName}*`;
}
/**

View file

@ -48,6 +48,20 @@ describe('query for signal', () => {
);
});
test('search on an index pattern without wildcard added', async () => {
const response = await server.inject(
getSignalsQueryRequest(),
requestContextMock.convertContext(context)
);
expect(response.status).toEqual(200);
expect(ruleDataClient.getReader).toHaveBeenCalledWith(
expect.objectContaining({
namespace: 'default',
})
);
});
test('returns 200 when using single agg', async () => {
const response = await server.inject(
getSignalsAggsQueryRequest(),