Read Access to Indexes from Private Tenant for Externally Authenticated Users

Hello,
Apologies if this has been answered elsewhere, but I did not find anything that matched this scenario.

We are using OpenDistro 1.13.3 with ElasticSearch OSS 7.10.2

I have a scenario where I need to make indexes with naming pattern syslog* available to any externally authenticated user in their Private tenant space. The users are externally authenticated via Active Directory, and only have access to the Global Tenant and the Private Tenant. The intention is to have the Private Tenant used as a “sandbox” area for users to learn in or develop custom dashboards, prior to sharing them in the Global tenant.

Unfortunately, I cannot figure out from either the documentation or trial-and-error what needs to be done to make the syslog* indexes visible to the users in the Private Tenant. (I do know how to create a custom role, role mapping, and custom tenant, but this does not meet the requirements of my brief.)

Can someone shed some light on what needs to be done to allow externally authenticated (non-local) users read-only permissions to indexes other than “own-index” within the Private tenant space?

Thank you,

Jaimie Livingston

@jaimie.livingston
See custom role below:

testRole1:
  reserved: false
  hidden: false
  index_permissions:
  - index_patterns:
    - "syslog*"
    fls: []
    masked_fields: []
    allowed_actions:
    - "read"
  tenant_permissions: []
  static: false

If you map the external users to this role, together with kibana_user, they should have access to the private tenant and Global.

This was tested using Opensearch, but should work with ODFE the same way, please confirm.

Just to confirm, You will not be able to “Share” dashboards (or any other kibana objects) from one tenant to another, as they are treated separately.

@Anthony
Thank you for your answer. I’ve actually done that, but still am not able to access the index files or create any index patterns from the private tenant. In the config below “central-logging-users” is the active directory group.

Here is the role that I have defined:

{
  "pf_users" : {
    "reserved" : false,
    "hidden" : false,
    "cluster_permissions" : [
      "cluster_composite_ops_ro"
    ],
    "index_permissions" : [
      {
        "index_patterns" : [
          "*syslog*"
        ],
        "dls" : "",
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "search",
          "read"
        ]
      }
    ],
    "tenant_permissions" : [ ],
    "static" : false
  }
}

and here are the role mappings:

{
  "pf_users" : {
    "hosts" : [ ],
    "users" : [ ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [
      "central-logging-users",
      "kibana-user"
    ],
    "and_backend_roles" : [ ]
  }
}

I’m sure I’m missing something simple.

Any guidance will be appreciated.

Thanks,
Jaimie Livingston

@jaimie.livingston I think there might be a mix up with security roles vs backend roles.

Can you run the below with credentials for one of the users and post the result here:

curl --insecure -u {user}:{password} -XGET “http{s}://{opensearch}:9200/_opendistro/_security/authinfo?pretty”

@Anthony

Here 'tis. Thank you for spending time on this…

~Jaimie

$ curl -k -u joe.test:notthis -XGET "http{s}://10.xx.xx.xx:9200/_opendistro/_security/authinfo?pretty"
{
  "user" : "User [name=Joe Test, backend_roles=[central-logging-users], requestedTenant=null]",
  "user_name" : "Joe Test",
  "user_requested_tenant" : null,
  "remote_address" : "10.xx.xx.xx:50694",
  "backend_roles" : [
    "central-logging-users"
  ],
  "custom_attribute_names" : [
    "attr.ldap.primaryGroupID",
    "attr.ldap.lastLogon",
    "attr.ldap.logonCount",
    "attr.ldap.badPwdCount",
    "attr.ldap.objectGUID",
    "attr.ldap.userAccountControl",
    "attr.ldap.whenCreated",
    "ldap.original.username",
    "attr.ldap.lastLogoff",
    "attr.ldap.countryCode",
    "attr.ldap.instanceType",
    "attr.ldap.sAMAccountName",
    "attr.ldap.userPrincipalName",
    "attr.ldap.whenChanged",
    "attr.ldap.objectClass",
    "attr.ldap.givenName",
    "ldap.dn",
    "attr.ldap.sAMAccountType",
    "attr.ldap.cn",
    "attr.ldap.accountExpires",
    "attr.ldap.description",
    "attr.ldap.dSCorePropagationData",
    "attr.ldap.name",
    "attr.ldap.uSNCreated",
    "attr.ldap.uSNChanged",
    "attr.ldap.displayName",
    "attr.ldap.objectSid",
    "attr.ldap.codePage",
    "attr.ldap.pwdLastSet",
    "attr.ldap.sn",
    "attr.ldap.mail",
    "attr.ldap.lastLogonTimestamp"
  ],
  "roles" : [
    "own_index",
    "pf_users"
  ],
  "tenants" : {
    "Joe Test" : true,
    "pf_users" : false
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}

@jaimie.livingston Can you map to kibana_user instead of own_index, that’s just the way I have mine setup.

If this doesn’t help, can you answer the below, to get a better understanding of the issue:

What tenants do you have a choice of when you trick the user (top/right)?
Which way are you trying to create the index pattern?
Do you see any errors (either in GUI or the logs)?

@Anthony
I’m not sure. I do not appear to be able to do this directly in the kibana webui.
Is this done via an ldap attribute in config.yml, or roles.yml or somewhere else?

@jaimie.livingston You can map the kibana_user to all users, by selecting * under mapped users in GUI.
Or (in the same GUI) you can assign any backend_role that the users are receiving from ldap.
Hope this helps

@Anthony
I’ve done that, and I still can’t load or create any index or index pattern in the Private Tenant.

Since I’m unable to directly edit the reserved kibana_user and own_index roles, I duplicated and combined the two into a single kibana_user_enhanced role, and have mapped it to the AD group “central-logging-users”, then added an index permission set for *syslog* indexes.

Still, when I try to browse the indexes as a basic user (Joe Test) in the Private tenant (the only tenant available to this class of user), I get the following security exception for indices:monitor/settings/get even though the permission is part of the permissions for *syslog* index patterns, via the pf_indices_monitor_all action group.

[security_exception] no permissions for [indices:monitor/settings/get] and User [name=Joe Test, backend_roles=[central-logging-users], requestedTenant=__user__]

I’ve included the users auth, the kibana_user_enhanced role, and the actions groups used below the signature. Perhaps you’ll see something that I’ve missed.

In any case, thank you for your help on this. I know time is valuable.

Jaimie Livingston

#####

GET _opendistro/_security/authinfo/ for Joe Test

{
  "user" : "User [name=Joe Test, backend_roles=[central-logging-users], requestedTenant=__user__]",
  "user_name" : "Joe Test",
  "user_requested_tenant" : "__user__",
  "remote_address" : "10.xx.xx.xx:57384",
  "backend_roles" : [
    "central-logging-users"
  ],
  "custom_attribute_names" : [
    "attr.ldap.primaryGroupID",
<snip>
    "attr.ldap.lastLogonTimestamp"
  ],
  "roles" : [
    "kibana_user_enhanced"
  ],
  "tenants" : {
    "Joe Test" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}

#####

GET _opendistro/_security/api/roles/kibana_user_enhanced

{
  "kibana_user_enhanced" : {
    "reserved" : false,
    "hidden" : false,
    "cluster_permissions" : [
      "cluster_composite_ops",
      "cluster_monitor",
      "read"
    ],
    "index_permissions" : [
      {
        "index_patterns" : [
          ".kibana",
          ".kibana-6",
          ".kibana_*"
        ],
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "read",
          "delete",
          "manage",
          "index"
        ]
      },
      {
        "index_patterns" : [
          ".tasks",
          ".management-beats",
          "*:.tasks",
          "*:.management-beats"
        ],
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "indices_all"
        ]
      },
      {
        "index_patterns" : [
          "*syslog*"
        ],
        "dls" : "",
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "pf_indices_monitor_all",
          "pf_indices_data_read_all",
          "pf_indices_admin_get"
        ]
      },
      {
        "index_patterns" : [
          "${user_name}"
        ],
        "dls" : "",
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "indices_all"
        ]
      }
    ],
    "tenant_permissions" : [ ],
    "static" : false
  }
}


#####

GET _opendistro/_security/api/actiongroups/pf_indices_data_read_all

{
  "pf_indices_data_read_all" : {
    "reserved" : false,
    "hidden" : false,
    "allowed_actions" : [
      "indices:data/read/explain",
      "indices:data/read/field_caps",
      "indices:data/read/field_caps*",
      "indices:data/read/get",
      "indices:data/read/mget",
      "indices:data/read/mget*",
      "indices:data/read/msearch",
      "indices:data/read/msearch/template",
      "indices:data/read/mtv",
      "indices:data/read/mtv*",
      "indices:data/read/scroll",
      "indices:data/read/scroll/clear",
      "indices:data/read/search",
      "indices:data/read/search*",
      "indices:data/read/search/template",
      "indices:data/read/tv"
    ],
    "static" : false
  }
}

#####

GET _opendistro/_security/api/actiongroups/pf_indices_monitor_all

{
  "pf_indices_monitor_all" : {
    "reserved" : false,
    "hidden" : false,
    "allowed_actions" : [
      "indices:monitor/recovery",
      "indices:monitor/segments",
      "indices:monitor/settings/get",
      "indices:monitor/shard_stores",
      "indices:monitor/stats",
      "indices:monitor/upgrade"
    ],
    "static" : false
  }
}


#####

GET _opendistro/_security/api/actiongroups/pf_indices_admin_get

{
  "pf_indices_admin_get" : {
    "reserved" : false,
    "hidden" : false,
    "allowed_actions" : [
      "indices:admin/aliases",
      "indices:admin/aliases/exists",
      "indices:admin/aliases/get",
      "indices:admin/analyze",
      "indices:admin/exists",
      "indices:admin/get",
      "indices:admin/mappings/fields/get",
      "indices:admin/mappings/fields/get*",
      "indices:admin/mappings/get",
      "indices:admin/open",
      "indices:admin/shards/search_shards",
      "indices:admin/template/get",
      "indices:admin/types/exists",
      "indices:admin/validate/query"
    ],
    "static" : false
  }
}


I had a similar scenario, we have achieved it through the following steps:

  1. Create a custom role with the following cluster permission:
  • kibana_all_write
  • cluster_composite_ops_ro
  • indices:data/write/bulk*
  • cluster:admin/opendistro/reports/definition/list
  • cluster:admin/opendistro/reports/definition/list
  • cluster:admin/opendistro/reports/instance/list
  • cluster:admin/opendistro/reports/instance/get
  • cluster:admin/opendistro/reports/definition/create
  • cluster:admin/opendistro/reports/definition/update
  • cluster:admin/opendistro/reports/definition/on_demand
  • cluster:admin/opendistro/reports/definition/delete
  • cluster:admin/opendistro/reports/definition/get
  • cluster:admin/opendistro/reports/menu/download
  • cluster:admin/opendistro/alerting/alerts/get
  • cluster:admin/opendistro/alerting/alerts/ack
  • cluster:admin/opendistro/alerting/monitor/write
  • cluster:admin/opendistro/alerting/monitor/delete
  • cluster:admin/opendistro/alerting/monitor/execute
  • cluster:admin/opendistro/alerting/monitor/get
  • cluster:admin/opendistro/alerting/monitor/search
  • cluster:admin/opendistro/alerting/destination/get
  • cluster:admin/opendistro/alerting/destination/write
  • cluster:admin/opendistro/alerting/destination/delete
  • cluster:admin/opendistro/alerting/destination/email_account/delete
  • cluster:admin/opendistro/alerting/destination/email_account/get
  • cluster:admin/opendistro/ad/detector/search
  • cluster:admin/opendistro/ad/detector/delete
  • cluster:admin/opendistro/ad/detector/info
  • cluster:admin/opendistro/ad/detector/jobmanagement
  • cluster:admin/opendistro/ad/detector/preview
  • cluster:admin/opendistro/ad/detector/run
  • cluster:admin/opendistro/ad/detector/stats
  • cluster:admin/opendistro/ad/detector/write
  • cluster:admin/opendistro/ad/result/search
    you can remove the permissions according to your case.

Assing the following to Index permissions:

  • index: syslog*
  • Index Permission: read
  1. Map the users to the custom role you created above, preferred to map the user group coming from AD as backend role mapping.
  2. Create a custom tenant.
  3. Assign the custom role permission to the custom tenant with Read/Write permission.

When the user loggin, he will be mapped to the custom role and tenant, he will be on the private tenant by default, he can swith to the custom tenant to perform what is required.

Thanks
Hassan

@jaimie.livingston It is a known bug that duplicating kibana_user role doesn’t actually provide the same permissions under the hood. It would appears as though this role is hard-coded somewhere.

Is there any reason you can’t map this role to all uses, even for testing purposes?

@Anthony
Mapping “*” to kibana_user had no positive effect. The users still cannot view existing indexes or create index patterns inside of the Private tenant. The error is consistent:

[security_exception] no permissions for [indices:monitor/settings/get] and User [name=Joe Test, backend_roles=[central-logging-users], requestedTenant=__user__]

I’m beginning to believe that my desire to limit some users to only their Private tenant space, and be able to use an existing set of indexes/index patterns is simply not possible with the version of ODFE I have installed.

I’ve included the config output below for the users auth, the kibana_user role, and the kibana_user mapping.

Thank you again for your time.
~Jaimie

#####

GET _opendistro/_security/authinfo/ for joe.test

{
  "user" : "User [name=Joe Test, backend_roles=[central-logging-users], requestedTenant=__user__]",
  "user_name" : "Joe Test",
  "user_requested_tenant" : "__user__",
  "remote_address" : "10.xx.xx.xx:53884",
  "backend_roles" : [
    "central-logging-users"
  ],
  "custom_attribute_names" : [
    "attr.ldap.primaryGroupID",
<snip>
    "attr.ldap.lastLogonTimestamp"
  ],
  "roles" : [
    "kibana_user"
  ],
  "tenants" : {
    "Joe Test" : true,
    "global_tenant" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}

#####

GET _opendistro/_security/api/roles/kibana_user

{
  "kibana_user" : {
    "reserved" : true,
    "hidden" : false,
    "description" : "Provide the minimum permissions for a kibana user",
    "cluster_permissions" : [
      "cluster_composite_ops"
    ],
    "index_permissions" : [
      {
        "index_patterns" : [
          ".kibana",
          ".kibana-6",
          ".kibana_*"
        ],
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "read",
          "delete",
          "manage",
          "index"
        ]
      },
      {
        "index_patterns" : [
          ".tasks",
          ".management-beats",
          "*:.tasks",
          "*:.management-beats"
        ],
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "indices_all"
        ]
      }
    ],
    "tenant_permissions" : [ ],
    "static" : true
  }
}



#####

GET _opendistro/_security/api/rolesmapping/kibana_user

{
  "kibana_user" : {
    "hosts" : [ ],
    "users" : [
      "*"
    ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [
      "kibanauser",
      "central-logging-users"
    ],
    "and_backend_roles" : [ ]
  }
}

@jaimie.livingston please note in the above output you are mapping the user to only kibana_user:

 "roles" : [
    "kibana_user"
  ]

Which is of course not giving the user necessary permissions.