Roles from roles_mapping are ignored

Versions (relevant - OpenSearch/Dashboard/Server OS/Browser):
OpenSearch 2.11.1

Describe the issue:
Good afternoon. Please help me figure out the problem of defining roles in OpenSearch. I tried to set up OpenSearch stack integration with Active Directori. Configured authentication and authorization via LDAP in the cohfig.yml file. Divided AD users into two groups: administrators with the admin_AD role and users with readall_AD rights. I created the roles in the roles_mapping.yml file. But when authorizing through the Opensearch Dashboards web interface, AD roles are used, and not those that I wrote in roles_mapping.yml. Is this the reason for my error?

Configuration:
file configuration roles_mapping.yml:

admin_AD:
  reserved: false
  backend_roles:
  - "GISAP Admins"
readall_AD:
  reserved: false
  backend_roles:
  - "ORIS"

file configuration config.yml :

      ldap:
        description: "Authenticate via LDAP or Active Directory"
        # http_enabled: false
        http_enabled: true
        transport_enabled: false
        order: 5
        http_authenticator:
          type: basic
          challenge: false
        authentication_backend:
          # LDAP authentication backend (authenticate users against a LDAP or Active Directory)
          type: ldap
          config:
            # enable ldaps
            enable_ssl: false
            # enable start tls, enable_ssl should be false
            enable_start_tls: false
            # send client certificate
            enable_ssl_client_auth: false
            # Π΄ΠΎΠ±Π°Π²ΠΈΠ» ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ Ρ€Π΅Ρ„Π΅Ρ€Π°Π»ΡŒΠ½Ρ‹Π΅ ссылки
            # enable_referrals: false
            # verify ldap hostname
            verify_hostnames: true
            hosts:
            - dc.firm-august.ru:389
            - dc2.firm-august.ru:389
            bind_dn: 'CN=elasticsearchuser,OU=GISAP,OU=!Π‘Π»ΡƒΠΆΠ΅Π±Π½Ρ‹Π΅ Аккаунты,DC=firm-august,DC=ru'
            password: 'XXXXX'
            # userbase: 'OU=Π”Π΅ΠΏΠ°Ρ€Ρ‚Π°ΠΌΠ΅Π½Ρ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½Ρ‹Ρ… Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ,OU=ДирСкция ΠΏΠΎ стратСгичСскому Ρ€Π°Π·Π²ΠΈΡ‚ΠΈΡŽ ΠΈ измСнСниям,OU=Departments,DC=firm-august,DC=ru'
            # Filter to search for users (currently in the whole subtree beneath userbase)
            # {0} is substituted with the username
            # usersearch: '(sAMAccountName={0})'
            # Use this attribute from the user as username (if not set then DN is used)
            username_attribute: 'cn'
            users:
              primary-userbase:
                base: 'OU=Departments,DC=firm-august,DC=ru'
                search: '(sAMAccountName={0})'
              secondary-userbase:
                base: 'OU=!АдминистративныС Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Ρ‹,OU=!Π‘Π»ΡƒΠΆΠ΅Π±Π½Ρ‹Π΅ Аккаунты,DC=firm-august,DC=ru'
                search: '(sAMAccountName={0})'
    authz:
      roles_from_myldap:
        description: "Authorize via LDAP or Active Directory"
        http_enabled: false
        transport_enabled: false
        authorization_backend:
          # LDAP authorization backend (gather roles from a LDAP or Active Directory, you have to configure the above LDAP authentication backend settings too)
          type: ldap
          config:
            # enable ldaps
            enable_ssl: false
            # enable start tls, enable_ssl should be false
            enable_start_tls: false
            # send client certificate
            enable_ssl_client_auth: false
            # verify ldap hostname
            verify_hostnames: true
            hosts:
            - dc.firm-august.ru:389
            - dc2.firm-august.ru:389
            bind_dn: 'CN=elasticsearchuser,OU=GISAP,OU=!Π‘Π»ΡƒΠΆΠ΅Π±Π½Ρ‹Π΅ Аккаунты,DC=firm-august,DC=ru'
            password: 'XXXXX'
            rolebase: 'OU=!Groups,DC=firm-august,DC=ru'
            # Filter to search for roles (currently in the whole subtree beneath rolebase)
            # {0} is substituted with the DN of the user
            # {1} is substituted with the username
            # {2} is substituted with an attribute value from user's directory entry, of the authenticated user. Use userroleattribute to specify the name of the attribute
            rolesearch: '(member={0})'
            # Specify the name of the attribute which value should be substituted with {2} above
            userroleattribute: '(sAMAccountName={0})'
            # Roles as an attribute of the user entry
            userrolename: 'memberOf'
            # The attribute in a role entry containing the name of that role, Default is "name".
            # Can also be "dn" to use the full DN as rolename.
            rolename: 'cn'
            # Resolve nested roles transitive (roles which are members of other roles and so on ...)
            resolve_nested_roles: true
            users:
              primary-userbase:
                base: 'OU=Departments,DC=firm-august,DC=ru'
                search: '(sAMAccountName={0})'
              secondary-userbase:
                base: 'OU=!АдминистративныС Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Ρ‹,OU=!Π‘Π»ΡƒΠΆΠ΅Π±Π½Ρ‹Π΅ Аккаунты,DC=firm-august,DC=ru'
                search: '(sAMAccountName={0})'
            skip_users:
             - 'kibanaserver'
             - 'logstash'
             - 'admin'
            #  - 'cn=Michael Jackson,ou*people,o=TEST'
            #  - '/\S*/'

Relevant Logs or Screenshots:

Hi @Pan-Vad,

Have you applied your changes in roles_mapping.yml with securityadmin.sh ?

Could you please share output of:

curl --insecure -u <admin_username>:<admin_password> -XGET https://<OS_node>:9200/_plugins/_security/api/rolesmapping?pretty

curl --insecure -u <ldap_user>:<ldap_password> -XGET https://<OS_node>:9200/_plugins/_security/authinfo?pretty

Thanks,
mj

Yes I used this script: cd /etc/opensearch/ &&
export OPENSEARCH_JAVA_HOME=/usr/share/opensearch/jdk/ &&
cd /usr/share/opensearch/plugins/opensearch-security/tools &&
./securityadmin.sh -cd /etc/opensearch/opensearch-security/ -icl -nhnv -cacert /etc/opensearch/root-ca.pem -cert /etc/opensearch/opensearchadmin.pem -key /etc/opensearch/opensearchadmin-key.pem -h sapinftstosn02.avgust.com

Output of the first command:

{
  "manage_snapshots" : {
    "hosts" : [ ],
    "users" : [ ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [
      "snapshotrestore"
    ],
    "and_backend_roles" : [ ]
  },
  "logstash" : {
    "hosts" : [ ],
    "users" : [ ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [
      "logstash"
    ],
    "and_backend_roles" : [ ]
  },
  "own_index" : {
    "hosts" : [ ],
    "users" : [
      "*"
    ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [ ],
    "and_backend_roles" : [ ],
    "description" : "Allow full access to an index named like the username"
  },
  "kibana_user" : {
    "hosts" : [ ],
    "users" : [ ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [
      "kibanauser"
    ],
    "and_backend_roles" : [ ],
    "description" : "Maps kibanauser to kibana_user"
  },
  "readall_AD" : {
    "hosts" : [ ],
    "users" : [ ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [
      "ΠžΡ‚Π΄Π΅Π» развития ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΎΠ½Π½Ρ‹Ρ… систСм"
    ],
    "and_backend_roles" : [ ]
  },
  "all_access" : {
    "hosts" : [ ],
    "users" : [ ],
    "reserved" : true,
    "hidden" : false,
    "backend_roles" : [
      "admin"
    ],
    "and_backend_roles" : [ ],
    "description" : "Maps admin to all_access"
  },
  "readall" : {
    "hosts" : [ ],
    "users" : [ ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [
      "readall"
    ],
    "and_backend_roles" : [ ]
  },
  "kibana_server" : {
    "hosts" : [ ],
    "users" : [
      "kibanaserver"
    ],
    "reserved" : true,
    "hidden" : false,
    "backend_roles" : [ ],
    "and_backend_roles" : [ ]
  },
  "admin_AD" : {
    "hosts" : [ ],
    "users" : [ ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [
      "GISAP Admins"
    ],
    "and_backend_roles" : [ ]
  }
}

Output of the second command:

{
  "user" : "User [name=yukhnovskiyadm, backend_roles=[], requestedTenant=null]",
  "user_name" : "yukhnovskiyadm",
  "user_requested_tenant" : null,
  "remote_address" : "192.168.20.41:44075",
  "backend_roles" : [ ],
  "custom_attribute_names" : [
    "attr.ldap.primaryGroupID",
    "attr.ldap.msTSExpireDate",
    "attr.ldap.lastLogon",
    "attr.ldap.logonCount",
    "attr.ldap.badPwdCount",
    "attr.ldap.objectGUID",
    "attr.ldap.userAccountControl",
    "attr.ldap.msTSLicenseVersion3",
    "attr.ldap.msTSLicenseVersion2",
    "attr.ldap.whenCreated",
    "ldap.original.username",
    "attr.ldap.lastLogoff",
    "attr.ldap.countryCode",
    "attr.ldap.instanceType",
    "attr.ldap.sAMAccountName",
    "attr.ldap.msTSManagingLS",
    "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.dSCorePropagationData",
    "attr.ldap.lockoutTime",
    "attr.ldap.name",
    "attr.ldap.uSNCreated",
    "attr.ldap.uSNChanged",
    "attr.ldap.displayName",
    "attr.ldap.objectSid",
    "attr.ldap.codePage",
    "attr.ldap.pwdLastSet",
    "attr.ldap.adminCount",
    "attr.ldap.msTSLicenseVersion",
    "attr.ldap.lastLogonTimestamp"
  ],
  "roles" : [
    "own_index"
  ],
  "tenants" : {
    "yukhnovskiyadm" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}

@Pan-Vad, I see you are mapping your roles via β€œbackend_roles”, but I do not see your β€œbackend_roles” passed to the LDAP user:

Could you please share the output of:

curl --insecure -u <admin_username>:<admin_password> -XGET https://<OS_node>:9200/_plugins/_security/api/securityconfig?pretty

Please use β€œPreformatted text (Ctrl + e)” or
image

Thanks,
mj

Yes, I myself don’t understand why this happens, maybe you can help me figure it out.

{
  "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" : true,
          "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" : [
                "dc.firm-august.ru:389",
                "dc2.firm-august.ru:389"
              ],
              "bind_dn" : "CN=elasticsearchuser,OU=GISAP,OU=!Π‘Π»ΡƒΠΆΠ΅Π±Π½Ρ‹Π΅ Аккаунты,DC=firm-august,DC=ru",
              "password" : "XXXX",
              "username_attribute" : "cn",
              "users" : {
                "primary-userbase" : {
                  "base" : "OU=Departments,DC=firm-august,DC=ru",
                  "search" : "(sAMAccountName={0})"
                },
                "secondary-userbase" : {
                  "base" : "OU=!АдминистративныС Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Ρ‹,OU=!Π‘Π»ΡƒΠΆΠ΅Π±Π½Ρ‹Π΅ Аккаунты,DC=firm-august,DC=ru",
                  "search" : "(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" : true,
          "transport_enabled" : false,
          "authorization_backend" : {
            "type" : "ldap",
            "config" : {
              "enable_ssl" : false,
              "enable_start_tls" : false,
              "enable_ssl_client_auth" : false,
              "verify_hostnames" : true,
              "hosts" : [
                "dc.firm-august.ru:389",
                "dc2.firm-august.ru:389"
              ],
              "bind_dn" : "CN=elasticsearchuser,OU=GISAP,OU=!Π‘Π»ΡƒΠΆΠ΅Π±Π½Ρ‹Π΅ Аккаунты,DC=firm-august,DC=ru",
              "password" : "XXXX",
              "rolebase" : "OU=!Groups,DC=firm-august,DC=ru",
              "rolesearch" : "(member={0})",
              "userroleattribute" : "(sAMAccountName={0})",
              "userrolename" : "memberOf",
              "rolename" : "cn",
              "resolve_nested_roles" : true,
              "users" : {
                "primary-userbase" : {
                  "base" : "OU=Departments,DC=firm-august,DC=ru",
                  "search" : "(sAMAccountName={0})"
                },
                "secondary-userbase" : {
                  "base" : "OU=!АдминистративныС Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Ρ‹,OU=!Π‘Π»ΡƒΠΆΠ΅Π±Π½Ρ‹Π΅ Аккаунты,DC=firm-august,DC=ru",
                  "search" : "(sAMAccountName={0})"
                }
              },
              "skip_users" : [
                "kibanaserver",
                "logstash",
                "admin"
              ]
            }
          },
          "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
    }
  }
}

@Pan-Vad, would you mind testing with (in your authz.roles_from_myldap section):


"rolesearch" : "memberOf"

and
"rolesearch" : "'(uid={0})'"

Best,
mj

Thank you. I have configured the setting
β€œrolesearch” : β€œβ€˜(uid={0})’”
After logging in through the web interface, I went to check the account role. β€œBackend roles” appeared. But I didn’t understand why the roles from AD were applied, and not from the configuration specified in the role_mapping.yml file

@Pan-Vad, It will show all the roles as backed_roles from your LDAP response, it will only map the ones as per roles_mapping.yml.

Best,
mj

I think I get the idea. Thank you very much

1 Like