Skip to content

Commit 5ee37d5

Browse files
opensearch-trigger-bot[bot]petardzlezzago
authored andcommitted
[Backport 2.x] Notification security fix (opensearch-project#861)
* Notification security fix (opensearch-project#852) * added injecting whole user object in threadContext before calling notification APIs so that backend roles are available to notification plugin Signed-off-by: Petar Dzepina <[email protected]> * compile fix Signed-off-by: Petar Dzepina <[email protected]> * refactored user_info injection to use InjectSecurity Signed-off-by: Petar Dzepina <[email protected]> * ktlint fix Signed-off-by: Petar Dzepina <[email protected]> --------- Signed-off-by: Petar Dzepina <[email protected]> (cherry picked from commit e0b7a5a) * remove unneeded import Signed-off-by: Ashish Agrawal <[email protected]> --------- Signed-off-by: Ashish Agrawal <[email protected]> Co-authored-by: Petar Dzepina <[email protected]> Co-authored-by: Ashish Agrawal <[email protected]> Signed-off-by: AWSHurneyt <[email protected]>
1 parent 2337100 commit 5ee37d5

File tree

2 files changed

+27
-33
lines changed

2 files changed

+27
-33
lines changed

alerting/src/main/kotlin/org/opensearch/alerting/MonitorRunner.kt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,24 @@ abstract class MonitorRunner {
6262
throw IllegalStateException("Message content missing in the Destination with id: ${action.destinationId}")
6363
}
6464
if (!dryrun) {
65-
val roles = MonitorRunnerService.getRolesForMonitor(monitor)
66-
withClosableContext(
67-
InjectorContextElement(monitor.id, monitorCtx.settings!!, monitorCtx.threadPool!!.threadContext, roles)
68-
) {
69-
actionOutput[Action.MESSAGE_ID] = getConfigAndSendNotification(
70-
action,
71-
monitorCtx,
72-
actionOutput[Action.SUBJECT],
73-
actionOutput[Action.MESSAGE]!!
74-
)
65+
val client = monitorCtx.client
66+
client!!.threadPool().threadContext.stashContext().use {
67+
withClosableContext(
68+
InjectorContextElement(
69+
monitor.id,
70+
monitorCtx.settings!!,
71+
monitorCtx.threadPool!!.threadContext,
72+
monitor.user?.roles,
73+
monitor.user
74+
)
75+
) {
76+
actionOutput[Action.MESSAGE_ID] = getConfigAndSendNotification(
77+
action,
78+
monitorCtx,
79+
actionOutput[Action.SUBJECT],
80+
actionOutput[Action.MESSAGE]!!
81+
)
82+
}
7583
}
7684
}
7785
ActionRunResult(action.id, action.name, actionOutput, false, MonitorRunnerService.currentTime(), null)

core/src/main/kotlin/org/opensearch/alerting/opensearchapi/OpenSearchExtensions.kt

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import org.opensearch.action.search.ShardSearchFailure
1818
import org.opensearch.client.OpenSearchClient
1919
import org.opensearch.common.settings.Settings
2020
import org.opensearch.common.util.concurrent.ThreadContext
21-
import org.opensearch.common.util.concurrent.ThreadContext.StoredContext
2221
import org.opensearch.common.xcontent.ToXContent
2322
import org.opensearch.common.xcontent.XContentHelper
2423
import org.opensearch.common.xcontent.XContentType
@@ -171,28 +170,13 @@ suspend fun <T> NotificationsPluginInterface.suspendUntil(block: NotificationsPl
171170
})
172171
}
173172

174-
/**
175-
* Store a [ThreadContext] and restore a [ThreadContext] when the coroutine resumes on a different thread.
176-
*
177-
* @param threadContext - a [ThreadContext] instance
178-
*/
179-
class ElasticThreadContextElement(private val threadContext: ThreadContext) : ThreadContextElement<Unit> {
180-
181-
companion object Key : CoroutineContext.Key<ElasticThreadContextElement>
182-
private var context: StoredContext = threadContext.newStoredContext(true)
183-
184-
override val key: CoroutineContext.Key<*>
185-
get() = Key
186-
187-
override fun restoreThreadContext(context: CoroutineContext, oldState: Unit) {
188-
this.context = threadContext.stashContext()
189-
}
190-
191-
override fun updateThreadContext(context: CoroutineContext) = this.context.close()
192-
}
193-
194-
class InjectorContextElement(id: String, settings: Settings, threadContext: ThreadContext, private val roles: List<String>?) :
195-
ThreadContextElement<Unit> {
173+
class InjectorContextElement(
174+
id: String,
175+
settings: Settings,
176+
threadContext: ThreadContext,
177+
private val roles: List<String>?,
178+
private val user: User? = null
179+
) : ThreadContextElement<Unit> {
196180

197181
companion object Key : CoroutineContext.Key<InjectorContextElement>
198182
override val key: CoroutineContext.Key<*>
@@ -202,6 +186,8 @@ class InjectorContextElement(id: String, settings: Settings, threadContext: Thre
202186

203187
override fun updateThreadContext(context: CoroutineContext) {
204188
rolesInjectorHelper.injectRoles(roles)
189+
// This is from where plugins extract backend roles. It should be passed when calling APIs of other plugins
190+
rolesInjectorHelper.injectUserInfo(user)
205191
}
206192

207193
override fun restoreThreadContext(context: CoroutineContext, oldState: Unit) {

0 commit comments

Comments
 (0)