Saturday, July 6, 2013

CCIE DC: (Sort of), LDAP Authentication to Active Directory on NX-OS

Hi Guys!

I tell you what, getting this up and running to show you guys was a heck of a challenge, This is certainly not as easy as it looks,  I had to piece things together from a variety of documents:

So. Let's describe what we actually want to do, then we will look at how to configure it.

SO i have an Active Directory server, I want to have my MDS Switch (MDS switch in this case as I was unable to access a 7k to test on, sorry guys!), to be able to authenticate via LDAP to this active directory server, and to retrieve it's role mapping and privileges from this active directory server.

OK, Let's get to it!

First of all, we need a few details to be able to do this easily, we need to know the DN of the base of our active directory server.

The easiest way to find that in AD is the adsiedit:


So we can tell the root of our tree is DC=ccierants,DC=com

Next, we need to create a user  that will be used to bind to the Active DIrectory, in this example we have called him ucsbind:


You can see from the screenshot below we have his full distingushed name, which is great because we will need that later :).


The next thing we need is our Base-DN that we will actually be searching from, which in our case will be all the users under CiscoUCS:

At this point we have all the following Info:

  • A base DN
  • a distingushed name for our binding user
  • a binding user password
  • the directory we will be searching for users from

 Let's start to look at some config.

feature ldap

First step as always is to enable the feature

Next, we define an LDAP server:

ldap-server host rootDN "CN=ucsbind,OU=CiscoUCS,DC=ccierants,DC=com"
password decrypted port 389 timeout 30

This defines our LDAP server, next we need to create our LDAP group:

aaa group server ldap Newldap
  ldap-search-map cisco

The search-map is a key bit of config, let me let you in on a secret: IF YOU DON'T HAVE A SEARCH MAP, THE GROUP IS NOT VALID AND WILL NOT BE USED.

So here is the config on the actual ldap search-map

ldap search-map cisco  userprofile attribute-name "description" search-filter "(cn=$userid)" base-DN "OU=CiscoUCS,DC=ccierants,DC=com"

The item highlighted in green is your attribute-field that is used for mapping a role to your user when they login, we will get back to that shortly, the item in red is your search filter, this is used so LDAP knows what user to look for, and then look at the "description" value for.

So now that you have all this configured, final step is to specify your AAA authentication method like your probably already used to:

MDS1(config)# aaa authentication login default group Newldap

THere is one final step we need to do in the actual Active Directory, and that is we need to specify what role this user should be allowed.

First, you need to know what roles are available before you can actually define a role, this can be done with:

MDS1# show role brief

Role: network-admin
Description: Predefined Network Admin group. This role cannot be modified
Access to all the switch commands

Role: network-operator
Description: Predefined Network Operator group. This role cannot be modified
Access to Show commands and selected Exec commands

Role: server-admin
  Description: Predefined system role for server administrators. This role
  cannot be modified.
  Vsan policy: permit (default)

Awesome! We have a list of predefined roles, we could obviously also create our own, next we need to update the description field (because remember, we set aside the description field as what we use in our LDAP map) to show that we want to have this role assigned to the user as they login, but note it MUST be in a special format:

Check out the info from the doco:

So! We need to define this, let's go to our description

Note the section highlighted in yellow (Incidentally, the tool I am using here is called Jxplorer and it's incredibly useful for troubleshooting LDAP connectivity)

Done! We can test the group, but as I test it i am also going to enable the VERY helpful debug so we can take a closer look:

MDS1# debug ldap aaa-request
MDS1# debug ldap aaa-request-lowlevel
MDS1# test aaa group Newldap ?
  WORD  User name (Max Size 32)

MDS1# test aaa group Newldap ucsbind password

2013 Jul  6 13:11:38.069576 ldap: mts_ldap_aaa_request_handler: user :ucsbind:, user_len 7, user_data_len 9
2013 Jul  6 13:11:38.069621 ldap: ldap_authenticate: user ucsbind servergroup Newldap
2013 Jul  6 13:11:38.069913 ldap: IN FUNCTION ldap_search_map.... for name cisco
2013 Jul  6 13:11:38.070486 ldap: ldap_client_auth_init: (user ucsbind) - ldap_init success for host port 389

This line is showing us the LDAP connection was succesful, and that it managed to find the group and find a server in the group, like I mentioned before, if you don't have an LDAP-Search-MAP in the group, you won't get anywhere as it won't even find the server

2013 Jul  6 13:11:38.344353 ldap: ldap_do_initial_bind: (user ucsbind rootDN CN=ucsbind,OU=CiscoUCS,DC=ccierants,DC=com ) - initiated bind for root
2013 Jul  6 13:11:38.619647 ldap: ldap_process_result: entering... for user ucsbind
2013 Jul  6 13:11:38.619689 ldap: ldap_process_result: ldap_result (user ucsbind) - bind
2013 Jul  6 13:11:38.620002 ldap: ldap_user_filter_substitute: filter string: (cn=$userid), out_filter_len = 12 

Here we can see that LDAP is using the filter string cn=$userid

2013 Jul  6 13:11:38.620046 ldap: ldap_do_search: (user ucsbind) search filter (cn=ucsbind)

The variable $userid is replaced with ucsbind (the user we are testing) in this line.

2013 Jul  6 13:11:38.620406 ldap: ldap_do_search: (user ucsbind) - initiated search
2013 Jul  6 13:11:38.893931 ldap: ldap_process_result: entering... for user ucsbind
2013 Jul  6 13:11:38.893974 ldap: ldap_process_result: ldap_result (user ucsbind) - in progress
2013 Jul  6 13:11:38.894625 ldap: ldap_handle_user_role_search_rsp: (user ucsbind) DN CN=ucsbind,OU=CiscoUCS,DC=ccierants,DC=com 

We have found the user.

2013 Jul  6 13:11:38.894745 ldap: attribute: description 

the attribute we are looking for is description, what's in the description?

2013 Jul  6 13:11:38.894862 ldap: value: shell:roles= network-admin
2013 Jul  6 13:11:38.894915 ldap: retrieve_user_profile: vsa_string: shell:roles= network-admin2013 Jul  6 13:11:38.894969 ldap: retrieve_user_profile: protocol shell
2013 Jul  6 13:11:38.895013 ldap: retrieve_user_profile: attribute roles 

Well well well, the attribute contains a VSA that Me, Mr MDS, understands!

2013 Jul  6 13:11:38.895055 ldap: extract_value: vsa_string:  network-admin
2013 Jul  6 13:11:38.895099 ldap: extract_value: no quote, extracted value: network-admin
2013 Jul  6 13:11:38.895141 ldap: extract_value: no quote, vsa_string after extraction:
2013 Jul  6 13:11:38.895181 ldap: retrieve_user_profile: extracted role value:network-admin:
2013 Jul  6 13:11:38.895228 ldap: ldap_parse_user_profile: roles after filter: network-admin

I extrat the term "network-admin" from this VSA and i know that there is a role called network-admin!

2013 Jul  6 13:11:38.895338 user has been authenticated

the user is authenticated!

That is the guts of it guys, the debug ldap commands are incredibly powerful, and the test commands are useful too.

Now if you have read this far let me tell you a couple of other things

First of all, the above is all fine, there is a command in the MDS Config:
 "aaa user default-role"

This is a default part of the config, and basically says that any user authenticated via LDAP will inherit all of the permissions of the default-role (which is a special system defined role) when the user log's into the MDS _IF_ the user doesn't have any attributes for permissions in there role for example.

User Access Verification
login: testucsuser
MDS1# conf t
Enter configuration commands, one per line.  End with CNTL/Z.
MDS1(config)# ?
  no        Negate a command or set its defaults
  username  Configure user information.
  end       Go to exec mode
  exit      Exit from command interpreter

As you can see, there is not exactly that many options available in the default role!

Finally, this all relates back to UCS, UCS uses a lot of this config to provide its authentication, the only thing that is not relevant is the group configuration, UCS uses memberof attributes to control this as per here:

Here is an example of a UCS configured with LDAP authentication:

sudcucst01-A(nxos)# show ldap-server 

     timeout : 30
        port : 0
      baseDN :
user profile attribute :
search filter :
  use groups : 0
recurse groups : 0
group attribute : memberOf
    group map CN=ucsadmin,OU=CiscoUCS,DC=ccierants,DC=com:
        roles: admin
total number of servers : 1

following LDAP servers are configured:
        timeout: 30    port: 389    rootDN: CN=ucsbind,OU=CiscoUCS,DC=ccierants,DC=com
        enable-ssl: false
        baseDN: dc=ccierants,dc=com
        user profile attribute:
        search filter: sAMAccountName=$userid
        use groups: true
        recurse groups: true
        group attribute: memberOf