diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 94415f9b59e004..1fd0552569b2d8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -217,6 +217,7 @@ export const signalRulesAlertType = ({ hasTimestampFields( wroteStatus, hasTimestampOverride ? (timestampOverride as string) : '@timestamp', + name, timestampFieldCaps, inputIndices, ruleStatusService, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index 7888bb6deaab79..a68fac7d920f26 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -843,6 +843,7 @@ describe('utils', () => { const res = await hasTimestampFields( false, timestampField, + 'myfakerulename', // eslint-disable-next-line @typescript-eslint/no-explicit-any timestampFieldCapsResponse as ApiResponse>, ['myfa*'], @@ -883,6 +884,7 @@ describe('utils', () => { const res = await hasTimestampFields( false, timestampField, + 'myfakerulename', // eslint-disable-next-line @typescript-eslint/no-explicit-any timestampFieldCapsResponse as ApiResponse>, ['myfa*'], @@ -895,6 +897,60 @@ describe('utils', () => { ); expect(res).toBeTruthy(); }); + + test('returns true when missing logs-endpoint.alerts-* index and rule name is Endpoint Security', async () => { + const timestampField = '@timestamp'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const timestampFieldCapsResponse: Partial, Context>> = { + body: { + indices: [], + fields: {}, + }, + }; + mockLogger.error.mockClear(); + const res = await hasTimestampFields( + false, + timestampField, + 'Endpoint Security', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + timestampFieldCapsResponse as ApiResponse>, + ['logs-endpoint.alerts-*'], + ruleStatusServiceMock, + mockLogger, + buildRuleMessage + ); + expect(mockLogger.error).toHaveBeenCalledWith( + 'This rule is attempting to query data from Elasticsearch indices listed in the "Index pattern" section of the rule definition, however no index matching: ["logs-endpoint.alerts-*"] was found. This warning will continue to appear until a matching index is created or this rule is de-activated. If you have recently enrolled agents enabled with Endpoint Security through Fleet, this warning should stop once an alert is sent from an agent. name: "fake name" id: "fake id" rule id: "fake rule id" signals index: "fakeindex"' + ); + expect(res).toBeTruthy(); + }); + + test('returns true when missing logs-endpoint.alerts-* index and rule name is NOT Endpoint Security', async () => { + const timestampField = '@timestamp'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const timestampFieldCapsResponse: Partial, Context>> = { + body: { + indices: [], + fields: {}, + }, + }; + mockLogger.error.mockClear(); + const res = await hasTimestampFields( + false, + timestampField, + 'NOT Endpoint Security', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + timestampFieldCapsResponse as ApiResponse>, + ['logs-endpoint.alerts-*'], + ruleStatusServiceMock, + mockLogger, + buildRuleMessage + ); + expect(mockLogger.error).toHaveBeenCalledWith( + 'This rule is attempting to query data from Elasticsearch indices listed in the "Index pattern" section of the rule definition, however no index matching: ["logs-endpoint.alerts-*"] was found. This warning will continue to appear until a matching index is created or this rule is de-activated. name: "fake name" id: "fake id" rule id: "fake rule id" signals index: "fakeindex"' + ); + expect(res).toBeTruthy(); + }); }); describe('wrapBuildingBlocks', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts index 58bf22be97bf87..30471ae2a35484 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts @@ -105,6 +105,7 @@ export const hasReadIndexPrivileges = async ( export const hasTimestampFields = async ( wroteStatus: boolean, timestampField: string, + ruleName: string, // any is derived from here // node_modules/@elastic/elasticsearch/api/kibana.d.ts // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -115,11 +116,15 @@ export const hasTimestampFields = async ( buildRuleMessage: BuildRuleMessage ): Promise => { if (!wroteStatus && isEmpty(timestampFieldCapsResponse.body.indices)) { - const errorString = `The following index patterns did not match any indices: ${JSON.stringify( + const errorString = `This rule is attempting to query data from Elasticsearch indices listed in the "Index pattern" section of the rule definition, however no index matching: ${JSON.stringify( inputIndices - )}`; - logger.error(buildRuleMessage(errorString)); - await ruleStatusService.warning(errorString); + )} was found. This warning will continue to appear until a matching index is created or this rule is de-activated. ${ + ruleName === 'Endpoint Security' + ? 'If you have recently enrolled agents enabled with Endpoint Security through Fleet, this warning should stop once an alert is sent from an agent.' + : '' + }`; + logger.error(buildRuleMessage(errorString.trimEnd())); + await ruleStatusService.warning(errorString.trimEnd()); return true; } else if ( !wroteStatus && diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts index 8d494724d9f766..6bdf881ba8ca29 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts @@ -138,7 +138,7 @@ export default ({ getService }: FtrProviderContext) => { expect(statusBody[body.id].current_status.status).to.eql('warning'); expect(statusBody[body.id].current_status.last_success_message).to.eql( - 'The following index patterns did not match any indices: ["does-not-exist-*"]' + 'This rule is attempting to query data from Elasticsearch indices listed in the "Index pattern" section of the rule definition, however no index matching: ["does-not-exist-*"] was found. This warning will continue to appear until a matching index is created or this rule is de-activated.' ); });