Skip to content

Commit 636b43f

Browse files
authored
Add validation check for doc level query name during monitor creation (opensearch-project#1506)
* add validation check for doc level query name during monitor creation Signed-off-by: Joanne Wang <[email protected]> * change to 0-256 chars Signed-off-by: Joanne Wang <[email protected]> * change validation message and move validation loc Signed-off-by: Joanne Wang <[email protected]> --------- Signed-off-by: Joanne Wang <[email protected]>
1 parent 62003ee commit 636b43f

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

alerting/src/main/kotlin/org/opensearch/alerting/resthandler/RestIndexMonitorAction.kt

+18
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ import org.opensearch.commons.alerting.action.AlertingActions
1616
import org.opensearch.commons.alerting.action.IndexMonitorRequest
1717
import org.opensearch.commons.alerting.action.IndexMonitorResponse
1818
import org.opensearch.commons.alerting.model.BucketLevelTrigger
19+
import org.opensearch.commons.alerting.model.DocLevelMonitorInput
1920
import org.opensearch.commons.alerting.model.DocumentLevelTrigger
2021
import org.opensearch.commons.alerting.model.Monitor
2122
import org.opensearch.commons.alerting.model.QueryLevelTrigger
2223
import org.opensearch.commons.alerting.model.ScheduledJob
24+
import org.opensearch.commons.utils.getInvalidNameChars
25+
import org.opensearch.commons.utils.isValidName
2326
import org.opensearch.core.rest.RestStatus
2427
import org.opensearch.core.xcontent.ToXContent
2528
import org.opensearch.core.xcontent.XContentParser.Token
@@ -117,8 +120,10 @@ class RestIndexMonitorAction : BaseRestHandler() {
117120
throw IllegalArgumentException("Illegal trigger type, ${it.javaClass.name}, for document level monitor")
118121
}
119122
}
123+
validateDocLevelQueryName(monitor)
120124
}
121125
}
126+
122127
val seqNo = request.paramAsLong(IF_SEQ_NO, SequenceNumbers.UNASSIGNED_SEQ_NO)
123128
val primaryTerm = request.paramAsLong(IF_PRIMARY_TERM, SequenceNumbers.UNASSIGNED_PRIMARY_TERM)
124129
val refreshPolicy = if (request.hasParam(REFRESH)) {
@@ -133,6 +138,19 @@ class RestIndexMonitorAction : BaseRestHandler() {
133138
}
134139
}
135140

141+
private fun validateDocLevelQueryName(monitor: Monitor) {
142+
monitor.inputs.filterIsInstance<DocLevelMonitorInput>().forEach { docLevelMonitorInput ->
143+
docLevelMonitorInput.queries.forEach { dlq ->
144+
if (!isValidName(dlq.name)) {
145+
throw IllegalArgumentException(
146+
"Doc level query name may not start with [_, +, -], contain '..', or contain: " +
147+
getInvalidNameChars().replace("\\", "")
148+
)
149+
}
150+
}
151+
}
152+
}
153+
136154
private fun validateDataSources(monitor: Monitor) { // Data Sources will currently be supported only at transport layer.
137155
if (monitor.dataSources != null) {
138156
if (

alerting/src/test/kotlin/org/opensearch/alerting/resthandler/MonitorRestApiIT.kt

+47
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import org.opensearch.alerting.randomAnomalyDetector
2626
import org.opensearch.alerting.randomAnomalyDetectorWithUser
2727
import org.opensearch.alerting.randomBucketLevelMonitor
2828
import org.opensearch.alerting.randomBucketLevelTrigger
29+
import org.opensearch.alerting.randomDocLevelMonitorInput
30+
import org.opensearch.alerting.randomDocLevelQuery
2931
import org.opensearch.alerting.randomDocumentLevelMonitor
3032
import org.opensearch.alerting.randomDocumentLevelTrigger
3133
import org.opensearch.alerting.randomQueryLevelMonitor
@@ -48,6 +50,7 @@ import org.opensearch.commons.alerting.model.Monitor
4850
import org.opensearch.commons.alerting.model.QueryLevelTrigger
4951
import org.opensearch.commons.alerting.model.ScheduledJob
5052
import org.opensearch.commons.alerting.model.SearchInput
53+
import org.opensearch.commons.utils.getInvalidNameChars
5154
import org.opensearch.core.common.bytes.BytesReference
5255
import org.opensearch.core.rest.RestStatus
5356
import org.opensearch.core.xcontent.ToXContent
@@ -1285,6 +1288,50 @@ class MonitorRestApiIT : AlertingRestTestCase() {
12851288
}
12861289
}
12871290

1291+
fun `test creating and updating a document monitor with invalid query name`() {
1292+
// creating a monitor with an invalid query name
1293+
val invalidQueryName = "_Invalid .. query ! n>ame"
1294+
val queries = listOf(randomDocLevelQuery(name = invalidQueryName))
1295+
val randomDocLevelMonitorInput = randomDocLevelMonitorInput(queries = queries)
1296+
val inputs = listOf(randomDocLevelMonitorInput)
1297+
val trigger = randomDocumentLevelTrigger()
1298+
var monitor = randomDocumentLevelMonitor(inputs = inputs, triggers = listOf(trigger))
1299+
1300+
try {
1301+
client().makeRequest("POST", ALERTING_BASE_URI, emptyMap(), monitor.toHttpEntity())
1302+
fail("Doc level monitor with invalid query name should be rejected")
1303+
} catch (e: ResponseException) {
1304+
assertEquals("Unexpected status", RestStatus.BAD_REQUEST, e.response.restStatus())
1305+
val expectedMessage = "Doc level query name may not start with [_, +, -], contain '..', or contain: " +
1306+
getInvalidNameChars().replace("\\", "")
1307+
e.message?.let { assertTrue(it.contains(expectedMessage)) }
1308+
}
1309+
1310+
// successfully creating monitor with valid query name
1311+
val testIndex = createTestIndex()
1312+
val docQuery = DocLevelQuery(query = "test_field:\"us-west-2\"", name = "valid (name)", fields = listOf())
1313+
val docLevelInput = DocLevelMonitorInput("description", listOf(testIndex), listOf(docQuery))
1314+
1315+
monitor = createMonitor(randomDocumentLevelMonitor(inputs = listOf(docLevelInput), triggers = listOf(trigger)))
1316+
1317+
// updating monitor with invalid query name
1318+
val updatedDocQuery = DocLevelQuery(query = "test_field:\"us-west-2\"", name = invalidQueryName, fields = listOf())
1319+
val updatedDocLevelInput = DocLevelMonitorInput("description", listOf(testIndex), listOf(updatedDocQuery))
1320+
1321+
try {
1322+
client().makeRequest(
1323+
"PUT", monitor.relativeUrl(),
1324+
emptyMap(), monitor.copy(inputs = listOf(updatedDocLevelInput)).toHttpEntity()
1325+
)
1326+
fail("Doc level monitor with invalid query name should be rejected")
1327+
} catch (e: ResponseException) {
1328+
assertEquals("Unexpected status", RestStatus.BAD_REQUEST, e.response.restStatus())
1329+
val expectedMessage = "Doc level query name may not start with [_, +, -], contain '..', or contain: " +
1330+
getInvalidNameChars().replace("\\", "")
1331+
e.message?.let { assertTrue(it.contains(expectedMessage)) }
1332+
}
1333+
}
1334+
12881335
/**
12891336
* This use case is needed by the frontend plugin for displaying alert counts on the Monitors list page.
12901337
* https://github.com/opensearch-project/alerting-dashboards-plugin/blob/main/server/services/MonitorService.js#L235

0 commit comments

Comments
 (0)