Skip to content

Add filter by backend roles setting - #2034

Merged
AWSHurneyt merged 46 commits into
opensearch-project:mainfrom
cloud-gov:add-filter-by-backend-roles-setting
Jul 20, 2026
Merged

Add filter by backend roles setting#2034
AWSHurneyt merged 46 commits into
opensearch-project:mainfrom
cloud-gov:add-filter-by-backend-roles-setting

Conversation

@markdboyd

@markdboyd markdboyd commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds a new plugin setting, plugins.alerting.filter_by_backend_roles_access_strategy, which allows users to control how filtering by backend roles works to determine access to alerting objects (monitors). The options for this setting are:

  • exact - Users have access to alerting objects if they have exactly the same (with no additional) backend roles as the user who created the object
  • intersect - Users have access to alerting objects if they share at least one backend role with the user who created the object
  • all - Users have access to alerting objects if their backend roles contain all of the backend roles of the user who created the object

Related Issues

Resolves #1940

Check List

  • New functionality includes testing.
  • New functionality has been documented.
  • API changes companion pull request created.
  • Commits are signed per the DCO using --signoff.
  • Public documentation issue/PR created.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

fun doUserBackendRolesMatchResource(userBackendRoles: List<String>, resourceBackendRoles: List<String>): Boolean {
if (filterByAccessStrategy == FilterByBackendRolesAccessStrategy.INTERSECT.strategy) {
return resourceBackendRoles.any { it in userBackendRoles }
} else if (filterByAccessStrategy == FilterByBackendRolesAccessStrategy.ALL.strategy) {

@AWSHurneyt AWSHurneyt Mar 20, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markdboyd with the ALL strategy, what is the intended behavior when a user has all of the same backend roles but also some additional roles? With this implementation, it looks like a user with more roles would not match the resource.

If I'm understanding the use case correctly, are the below behaviors the intention?

  1. user roles = [role1, role2, role3] and resource roles = [role1, role2, role3] should match
  2. user roles = [role1, role2, role3, role4, role5] and resource roles = [role1, role2, role3] should match
  3. user roles = [role1, role2, role3] and resource roles = [role1, role2, role3, role4, role5] should not match

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AWSHurneyt

what is the intended behavior when a user has all of the same backend roles but also some additional roles

In this case with the ALL strategy, the user would not have access.

If I'm understanding the use case correctly, are the below behaviors the intention?

  1. user roles = [role1, role2, role3] and resource roles = [role1, role2, role3] should match
  2. user roles = [role1, role2, role3, role4, role5] and resource roles = [role1, role2, role3] should match
  3. user roles = [role1, role2, role3] and resource roles = [role1, role2, role3, role4, role5] should not match

For scenario 2, the behavior would also be not match and the user would not have access

Perhaps ALL would be better named MATCH_EXACTLY to specify this behavior?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah thanks for clarifying. Yeah, EXACT makes sense in my mind given that additional context.

However, that intended behavior seems odd to me. Could you help me understand the use case for not permitting access to the resource when a user has more roles than are necessary?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AWSHurneyt - I thought more about this and I agree: ALL should provide access if the user roles contain all of the object backend roles, even if the user has additional roles. So for ALL, the user would have access in scenarios 1 and 2.

I added new logic to handle the ALL strategy. And I added EXACT as a separate strategy where the roles must match exactly with no additional roles

markdboyd added 11 commits June 9, 2026 09:40
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
…s access strategy

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
…ckend roles

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
…mpare sorted lists

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
…tting

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
…omparing

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
@markdboyd

Copy link
Copy Markdown
Contributor Author

@AWSHurneyt OK, I believe that I have added all of the requested tests

@AWSHurneyt

Copy link
Copy Markdown
Collaborator

@markdboyd I've rerun the failing security test a few times, but it still failing unfortunately. Could you take a look?

@markdboyd

Copy link
Copy Markdown
Contributor Author

@AWSHurneyt OK. I've run 5 of the failing tests from that workflow on my local machine, but none are failing so far.

…oes not run with any information from the parent context & add comments to explain behavior

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
…access strategy is exact

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
@markdboyd

Copy link
Copy Markdown
Contributor Author

@AWSHurneyt OK, I think I have resolved the test failures. The cause of the failures was the changes that I have made in the TransportAcknowledgeAlertAction.kt code.

Initially, the problem was that I was having failures on tests acknowledging alerts when filtering by backend roles is enabled. Specifically, the code was returning this error: https://github.com/cloud-gov/opensearch-alerting/blob/dcb6f946bf12da4e9d6124db2f9fa7c059d1bf24/alerting/src/main/kotlin/org/opensearch/alerting/transport/SecureTransportAction.kt#L86-L92

I traced out the error to the fact that TransportAcknowledgeAlertAction is doing a request to get a monitor: https://github.com/cloud-gov/opensearch-alerting/blob/dcb6f946bf12da4e9d6124db2f9fa7c059d1bf24/alerting/src/main/kotlin/org/opensearch/alerting/transport/TransportAcknowledgeAlertAction.kt#L112. And when filtering by backend role is enabled, this request needs the user information from the parent context, otherwise it fails with the above error.

My initial fix was to pass along just the user information from the parent context manually: 16a21e3. But it seems that solution was not thread safe, so inspired by

client.threadPool().threadContext.stashContext().use {
scope.launch(TenantContext(tenantId)) {
val singleThreadContext = newSingleThreadContext("GetRemoteIndexesActionThread")
withContext(singleThreadContext) {
it.restore()
, I refactored the code to 4c908c0.

However, with that change, we started seeing several integration test failures related to acknowledging alerts. I believe that the problem with 4c908c0 is that it was including the user information from the parent context when invoking the AcknowledgeHandler. However, the AcknowledgeHandler wants to run in the system context without any information about the authenticated user, otherwise it fails to retrieve information about alerts.

So I have now refactored the code again to 298276a. The gist of the behavior is now:

With these changes, I believe that the code should function as expected when filtering by backend role is enabled or not. And that all tests should now pass.

…t to get monitor operation

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
… when acknowledging an alert

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
… to acknowledge alerts

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
val validator = FilterByBackendRolesAccessStrategyValidator()
validator.validate("all")
validator.validate("exact")
validator.validate("intersect")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we expect capitalized and mixed-case inputs to be valid (e.g., ALL, and aLl)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the validation case insensitive: 2412be4, however, does this change alone allow a capitalized input to be accepted and used by the system?

@cwperks cwperks Jul 8, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AWSHurneyt since this is a cluster setting, I believe adding mixed case here allows all these permutations for flexibility. Similar to a CLI program accepting y|Y|YES|yes for more flexibility.

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
FilterByBackendRolesAccessStrategy.INTERSECT.strategy,
FilterByBackendRolesAccessStrategyValidator(),
Setting.Property.NodeScope,
Setting.Property.Dynamic

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as alerting PR, let's add Setting.Property.Sensitive here.

@Volatile private var indexTimeout = INDEX_TIMEOUT.get(settings)

@Volatile override var filterByEnabled = AlertingSettings.FILTER_BY_BACKEND_ROLES.get(settings)
@Volatile override var filterByAccessStrategy = AlertingSettings.FILTER_BY_BACKEND_ROLES_ACCESS_STRATEGY.get(settings)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert in this repo, but why must this be copied to all of these transport actions?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cwperks I think the reason this variable has to be copied into all of the transport actions is that filterByAccessStrategy is defined as a member on the SecureTransportAction interface which all of these actions implement: https://github.com/cloud-gov/opensearch-alerting/blob/2412be4a761f203a7cf1aac2a37321f3e6b7d1eb/alerting/src/main/kotlin/org/opensearch/alerting/transport/SecureTransportAction.kt#L42. So in order to satisfy the interface, all of the transport actions must include that member.

If I remove this line from the code then try to compile the plugin, I get this error:

Class 'TransportIndexAlertingCommentAction' is not abstract and does not implement abstract member:
var filterByAccessStrategy: String

AlertingSettings.TENANT_ACCOUNT_ID_HEADER,
AlertingSettings.TENANT_RESOURCE_ID_HEADER
AlertingSettings.TENANT_RESOURCE_ID_HEADER,
AlertingSettings.FILTER_BY_BACKEND_ROLES_ACCESS_STRATEGY

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add this near related FILTER_BY_BACKEND_ROLES setting in this list.

enableFilterBy()
putAlertMappings()

if (!isHttps()) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw I think you can add something like

@Before
fun checkPluggableDataformatEnabled() {
assumeTrue(
"Skipping — pluggable dataformat tests require feature flag enabled on cluster",
System.getProperty("tests.pluggable_dataformat_enabled", "false").toBoolean()
)
}
at the top of the test suite to skip all tests if running ITs without security enabled.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cwperks Not all of the tests in this file seem to require that https is enabled. Should they and then I can apply your suggested change?

…loser to AlertingSettings.FILTER_BY_BACKEND_ROLES in the plugin settings

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
…STRATEGY plugin setting

Signed-off-by: Mark Boyd <mark.boyd@gsa.gov>
@markdboyd

Copy link
Copy Markdown
Contributor Author

Related documentation changes: opensearch-project/documentation-website#12794

@AWSHurneyt

Copy link
Copy Markdown
Collaborator

Confirmed with @cwperks offline that his comments have been addressed. Merging.

@AWSHurneyt
AWSHurneyt merged commit f12e0c0 into opensearch-project:main Jul 20, 2026
18 checks passed
@markdboyd
markdboyd deleted the add-filter-by-backend-roles-setting branch July 20, 2026 18:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Add setting to control access to alerting objects by backend roles

3 participants