How to use ldap realm for authorisation for SAML realm

Hi team,

I have ldap realm configured to allow access to elasticsearch APIs. I also have SAML configured for kibana.
Now I want to setup user authorisation in saml using ldap realm instead of api based role mapping. I read this in elastic documentation _;

If your users also exist in a repository that can be directly accessed by Elasticsearch (such as an LDAP directory) then you can use authorization realms instead of role mappings.

In this case, you perform the following steps: 1. In your SAML realm, assigned a SAML attribute to act as the lookup userid, by configuring the attributes.principal setting. 2. Create a new realm that can lookup users from your local repository (e.g. an ldap realm) 3. In your SAML realm, set authorization_realms to the name of the realm you created in step 2.

My configuration -

xpack.security.authc.realms.saml1:
type: saml
order: 2
idp.metadata.path: /usr/share/elasticsearch/config/saml/idp-metadata.xml
idp.entity_id: "mineSSO"
sp.entity_id: "{entity_id}"
sp.acs: "{acs}"
sp.logout: "{logout}"
attributes.principal: "nameid:persistent"
encryption.key: /usr/share/elasticsearch/config/saml-cert/tls.key
encryption.certificate: /usr/share/elasticsearch/config/saml-cert/tls.crt
xpack.security.authc.realms.ldap1:
type: ldap
order: 0
url: "ldap://corpds.mine.com:389"
user_dn_templates:
- "uid={0},ou=people,o=mine.com,o=email"
group_search:
base_dn: "ou=groups,o=mine.com,o=email"
filter: uniqueMember={0}
files:
role_mapping: /usr/share/elasticsearch/config/role_mapping.yml
unmapped_groups_as_roles: false

role_mapping.yml: |
click_admins:
- "cn=GBI APC Infra,ou=groups,o=mine.com,o=email"
- "uid=rgujral,ou=people,o=mine.com,o=email"
roles.yml: |
click_admins:
run_as: [ 'clicks_watcher_1' ]
cluster: [ 'monitor' ]
indices:
- names: [ 'events-*' ]
privileges: [ 'read' ]
field_security:
grant: ['category', '@timestamp', 'message' ]
query: '{"match": {"category": "click"}}'

So I know I have to add authorisation_realms: ldap1 under saml realm but what should be the value for attributes.principal ?

attributes.principal needs to specify a SAML attribute (or nameid) that matches exactly with the userid you use in LDAP.
That is, something that your SAML IdP sends to ES that we can substitute into uid={0},ou=people,o=mine.com,o=email in order to get the correct DN for the LDAP bind.

Without knowing what your SAML setup looks like, I can't give you any more details than that.

@TimV , my saml setup is below -

xpack.security.authc.realms.saml1:
      type: saml
      order: 2
      idp.metadata.path: /usr/share/elasticsearch/config/saml/idp-metadata.xml
      idp.entity_id: "IDPSSO"
      sp.entity_id: "{entity_id}"
      sp.acs: "{acs}"
      sp.logout: "{logout}"
      attributes.principal: "nameid:persistent"
      encryption.key: /usr/share/elasticsearch/config/saml-cert/tls.key
      encryption.certificate: /usr/share/elasticsearch/config/saml-cert/tls.crt 

IDP supplies username in the form "anyname@mine.com"
I can map users by below mapping-

_security/role_mapping/saml-kibana-rajesh" -H 'Content-Type: application/json' -d'

{

"roles": [ "superuser" ],

"enabled": true,

"rules": { "all": [

{ "field": { "realm.name": "saml1" } },

{ "field": { "username": "jack_thomas@mine.com" } }

]}

}’

How can I provide the same in attributes.principal ?

I'm sorry, I don't understand the question.

You said you want to configure your SAML realm to delegate authorization to the LDAP realm. to do that you need to have an exact match in userids.

Does your SAML IdP provide something that you can match to the uid in your LDAP realm?

Look for a line that says:

The SAML Assertion contained the following attributes:

You have mentioned that you want to delegate the authorization to the LDAP realm. As Tim already explainer earlier: In order to do that, you need to configure attributes.principal to be the SAML Attribute that contains the value that is the user's uid in LDAP. So from all the SAML attributes that your IDP is sending and you need to determine which one has a value that corresponds to the value of the uid Attribute in LDAP.

Please do not share any SAML role mappings as these are irrelevant to the above and only complicate the discussion without adding any benefit. You have said that you want to do delegation in the LDAP realm ( == NOT in the SAML realm) , so -once the issue above is fixed- you would need to create role mappings that use information from the LDAP realm (see here for more information), and not the SAML one.


Slightly unrelated to the above discussion: Are you certain you need to delegate authorization to an LDAP realm ? It looks like that the SAML IDP uses this same LDAP to authenticate the users and it also gets their group memberships and releases this information within the SAML Assertion as the groups attribute. Why not use the value of groups attribute from SAML and SAML Role mappings to assign roles to your users instead of doing an extra call to your LDAP (by using the LDAP realm as an authorization realm ) in order to get the group membership information that you already have ?

@ikakavas Yes I'm considering value of groups attribute to do role mappings for SAML. I have followed this
https://www.elastic.co/guide/en/elastic-stack-overview/6.7/saml-role-mapping.html

I'm able to do mappings with username but not with groups.
The below works-

PUT _security/role_mapping/saml-kibana' -H 'Content-Type: application/json' -d'
{
"roles": [ "events-admin" ],
"enabled": true,
"rules": { "all": [
{ "field": { "realm.name": "saml1" } },
{ "field": { "username": "rgujral@apple.com" } }
]}
}'

But not when I try to map group for accessing saml (already mapped in IDP)

PUT _security/role_mapping/saml-kibana-group" -H 'Content-Type: application/json' -d'
{
"roles": [ "superuser" ],
"enabled": true,
"rules": { "all": [
{ "field": { "realm.name": "saml1" } },
{ "field": { "groups": "10606723" } }
] 
} 
}'

Please take the time to correctly format your posts. It greatly helps people that try to assist you. You can use the preview panel on the right to make sure your post looks fine. It would be great if you can fix that for your previous post.

Also do take the time to explain what you want to achieve, so that we can help you do that. Judging from what you said above, is it safe to assume that you don't want to use LDAP as an authorization realm anymore, and we should focus on getting your saml role mappings right ?

Finally, please do provider all the information you are asked to provide in previous answers. This will minimize the number of posts all of us have to write and eventually help you resolve your issues quickly. I Asked you above:

Did you do that ? What is this output? Can you share the logs with us ?

I'm not seeing anything that corresponds to attributes in elasticsearch logs, I'm only getting assertions and responses

I know I should get some string which shows attributes but I'm not getting. Is this because I have enabled encryption ?

No, as you can imagine we need to decrypt the assertion in order to consume it, so we get access to the attributes.

I can't understand how this happens, as we do print them in TRACE level. If you can't find them, can you at least copy paste here the part of your logs where the SAML authentication happens?

p.s. your post above is still not correctly formatted :slight_smile: Please fix that.

You should be looking for a line that starts with The SAML Assertion contained the following attributes: . What you have shared is you looking for the string response.

tail -f es-coordinating.log |grep -i "attributes"

  <saml:AttributeStatement>
  </saml:AttributeStatement>
[2019-06-11T17:12:37,768][TRACE][o.e.x.s.a.s.SamlAuthenticator] [es-coordinating-1] SAML AttributeStatement has [5] attributes and [0] encrypted attributes
[2019-06-11T17:12:37,770][TRACE][o.e.x.s.a.s.SamlAuthenticator] [es-coordinating-1] The SAML Assertion contained the following attributes: 
[2019-06-11T17:12:37,771][DEBUG][o.e.x.s.a.s.SamlRealm    ] [es-coordinating-1] Parsed token [SamlToken{3c73616d6c703a526573706f6e73652044657374696e6174696f6e3d2268747470733a2f2f6762696f627365727665722d6576656e74732d6465762e636f7270...}] to attributes [SamlAttributes(NameId(urn:oasis:names:tc:SAML:2.0:nameid-format:persistent)=rgujral@apple.com)[A40c6a056-1c32-49e8-90b8-ae87585290f7]{[Email=[rgujral@apple.com], FirstName=[Rohit], LastName=[Gujral], ADSID=[001333-04-7c6572cc-78ce-4312-add7-43a5df78a12d], Groups=[10606723,10182173,10447632,10589740,1002775869]]}]

So I'm mapped to a group 10606723. but when I map it for saml via API, I don't get access to kibana

PUT. _security/role_mapping/saml-kibana-group" -H 'Content-Type: application/json' -d'

{

"roles": [ "superuser" ],

"enabled": true,

"rules": { "all": [

{ "field": { "realm.name": "saml1" } },

{ "field": { "Groups": "10606723" } }

]

}

}'

As you can also find in our documentation you need to map the saml attribute to the relevant user property in elasticsearch and then use that property in your role mappings. More concretely you need to add

attributes.groups: Groups

to your saml realm configuration in elasticsearch.yml and then change your role mapping rule to

{ "field": { "groups": "10606723" } }

attributes.groups: Groups or attributes.groups: groups

for the reasons I explained in my previous post

enable the role mapping TRACE logging

PUT /_cluster/settings
{
  "transient": {
    "logger.org.elasticsearch.xpack.security.authc.support.mapper": "trace"
  }
} 

try to login again and look into (or share for us to look) your elasticsearch logs. The reason you are not getting authorized will be evident there. If you do select to share your logs, please do not use tail and grep as this will output only one line from the log entry and we need to see all of it. Grab the part of logs that is relevant to this troubleshooting and copy paste it here (using the proper formatting )

Can you also share how the relevant part to Groups within the

<saml:AttributeStatement>


</saml:AttributeStatement>

part looks like in your logs ?

It would have been a little bit easier to help if you could provide all the information that we asked for instead of just a part of it.

<saml:Attribute Name="Groups"> 
   <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                                        xsi:type="xs:string">
       10606723,10182173,10447632,10589740,1002775869
    </saml:AttributeValue> 
</saml:Attribute>

The problem is the above. Your IDP is sending all your groups in a comma separated string. The usual way to send multivalued attributes in SAML is to have multiple <AttributeValue> elements. So we would expect to get:

<saml:Attribute Name="Groups"> 
   <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                                        xsi:type="xs:string">10606723</saml:AttributeValue> 
  <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                                        xsi:type="xs:string">10182173</saml:AttributeValue> 
  <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                                        xsi:type="xs:string">10447632</saml:AttributeValue> 
  <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                                        xsi:type="xs:string">10589740</saml:AttributeValue> 
  <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                                        xsi:type="xs:string">1002775869</saml:AttributeValue>
</saml:Attribute>

and we would then parse that into an array of Strings, one for each group.

What happens now is that we parse only 1 string with the value 10606723,10182173,10447632,10589740,1002775869 and this is why the rule

{ "field": { "groups": "10606723" } }

is not matching. This would be obvious in the logs I asked if you could share with us above.

Now, your only solution as is, is to use a lucene regexp to match the value, as we describe here. Try replacing

{ "field": { "groups": "10606723" } }

with

{ "field": { "groups": "/.*10606723.*/" } }

@ikakavas. yes the regex did work for me and I told IDP to not send all drops in comma separated string.

 <saml:Attribute Name="Groups">
              
      <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">10606723</saml:AttributeValue>
              
      <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">10182173</saml:AttributeValue>
              
      <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">10447632</saml:AttributeValue>
              
            
    </saml:Attribute> 

Thanks a lot for ur help

Glad you sorted this out. If you get the IDP to start sending you the groups one per AttributeValue instead of a comma separated string, then you can go back and change

{ "field": { "groups": "/.*10606723.*/" } }

to

{ "field": { "groups": "10606723" } }

so that you don't unnecessarily use a regex

yes I'm using { "field": { "groups": "10606723" } }

As IDP has configured groups one per attribute value

1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.