NOTE I pulled this from a discussion in Slack on this same topic, saving it in Answers for posterity. Sorry about the poor formatting and run on sentences.
In AD (and other LDAP tools), both 'users' and 'group' are just objects with attributes. 'Groups' just happen to be objects that have "member" attributes and 'Users' don't. Splunk is relatively flexible about how it handles the mapping of LDAP objects to splunk roles. Take this setup right from the docs:
[ldaphost1]
host = ldaphost1.domain.com
port = 389
SSLEnabled = 0
bindDN = cn=bind_user
bindDNpassword = bind_user_password
groupBaseDN = ou=Groups,dc=splunk,dc=com
groupBaseFilter = (objectclass=*)
groupMappingAttribute = dn
groupMemberAttribute = uniqueMember
groupNameAttribute = cn
realNameAttribute = displayName
userBaseDN = ou=People,dc=splunk,dc=com
userBaseFilter = (objectclass=*)
userNameAttribute = uid
Notice the groupBaseDN is a different "subdirectory" of the LDAP tree ou=Groups from the userBaseDN in ou=People .
This is how most folks have their LDAP trees set up. When you put in a username and password, splunk uses its bind account to run an LDAP search for (&(objectclass=*)(uid=<username>)) inside of ou=People based on the values of userBaseDN , userBaseFilter and userNameAttribute .
If this returns a dn that matches (meaning it found you) it will attempt to BIND as that DN with the password you gave. If successful, you are authenticated.
Now, to find out what roles you have, it will use its bind account to do another search to map your roles but (again per the above config) it will search in ou=Groups for something matching (&(objectclass=*)(uniqueMember=<your_dn_found_before)) .
Whatever "groups" return from this final search, their value of cn (because of groupnameAttribute in the config file) will be matched against the roleMap for that LDAP strategy, and that is what you get in terms of Splunk roles.
Now let's compare that to a different example in the docs:
[supportLDAP]
SSLEnabled = 0
bindDN = cn=Directory Manager
bindDNpassword = #########
groupBaseDN = ou=People,dc=splunksupport,dc=com
groupBaseFilter = (objectclass=*)
groupMappingAttribute = uid
groupMemberAttribute = uid
groupNameAttribute = uid
host = supportldap.splunksupport.com
port = 389
realNameAttribute = cn
userBaseDN = ou=People,dc=splunksupport,dc=com
userBaseFilter = (objectclass=*)
userNameAttribute = uid
[roleMap_supportLDAP]
admin = rlee;bsmith
This is weird, but shows off the dynamism of splunk's ldap client. Here, both "users" and "groups" are pulled from ou=People . But looking at the group* settings what we've done is a hack to make "groups" reference "user" objects. The user login will go just like before .. search with the bind account, find you, bind with your dn and password . If successful, then we do the "group" by searching ou=People for someone where (&(objectclass=*)(uid=<your_uid>)) and use the uid value coming back from that in the roleMap lookup -- in effect making your "user" object look and feel like a "group" object.
To splunk it's "so I queried the part of the directory tree you told me to, using the parameters you gave me, and I got back results.
Whether the users are really users, the groups are really groups, or what, IDGAF" But, these two configurations are mutually exclusive.
You can easily configure splunk to map "groups" to splunk roles (see first config). You can easily configure splunk to map "users" to splunk roles (see second config). But, can you configure splunk to map "users" OR "groups" to splunk roles?
Taking advantage of the fact that LDAP allows multiple strategies and the first place a user is found is where they will get pulled from we can do something like this:
[authentication]
authType = LDAP
authSettings = ldaphost1-users, ldaphost1
[ldaphost1]
host = ldaphost1.domain.com
port = 389
SSLEnabled = 0
bindDN = cn=bind_user
bindDNpassword = bind_user_password
groupBaseDN = ou=Groups,dc=splunk,dc=com
groupBaseFilter = (objectclass=*)
groupMappingAttribute = dn
groupMemberAttribute = uniqueMember
groupNameAttribute = cn
realNameAttribute = displayName
userBaseDN = ou=People,dc=splunk,dc=com
userBaseFilter = (objectclass=*)
userNameAttribute = uid
[roleMap_ldaphost1]
user = Splunk_user_group
[ldaphost1-users]
host = ldaphost1.domain.com
port = 389
SSLEnabled = 0
bindDN = cn=bind_user
bindDNpassword = bind_user_password
groupBaseDN = ou=People,dc=splunk,dc=com
groupBaseFilter = (objectclass=*)
groupMappingAttribute = uid
groupMemberAttribute = uid
groupNameAttribute = uid
realNameAttribute = cn
userBaseDN = ou=People,dc=splunk,dc=com
userBaseFilter = (&(objectclass=*)(|(uid=rlee)(uid=bsmith))
userNameAttribute = uid
[roleMap_ldaphost1-users]
admin = rlee;bsmith
Notice these two "strategies" point to the same LDAP server, just queried in different ways -- same bind account and everything. When you have multiple LDAP "strategies" (stratagems?), then the first one to find a user is the one used. In this config I explictly search the ldaphost1-users strategy first, and have made it treat users and groups as basically identical objects (as shown in the docs link above) so that I can map user names to roles. But, I've nerfed the userBaseFilter in such a way that it will only ever find people who are mapped to a role below.
If you're not in the filter for the first strategy, then it falls through with "no user found", and goes to the second one that queries the same LDAP server -- but this time, it maps groups to roles and proceeds from there.
While this should work, this is terrible for the "users directly get a role case" because you have to both update the role map and the filter each time you want to add a user, and the filter will get unwieldy fast. Also there's another interesting side effect of this config -- if you map a user to a role in the ldaphost1-users stanza, then all of their role mappings must be done there. You can't "also include them in a group" and expect that to work.
... View more