Skip to content

Commit

Permalink
fix get alerts api with default params to return chained alerts and s…
Browse files Browse the repository at this point in the history
…kip audit alerts

Signed-off-by: Surya Sashank Nistala <[email protected]>
  • Loading branch information
eirsep committed Jul 13, 2023
1 parent 3ba65f2 commit c53ff40
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ object MonitorMetadataService :
monitor: Monitor,
createWithRunContext: Boolean = true,
skipIndex: Boolean = false,
workflowMetadataId: String? = null,
workflowMetadataId: String? = null
): Pair<MonitorMetadata, Boolean> {
try {
val created = true
Expand Down Expand Up @@ -154,7 +154,7 @@ object MonitorMetadataService :
XContentType.JSON
)
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.nextToken(), xcp)
MonitorMetadata.parse(xcp)
MonitorMetadata.parse(xcp, getResponse.id, getResponse.seqNo, getResponse.primaryTerm)
} else {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class TransportGetAlertsAction @Inject constructor(
clusterService: ClusterService,
actionFilters: ActionFilters,
val settings: Settings,
val xContentRegistry: NamedXContentRegistry
val xContentRegistry: NamedXContentRegistry,
) : HandledTransportAction<ActionRequest, GetAlertsResponse>(
AlertingActions.GET_ALERTS_ACTION_NAME,
transportService,
Expand All @@ -77,7 +77,7 @@ class TransportGetAlertsAction @Inject constructor(
override fun doExecute(
task: Task,
request: ActionRequest,
actionListener: ActionListener<GetAlertsResponse>
actionListener: ActionListener<GetAlertsResponse>,
) {
val getAlertsRequest = request as? GetAlertsRequest
?: recreateObject(request) { GetAlertsRequest(it) }
Expand All @@ -97,7 +97,15 @@ class TransportGetAlertsAction @Inject constructor(
queryBuilder.filter(QueryBuilders.termQuery("severity", getAlertsRequest.severityLevel))
}

if (getAlertsRequest.alertState != "ALL") {
if (getAlertsRequest.alertState == "ALL") {
// alerting dashboards expects chained alerts and individually executed monitors' alerts to be returned from this api
// when invoked with state=ALL. They require that audit alerts are NOT returned in this page
// and only be shown in "associated alerts" field under get workflow_alerts API.
// But if the API is called with query_params: state=AUDIT,monitor_id=<123>,workflow_id=<abc>, this api
// will return audit alerts generated by delegate monitor <123> in workflow <abc>
QueryBuilders.boolQuery()
.filter(QueryBuilders.boolQuery().mustNot(QueryBuilders.termsQuery(Alert.STATE_FIELD, Alert.State.AUDIT.name)))
} else {
queryBuilder.filter(QueryBuilders.termQuery("state", getAlertsRequest.alertState))
}

Expand All @@ -107,16 +115,23 @@ class TransportGetAlertsAction @Inject constructor(

if (getAlertsRequest.monitorId != null) {
queryBuilder.filter(QueryBuilders.termQuery("monitor_id", getAlertsRequest.monitorId))
if (getAlertsRequest.workflowIds.isNullOrEmpty()) {
val noWorklfowIdQuery = QueryBuilders.boolQuery()
.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(Alert.WORKFLOW_ID_FIELD)))
.should(QueryBuilders.termsQuery(Alert.WORKFLOW_ID_FIELD, ""))
queryBuilder.must(noWorklfowIdQuery)
}
} else if (getAlertsRequest.monitorIds.isNullOrEmpty() == false) {
queryBuilder.filter(QueryBuilders.termsQuery("monitor_id", getAlertsRequest.monitorIds))
if (getAlertsRequest.workflowIds.isNullOrEmpty()) {
val noWorklfowIdQuery = QueryBuilders.boolQuery()
.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(Alert.WORKFLOW_ID_FIELD)))
.should(QueryBuilders.termsQuery(Alert.WORKFLOW_ID_FIELD, ""))
queryBuilder.must(noWorklfowIdQuery)
}
}
if (getAlertsRequest.workflowIds.isNullOrEmpty() == false) {
queryBuilder.must(QueryBuilders.termsQuery("workflow_id", getAlertsRequest.workflowIds))
} else {
val noWorklfowIdQuery = QueryBuilders.boolQuery()
.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(Alert.WORKFLOW_ID_FIELD)))
.should(QueryBuilders.termsQuery(Alert.WORKFLOW_ID_FIELD, ""))
queryBuilder.must(noWorklfowIdQuery)
}
if (!tableProp.searchString.isNullOrBlank()) {
queryBuilder
Expand Down Expand Up @@ -196,7 +211,7 @@ class TransportGetAlertsAction @Inject constructor(
alertIndex: String,
searchSourceBuilder: SearchSourceBuilder,
actionListener: ActionListener<GetAlertsResponse>,
user: User?
user: User?,
) {
// user is null when: 1/ security is disabled. 2/when user is super-admin.
if (user == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ object CompositeWorkflowRunner : WorkflowRunner() {
.should(boolQuery().mustNot(existsQuery(Alert.ERROR_MESSAGE_FIELD)))
.should(termsQuery(Alert.ERROR_MESSAGE_FIELD, ""))
queryBuilder.must(noErrorQuery)
searchRequest.source().query(queryBuilder)
searchRequest.source().query(queryBuilder).size(9999)
val searchResponse: SearchResponse = monitorCtx.client!!.suspendUntil { monitorCtx.client!!.search(searchRequest, it) }
val alerts = searchResponse.hits.map { hit ->
val xcp = XContentHelper.createParser(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3942,6 +3942,23 @@ class MonitorDataSourcesIT : AlertingSingleNodeTestCase() {
)
var chainedAlerts = res.alerts
Assert.assertTrue(chainedAlerts.size == 1)

// verify get alerts api with defaults set in query params returns only chained alerts and not audit alerts
val table = Table("asc", "id", null, 1, 0, "")
val getAlertsDefaultParamsResponse = client().execute(
AlertingActions.GET_ALERTS_ACTION_TYPE,
GetAlertsRequest(
table = table,
severityLevel = "ALL",
alertState = "ALL",
monitorId = null,
alertIndex = null,
monitorIds = null,
workflowIds = null,
alertIds = null
)
).get()
Assert.assertEquals(getAlertsDefaultParamsResponse.alerts.size, 1)
Assert.assertTrue(res.associatedAlerts.isEmpty())
verifyAcknowledgeChainedAlerts(chainedAlerts, workflowId, 1)
Assert.assertTrue(chainedAlerts[0].executionId == executeWorkflowResponse.workflowRunResult.executionId)
Expand Down Expand Up @@ -3985,6 +4002,20 @@ class MonitorDataSourcesIT : AlertingSingleNodeTestCase() {
notTriggerResult = triggerResults[notTrigger.id]
Assert.assertFalse(notTriggerResult!!.triggered)
Assert.assertTrue(andTriggerResult!!.triggered)
val getAuditAlertsForMonitor1 = client().execute(
AlertingActions.GET_ALERTS_ACTION_TYPE,
GetAlertsRequest(
table = table,
severityLevel = "ALL",
alertState = "AUDIT",
monitorId = monitorResponse.id,
alertIndex = null,
monitorIds = null,
workflowIds = listOf(workflowId),
alertIds = null
)
).get()
Assert.assertEquals(getAuditAlertsForMonitor1.alerts.size, 1)
res = getWorkflowAlerts(workflowId)
chainedAlerts = res.alerts
Assert.assertTrue(chainedAlerts.size == 1)
Expand Down Expand Up @@ -4022,6 +4053,10 @@ class MonitorDataSourcesIT : AlertingSingleNodeTestCase() {
assertAuditStateAlerts(monitorResponse2.id, alerts1)
assertFindings(monitorResponse2.id, customFindingsIndex2, 1, 1, listOf("2"))
verifyAcknowledgeChainedAlerts(chainedAlerts, workflowId, 1)
//test redundant executions of workflow dont query old data again to verify metadata updation works fine
val redundantExec = executeWorkflow(workflow)
Assert.assertFalse(redundantExec?.workflowRunResult!!.triggerResults[andTrigger.id]!!.triggered)
Assert.assertTrue(redundantExec.workflowRunResult.triggerResults[notTrigger.id]!!.triggered)
}

private fun getDelegateMonitorMetadataId(
Expand Down

0 comments on commit c53ff40

Please sign in to comment.