These days I have been working in the configuration of a Kerberos environment for some databases using a windows 2008R2 forest as KDC. I know that I am not an expert in this matter but it seems that I was the best suited in this summer (vacation) time. Everytime I work with this technology I have the frustrating impression it is again my first time (always falling in the same errors and walking in circles, the same circles). This little entry is just for fixing in my faulted mind two tips I have learned (again) in this installation.
The Kerberos protocol is a recurring topic in the blog, if you do not remember, it is an authentication protocol based in cryptographic ticket granting and modeled in a client-server architecture. Microsoft added this technology to Active Directory and any user who logs in a windows AD domain receives a Kerberos ticket. Once the user has his valid ticket he can access any other service without re-authenticating again (Single SignOn / SSO). In order to do this, the service (the database in my case) should be configured to accept the Kerberos tickets. That configuration always has the following steps:
Creating a kerberos principal for the service (a user or account inside the AD that represents the service/application principal). This step is performed using the Active Directory Users and Computers snap-in in windows.
Associating the service name (Service Principal Name / SPN) with the previous account. This part can be done with the setspn windows command or the ktpass utility (the later mixes this and the following step).
Generating a keytab file, a file containing the Kerberos principal (SPN) and the encrypted key for this user. This file is needed by the service or application to validate the user. In windows this step is done using the previous ktpass utility.
Currently there are a lot of software that supports Kerberos as a valid authentication method (Application and Webs servers, Databases,...). This entry is a modest try to summarize two tips I have learned in this new adventure.
The crypto used in the keytab
The keytab generated for the SPN of the service uses a crypto algorithm. It seems that windows supports some of them (DES-CBC-CRC, DES-CBC-MD5, RC4-HMAC-NT, AES256-SHA1 and AES128-SHA1 but some of them, the old ones, are deprecated in newer versions of windows).
Depending the crypto passed to the ktpass command the user account should be modified accordingly. For example if the keytab is generated using DES-CBC-MD5 the user account should have the option Use kerberos DES encryption types for this account checked. But if RC4-HMAC-NT is used in the keytab generation the account should have this option unchecked. I have not tested AES cryptos but there are two more options (This accounts supports Kerberos AES 128 bit encryption and This accounts supports Kerberos AES 256 bit encryption) that may play a similar role.
If the account is not checked accordingly the service does not find a proper entry in the keytab (the account wants to use a DES key but only RC4 is in the keytab or vice-versa). After a lot of pain with this issue I realized (although it was not tested) that it is possible to use ALL as the crypto parameter in the ktpass command. This way the annoying keytab has all the damned cryptos and the service always finds the correct one.
This is an example of generating ALL the cryptos for a user account called ddbbuser assigning a SPN ddbb1/ddbb1.demo.test (a SPN is the fully qualified name of the host in which the service is running preceding by a service class, in the example the service is the database name):
ktpass -princ ddbb1/ddbb1.demo.test -mapuser ddbbuser -pass xxxxxx -crypto ALL -ptype KRB5_NT_PRINCIPAL -out all.keytab
Assigning several SPNs to the same account
The second tip that I want to backup here is the simple idea of using one account for several SPNs. Typically in a Kerberos configuration each service has a different user account, that account has associated the SPN of the service. But in my case I had hundreds of services and I wanted to use the same account for several services or SPNs. For example, imagine I have two databases (ddbb1 and ddbb2) which should be kerberized. The typical deployment would create two users (ddbb1user and ddbb2user) and would assign to each user the SPN of each database (ddbb1/ddbb1.demo.test and ddbb2/ddbb2.demo.test). Why not to use just one account and assign to it the two SPNs? For me it is a simple and beautiful idea that let me avoid the creation of hundreds of users (I can group several databases in one account).
I read a lot over the internet and everybody talked about limitations in ktpass to do this (each time the command is executed the kerberos number kvno is updated, and all the previous keytabs are invalidated). But finally this page gave me the clue to achieve this task. Let's continue with my previous example:
First both SPNs were assigned to the account (ktpass also performs this step but I prefer to be sure):
setspn -A ddbb1/ddbb1.demo.test ddbbuser
setspn -A ddbb2/ddbb2.demo.test ddbbuser
Then a ktpass is executed against the first SPN:
ktpass -princ ddbb1/ddbb1.demo.test@DEMO.TEST -mapuser ddbbuser -pass xxxxxx -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -out ddbb1.keytab
In this execution the password of the user is passed (you can use * for typing it without writing it in the command line) and no special options are used, so the kvno is incremented for the account.
Another ktpass is used for the second SPN but this time the command is executed using -setpass and -setupn, those options inform to not update the account password and the principal name respectively but the former has the collateral effect of not changing the kvno (previous keytab is still valid).
ktpass -princ ddbb2/ddbb2.demo.test@DEMO.TEST -mapuser ddbbuser -pass xxxxxx -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -out ddbb2.keytab -setupn -setpass
Now both keytab files can be distributed to each service machine and they are valid.
Another trick I discovered was adding the two SPNs inside the same file. This option is very useful when the service needs several SPNs for some reason.
The first SPN keytab is generated with a new kvno.
ktpass -princ ddbb1/ddbb1.demo.test@DEMO.TEST -mapuser ddbbuser -pass xxxxxx -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -out ddbb1.keytab -setupn
Then the second SPN is added without updating kvno (using -in option the second SPN is added to the first one and the resulting keytab file contains both SPNs). The command also needs the previous option (-setpass) to avoid the increment of the kvno and the invalidation of the previous keytab.
ktpass -princ ddbb2/ddbb2.demo.test@DEMO.TEST -mapuser ddbbuser -pass xxxxxx -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -in ddbb1.keytab -out ddbb1and2.keytab -setupn -setpass
Finally the ddbb1and2.keytab contains the two valid keytab entries for the two different SPN of the account.
With all these tests I finally understand what the hell a keytab file is. It is just a way of storing the password of the account (hashed using the specified cypher) but it has the kvno (the number of the keytab) as an extra security (only the last kvno is valid). So, if you know the password and the kvno of the account, you can generate as many keytabs as you want. And you can set whatever SPN inside the keytab file. For example if I know that my account ddbbuser is now using the kvno=5 the keytab file can be generated for my first SPN just like this:
$ ktutil
ktutil: addent -password -p ddbb1/ddbb1.demo.test@DEMO.TEST -k 5 -e RC4-HMAC
Password for ddbb1/ddbb1.demo.test@DEMO.TEST: xxxxxx
ktutil: wkt ddbb1.keytab
ktutil: q
The ktutil is the ktpass counterpart in linux (MIT implementation) but simpler, it does not mix concepts and just creates the keytab files. And I can do exactly the same for the second SPN or add both entries inside the same file. This way I can use the same account for as many SPNs as I want. I just need to add the SPN to the account (setspn) and then creating the keytab manually (no fucking ktpass anymore).
Obviously it has the disadvantage that the password of the account is known by the administrators. It seems that it is recommended to use the +rndpass option in the ktpass command, which assigns a random password to the account and keytab. But it limits one SPN per account, which I was trying to avoid.
I suppose that this entry is obvious for anyone who knows about Kerberos but I have spent a lot of time guessing this information. All the documentation I read is scarce and partial and nobody explains it in a clear way. Finally what drives me nuts is the fact that I have lived those problems in previous experiences, but Kerberos is so annoying and peculiar that you fall in the same mistakes again and again. That is why I decided to bring my notes into the blog. Let's see if the next time it is easier!
Regards!
Comments