mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[SECURITY SOLUTION] Remove timeline alert search strategy (#160310)
## Summary Fix https://github.com/elastic/security-team/issues/6488 for `timeline alert strategy` Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
f5a111eaab
commit
c40cd0365d
5 changed files with 5 additions and 109 deletions
|
@ -65,7 +65,7 @@ const ACTION_BUTTON_COUNT = 4;
|
|||
const testProps: EventsViewerProps = {
|
||||
defaultModel: eventsDefaultModel,
|
||||
end: to,
|
||||
entityType: EntityType.ALERTS,
|
||||
entityType: EntityType.EVENTS,
|
||||
indexNames: [],
|
||||
tableId: TableId.test,
|
||||
leadingControlColumns: getDefaultControlColumn(ACTION_BUTTON_COUNT),
|
||||
|
|
|
@ -66,7 +66,7 @@ describe('epicLocalStorage', () => {
|
|||
testProps = {
|
||||
defaultModel: eventsDefaultModel,
|
||||
end: to,
|
||||
entityType: EntityType.ALERTS,
|
||||
entityType: EntityType.EVENTS,
|
||||
tableId: TableId.test,
|
||||
leadingControlColumns: getDefaultControlColumn(ACTION_BUTTON_COUNT),
|
||||
renderCellValue: DefaultCellRenderer,
|
||||
|
|
|
@ -18,7 +18,6 @@ export enum TimelineEventsQueries {
|
|||
}
|
||||
|
||||
export const EntityType = {
|
||||
ALERTS: 'alerts',
|
||||
EVENTS: 'events',
|
||||
SESSIONS: 'sessions',
|
||||
} as const;
|
||||
|
|
|
@ -32,7 +32,6 @@ export class TimelinesPlugin
|
|||
core.getStartServices().then(([_, depsStart]) => {
|
||||
const TimelineSearchStrategy = timelineSearchStrategyProvider(
|
||||
depsStart.data,
|
||||
depsStart.alerting,
|
||||
this.logger,
|
||||
this.security
|
||||
);
|
||||
|
|
|
@ -5,14 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ALERT_RULE_CONSUMER, ALERT_RULE_TYPE_ID, SPACE_IDS } from '@kbn/rule-data-utils';
|
||||
import { map, mergeMap, catchError } from 'rxjs/operators';
|
||||
import { from } from 'rxjs';
|
||||
import {
|
||||
AlertingAuthorizationEntity,
|
||||
AlertingAuthorizationFilterType,
|
||||
PluginStartContract as AlertingPluginStartContract,
|
||||
} from '@kbn/alerting-plugin/server';
|
||||
import { map, mergeMap } from 'rxjs/operators';
|
||||
import {
|
||||
ISearchStrategy,
|
||||
PluginStart,
|
||||
|
@ -20,8 +13,7 @@ import {
|
|||
shimHitsTotal,
|
||||
} from '@kbn/data-plugin/server';
|
||||
import { ENHANCED_ES_SEARCH_STRATEGY, ISearchOptions } from '@kbn/data-plugin/common';
|
||||
import { AuditLogger, SecurityPluginSetup } from '@kbn/security-plugin/server';
|
||||
import { AlertAuditAction, alertAuditEvent } from '@kbn/rule-registry-plugin/server';
|
||||
import { SecurityPluginSetup } from '@kbn/security-plugin/server';
|
||||
import { Logger } from '@kbn/logging';
|
||||
import {
|
||||
TimelineFactoryQueryTypes,
|
||||
|
@ -35,15 +27,12 @@ import { isAggCardinalityAggregate } from './factory/helpers/is_agg_cardinality_
|
|||
|
||||
export const timelineSearchStrategyProvider = <T extends TimelineFactoryQueryTypes>(
|
||||
data: PluginStart,
|
||||
alerting: AlertingPluginStartContract,
|
||||
logger: Logger,
|
||||
security?: SecurityPluginSetup
|
||||
): ISearchStrategy<TimelineStrategyRequestType<T>, TimelineStrategyResponseType<T>> => {
|
||||
const esAsInternal = data.search.searchAsInternalUser;
|
||||
const es = data.search.getSearchStrategy(ENHANCED_ES_SEARCH_STRATEGY);
|
||||
return {
|
||||
search: (request, options, deps) => {
|
||||
const securityAuditLogger = security?.audit.asScoped(deps.request);
|
||||
const factoryQueryType = request.factoryQueryType;
|
||||
const entityType = request.entityType;
|
||||
|
||||
|
@ -53,17 +42,7 @@ export const timelineSearchStrategyProvider = <T extends TimelineFactoryQueryTyp
|
|||
|
||||
const queryFactory: TimelineFactory<T> = timelineFactory[factoryQueryType];
|
||||
|
||||
if (entityType != null && entityType === EntityType.ALERTS) {
|
||||
return timelineAlertsSearchStrategy({
|
||||
es: esAsInternal,
|
||||
request,
|
||||
options,
|
||||
deps,
|
||||
queryFactory,
|
||||
alerting,
|
||||
auditLogger: securityAuditLogger,
|
||||
});
|
||||
} else if (entityType != null && entityType === EntityType.SESSIONS) {
|
||||
if (entityType != null && entityType === EntityType.SESSIONS) {
|
||||
return timelineSessionsSearchStrategy({
|
||||
es,
|
||||
request,
|
||||
|
@ -109,87 +88,6 @@ const timelineSearchStrategy = <T extends TimelineFactoryQueryTypes>({
|
|||
);
|
||||
};
|
||||
|
||||
const timelineAlertsSearchStrategy = <T extends TimelineFactoryQueryTypes>({
|
||||
es,
|
||||
request,
|
||||
options,
|
||||
deps,
|
||||
queryFactory,
|
||||
alerting,
|
||||
auditLogger,
|
||||
}: {
|
||||
es: ISearchStrategy;
|
||||
request: TimelineStrategyRequestType<T>;
|
||||
options: ISearchOptions;
|
||||
deps: SearchStrategyDependencies;
|
||||
alerting: AlertingPluginStartContract;
|
||||
queryFactory: TimelineFactory<T>;
|
||||
auditLogger: AuditLogger | undefined;
|
||||
}) => {
|
||||
const indices = request.defaultIndex ?? request.indexType;
|
||||
const requestWithAlertsIndices = { ...request, defaultIndex: indices, indexName: indices };
|
||||
|
||||
// Note: Alerts RBAC are built off of the alerting's authorization class, which
|
||||
// is why we are pulling from alerting, not ther alertsClient here
|
||||
const alertingAuthorizationClient = alerting.getAlertingAuthorizationWithRequest(deps.request);
|
||||
const getAuthFilter = async () =>
|
||||
alertingAuthorizationClient.getFindAuthorizationFilter(AlertingAuthorizationEntity.Alert, {
|
||||
type: AlertingAuthorizationFilterType.ESDSL,
|
||||
// Not passing in values, these are the paths for these fields
|
||||
fieldNames: {
|
||||
consumer: ALERT_RULE_CONSUMER,
|
||||
ruleTypeId: ALERT_RULE_TYPE_ID,
|
||||
spaceIds: SPACE_IDS,
|
||||
},
|
||||
});
|
||||
|
||||
return from(getAuthFilter()).pipe(
|
||||
mergeMap(({ filter }) => {
|
||||
const dsl = queryFactory.buildDsl({
|
||||
...requestWithAlertsIndices,
|
||||
authFilter: filter,
|
||||
});
|
||||
return es.search({ ...requestWithAlertsIndices, params: dsl }, options, deps);
|
||||
}),
|
||||
map((response) => {
|
||||
const rawResponse = shimHitsTotal(response.rawResponse, options);
|
||||
// Do we have to loop over each hit? Yes.
|
||||
// ecs auditLogger requires that we log each alert independently
|
||||
if (auditLogger != null) {
|
||||
rawResponse.hits?.hits?.forEach((hit) => {
|
||||
auditLogger.log(
|
||||
alertAuditEvent({
|
||||
action: AlertAuditAction.FIND,
|
||||
id: hit._id,
|
||||
outcome: 'success',
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...response,
|
||||
rawResponse,
|
||||
};
|
||||
}),
|
||||
mergeMap((esSearchRes) => queryFactory.parse(requestWithAlertsIndices, esSearchRes)),
|
||||
catchError((err) => {
|
||||
// check if auth error, if yes, write to ecs logger
|
||||
if (auditLogger != null && err?.output?.statusCode === 403) {
|
||||
auditLogger.log(
|
||||
alertAuditEvent({
|
||||
action: AlertAuditAction.FIND,
|
||||
outcome: 'failure',
|
||||
error: err,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
throw err;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const timelineSessionsSearchStrategy = <T extends TimelineFactoryQueryTypes>({
|
||||
es,
|
||||
request,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue