-
Notifications
You must be signed in to change notification settings - Fork 79
Local uri input monitor support #369
base: local-uri-input-monitor-support
Are you sure you want to change the base?
Changes from 5 commits
dc0c449
f33f9a4
546b384
ab030dc
c9a73fd
708d00b
3ec3d71
aa789dd
e819bfb
c50ab98
6111184
28d3fba
c05884a
1d03c61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| package com.amazon.opendistroforelasticsearch.alerting.settings | ||
|
|
||
| import com.amazon.opendistroforelasticsearch.alerting.core.model.LocalUriInput | ||
|
|
||
| /** | ||
| * A class that supports storing a unique set of API paths that can be accessed by general users. | ||
| */ | ||
| class SupportedApiSettings { | ||
| companion object { | ||
| const val CLUSTER_HEALTH_PATH = "/_cluster/health" | ||
| const val CLUSTER_STATS_PATH = "/_cluster/stats" | ||
|
|
||
| /** | ||
| * Each String represents the path to call an API. | ||
| * NOTE: Paths should conform to the following pattern: | ||
| * "/_cluster/health" | ||
| * | ||
| * Each Set<String> represents the supported JSON payload for the respective API. | ||
| */ | ||
| private var supportedApiList = HashMap<String, Map<String, Set<String>>>() | ||
|
|
||
| /** | ||
| * Set to TRUE to enable the supportedApiList check. Set to FALSE to disable. | ||
| */ | ||
| // TODO: Currently set to TRUE for testing purposes. | ||
| // Should likely be set to FALSE by default. | ||
| private var supportedApiListEnabled = true | ||
|
|
||
| init { | ||
| supportedApiList[CLUSTER_HEALTH_PATH] = hashMapOf() | ||
| supportedApiList[CLUSTER_STATS_PATH] = hashMapOf() | ||
| } | ||
|
|
||
| /** | ||
| * Returns the map of all supported json payload associated with the provided path from supportedApiList. | ||
| * @param path The path for the requested API. | ||
| * @return The map of all supported json payload for the requested API. | ||
| * @throws IllegalArgumentException When supportedApiList does not contain a value for the provided key. | ||
| */ | ||
| fun getSupportedJsonPayload(path: String): Map<String, Set<String>> { | ||
| return supportedApiList[path] ?: throw IllegalArgumentException("API path not in supportedApiList: $path") | ||
| } | ||
|
|
||
| /** | ||
| * If [supportedApiListEnabled] is TRUE, calls [validatePath] to confirm whether the provided path | ||
| * is in supportedApiList. Will otherwise take no actions. | ||
| * @param localUriInput The [LocalUriInput] to validate. | ||
| * @return The path that was validated. | ||
| */ | ||
| fun validateLocalUriInput(localUriInput: LocalUriInput): String { | ||
|
||
| val path = localUriInput.toConstructedUri().path | ||
| if (supportedApiListEnabled) validatePath(path) | ||
| return path | ||
| } | ||
|
|
||
| /** | ||
| * Confirms whether the provided path is in supportedApiList. | ||
| * Throws an exception if the provided path is not on the list; otherwise performs no action. | ||
| * @param path The path to validate. | ||
| * @throws IllegalArgumentException When supportedApiList does not contain the provided path. | ||
| */ | ||
| private fun validatePath(path: String) { | ||
| if (!supportedApiList.contains(path)) throw IllegalArgumentException("API path not in supportedApiList: $path") | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.amazon.opendistroforelasticsearch.alerting.util | ||
|
|
||
| import com.amazon.opendistroforelasticsearch.alerting.core.model.LocalUriInput | ||
| import com.amazon.opendistroforelasticsearch.alerting.elasticapi.convertToMap | ||
| import com.amazon.opendistroforelasticsearch.alerting.settings.SupportedApiSettings | ||
| import com.amazon.opendistroforelasticsearch.alerting.settings.SupportedApiSettings.Companion.validateLocalUriInput | ||
| import org.elasticsearch.action.ActionResponse | ||
| import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest | ||
| import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse | ||
| import org.elasticsearch.action.admin.cluster.stats.ClusterStatsRequest | ||
| import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse | ||
| import org.elasticsearch.client.Client | ||
|
|
||
| fun executeTransportAction(localUriInput: LocalUriInput, client: Client): ActionResponse { | ||
| val path = validateLocalUriInput(localUriInput) | ||
| if (path == SupportedApiSettings.CLUSTER_HEALTH_PATH) { | ||
| return client.admin().cluster().health(ClusterHealthRequest()).get() | ||
| } | ||
| if (path == SupportedApiSettings.CLUSTER_STATS_PATH) { | ||
| return client.admin().cluster().clusterStats(ClusterStatsRequest()).get() | ||
| } | ||
| throw IllegalArgumentException("Unsupported API: $path") | ||
|
||
| } | ||
|
|
||
| fun ActionResponse.toMap(): Map<String, Any> { | ||
| if (this is ClusterHealthResponse) { | ||
| return this.convertToMap() | ||
| } | ||
| if (this is ClusterStatsResponse) { | ||
| return this.convertToMap() | ||
| } | ||
| throw IllegalArgumentException("Unsupported ActionResponse type: ${this.javaClass.name}") | ||
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just curious: why do we need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is essentially an on/off switch that I implemented at the beginning of the project. If a user did not want to check the API called by the monitor against the allow list, this value could be set to FALSE. That would allow users to create monitors for any API that this feature support. At the moment, it doesn't serve much of a purpose; but it could be more valuable as more API become supported.
We could remove this value if we feel it's extraneous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand this correctly this is something intended to be specified by the user and if this is set to false then they cannot use the LocalUrlInput feature.
I am not sure I understand how this is configurable by the end user at the moment. Do you think this can be defined as a cluster setting so user can turn it on off as it seems fit for them? or if this is not configurable at the moment suggest going with removing this as it serves no purpose and in future when needed to add the customization we can introduce the cluster setting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If configured to false, users could still use the LocalUriInput feature; but the allow list wouldn't be checked for the requested API before creating and executing the monitor. At the moment, the allow list exposes both of the supported API; but as support for more API is added, a cluster owner could essentially configure this setting to false to allow access to any supported API, regardless of whether they are on the allow list.
Your comment about configuring via settings makes sense though. This will be easy enough to reimplement if there's a need in the future.
Removed this value.