How to get a list of indices for which i have been granted permission?

Versions (relevant - OpenSearch/Dashboard/Server OS/Browser):
Currently testing with 2.11 but the same applies for older releases.

Describe the issue:
As an example I created a new user (testuser) and a new role (testrole) and mapped the user to the role. Then I granted the role INDICES_ALL on a single index in my OpenSeach instance.

What i would like to do is get a list of indices for which my testuser can access, but it seems unless i grant permissions on all other indices generic calls like _mappings or _stats or _aliases all seem to return a permission error.

This is different behavior than what I noticed with Elasticsearch.
To find out what indexes the user can access we tried the following APIs:

  • _stats - requires indices:monitor/stats
  • _aliases - requires indices:admin/aliases/get
  • _mappings - requires indices:admin/mappings/get
  • _cat/indices - requires cluster:monitor/state & indices:monitor/settings/get

and Elasticsearch will return the info for the indicesfor which i have granted this permission
but OpenSearch will fail unless we grant permissions on ALL indices.

Further there is an additional API in Elasticsearch that can rerturn information about what indexes that i have permissions:

  • ⁠_security/user/_privileges - doesnt seem to require any specific permissions

but I dont see any equivalent in OpenSearch.

Our goal is to simply allow a user to get a list of indices they have permission to with the least amount of permissions granted.

Hi @cdobbins,

To achieve the desired behaviour in OpenSearch with minimal permission you will need the following:

/opensearch/config/opensearch-security/config.yml
add:

config:
  dynamic:
    do_not_fail_on_forbidden: true
    do_not_fail_on_forbidden_empty: true
    ...

Minimum permission required:

    "cluster_permissions" : [
      "cluster:monitor/state",
      "cluster:monitor/health"
    ],
    "index_permissions" : [
      {
        "index_patterns" : [
          **List of index patterns**
        ],
        "allowed_actions" : [
          "indices:monitor/settings/get",
          "indices:monitor/stats"
        ]
      }
    ]

You can get more information on this here: [BUG] do_not_fail_on_forbidden_empty does not work for cat api · Issue #1815 · opensearch-project/security · GitHub and [Backport 2.x] Command `cat/indices` will filter results per the do not fail on forbidden setting by derek-ho · Pull Request #3258 · opensearch-project/security · GitHub

Best,
Mantas

Thanks Mantas for the info although, i dont think its working.
I have this set in the config.yml

config:
  dynamic:
    do_not_fail_on_forbidden: true
    do_not_fail_on_forbidden_empty: true

And i set the permissions you mentioned


…but i still get the permissions error unless i specify * for indexes

But beyond the functionality not working as you described…Do you know if there are options that dont require cluster_permissions?
For example in Elasticsearch i can simply grant indices:monitor/stats on the index i want and then calling _stats will return the stats for that one index.
We are looking for a solution that will allow a user to retrieve the names of indexes they have permission to read/search with the least possible permissions.

Hi @cdobbins ,

Could you please run the below and share the output:

in a terminal with curl:

curl --insecure -u <adminUSERNAME>:<adminPASSWORD> -XGET https://<OpenSearch_node_FQDN_or_IP>:9200/_plugins/_security/api/securityconfig?pretty

or in devTools with admin user:

GET _plugins/_security/api/securityconfig?pretty

NOTE: please blank any sensitive data if any.

Thanks,
Mantas

Here is the output, and i see that the options didnt actually get set to TRUE…
hmm

{
    "config": {
        "dynamic": {
            "filtered_alias_mode": "warn",
            "disable_rest_auth": false,
            "disable_intertransport_auth": false,
            "respect_request_indices_options": false,
            "kibana": {
                "multitenancy_enabled": true,
                "private_tenant_enabled": true,
                "default_tenant": "",
                "server_username": "kibanaserver",
                "index": ".kibana"
            },
            "http": {
                "anonymous_auth_enabled": false,
                "xff": {
                    "enabled": false,
                    "internalProxies": "192\\.168\\.0\\.10|192\\.168\\.0\\.11",
                    "remoteIpHeader": "X-Forwarded-For"
                }
            },
            "authc": {
                "jwt_auth_domain": {
                    "http_enabled": false,
                    "transport_enabled": false,
                    "order": 0,
                    "http_authenticator": {
                        "challenge": false,
                        "type": "jwt",
                        "config": {
                            "signing_key": "base64 encoded HMAC key or public RSA/ECDSA pem key",
                            "jwt_header": "Authorization",
                            "jwt_clock_skew_tolerance_seconds": 30
                        }
                    },
                    "authentication_backend": {
                        "type": "noop",
                        "config": {
                        }
                    },
                    "description": "Authenticate via Json Web Token"
                },
                "ldap": {
                    "http_enabled": false,
                    "transport_enabled": false,
                    "order": 5,
                    "http_authenticator": {
                        "challenge": false,
                        "type": "basic",
                        "config": {
                        }
                    },
                    "authentication_backend": {
                        "type": "ldap",
                        "config": {
                            "enable_ssl": false,
                            "enable_start_tls": false,
                            "enable_ssl_client_auth": false,
                            "verify_hostnames": true,
                            "hosts": [
                                "localhost:8389"
                            ],
                            "userbase": "ou=people,dc=example,dc=com",
                            "usersearch": "(sAMAccountName={0})"
                        }
                    },
                    "description": "Authenticate via LDAP or Active Directory"
                },
                "basic_internal_auth_domain": {
                    "http_enabled": true,
                    "transport_enabled": true,
                    "order": 4,
                    "http_authenticator": {
                        "challenge": true,
                        "type": "basic",
                        "config": {
                        }
                    },
                    "authentication_backend": {
                        "type": "intern",
                        "config": {
                        }
                    },
                    "description": "Authenticate via HTTP Basic against internal users database"
                },
                "proxy_auth_domain": {
                    "http_enabled": false,
                    "transport_enabled": false,
                    "order": 3,
                    "http_authenticator": {
                        "challenge": false,
                        "type": "proxy",
                        "config": {
                            "user_header": "x-proxy-user",
                            "roles_header": "x-proxy-roles"
                        }
                    },
                    "authentication_backend": {
                        "type": "noop",
                        "config": {
                        }
                    },
                    "description": "Authenticate via proxy"
                },
                "clientcert_auth_domain": {
                    "http_enabled": false,
                    "transport_enabled": false,
                    "order": 2,
                    "http_authenticator": {
                        "challenge": false,
                        "type": "clientcert",
                        "config": {
                            "username_attribute": "cn"
                        }
                    },
                    "authentication_backend": {
                        "type": "noop",
                        "config": {
                        }
                    },
                    "description": "Authenticate via SSL client certificates"
                },
                "kerberos_auth_domain": {
                    "http_enabled": false,
                    "transport_enabled": false,
                    "order": 6,
                    "http_authenticator": {
                        "challenge": true,
                        "type": "kerberos",
                        "config": {
                            "krb_debug": false,
                            "strip_realm_from_principal": true
                        }
                    },
                    "authentication_backend": {
                        "type": "noop",
                        "config": {
                        }
                    }
                }
            },
            "authz": {
                "roles_from_another_ldap": {
                    "http_enabled": false,
                    "transport_enabled": false,
                    "authorization_backend": {
                        "type": "ldap",
                        "config": {
                        }
                    },
                    "description": "Authorize via another Active Directory"
                },
                "roles_from_myldap": {
                    "http_enabled": false,
                    "transport_enabled": false,
                    "authorization_backend": {
                        "type": "ldap",
                        "config": {
                            "enable_ssl": false,
                            "enable_start_tls": false,
                            "enable_ssl_client_auth": false,
                            "verify_hostnames": true,
                            "hosts": [
                                "localhost:8389"
                            ],
                            "rolebase": "ou=groups,dc=example,dc=com",
                            "rolesearch": "(member={0})",
                            "userrolename": "disabled",
                            "rolename": "cn",
                            "resolve_nested_roles": true,
                            "userbase": "ou=people,dc=example,dc=com",
                            "usersearch": "(uid={0})"
                        }
                    },
                    "description": "Authorize via LDAP or Active Directory"
                }
            },
            "auth_failure_listeners": {
            },
            "do_not_fail_on_forbidden": false,
            "multi_rolespan_enabled": true,
            "hosts_resolver_mode": "ip-only",
            "do_not_fail_on_forbidden_empty": false
        }
    }
}

Have you applied your changes using ./securityadmin.sh, please see more details here: Applying changes to configuration files - OpenSearch documentation

Let me know if you have any questions or need help with ./securityadmin.sh

Best,
Mantas

I thought i had ran the securityadmin, but apparently missed that step.
I am testing the functionality now and so far seems to be working, thanks!

you are welcome, glad to help! keep me posted on your test results.

Interestingly i started by testing the _stats API… and even though i have only granted READ permission on 2 indexes, _stats is returning the information for all indexes, is that expected with those new options set in config.yml? shouldnt i only see the 2 indexes?

…same for _cat/indices

…and the _aliases API still requires that i grant indices:admin/aliases/get to all indexes (*)
…same thing for _mappings

Interesting, I’ll run some tests in my lab and share the results with you too.

Are there any similar OpenSearch APIs that will return similar information as GET _security/user/_privileges for Elasticsearch?

Hi @cdobbins ,

You can use: GET _plugins/_security/authinfo?pretty to figure out roles and privileges, but let me know if you want something more specific.

Best,
Mantas

Thanks Mantas, unfortunately that doesnt show me the indexes and what permissions i have on them.

Hi @cdobbins,

I do not know nor was I able to find anything that would return user privileges to indices. You could check the user’s roles with (authinfo) and retrieve index patterns from roles as a workaround GET _plugins/_security/api/roles/<role>.

Or you could file a feature request at OpenSearch Project · GitHub

Best,
Mantas

thanks, feature request has been logged: