NetScaler – OTP Encryption Tool

Reading Time: 3 minutes

Table of Contents

Overview

Recently the internal Public Key Infrastructure (PKI) at one of my customers will change in a few weeks, with new private keys, too.

What does that mean regarding my encrypted NetScaler Native OTP Attributes? You have to re-encrypt (decrypt following by encrypt) all of your users OTP Active Directory Attributes so the NetScaler further is able to read and write the attributes for successful OTP-Authentication. The other option is to let all Users create new Tokens by themself – quite a bad idea, isn’t it?

There’s already a description at Citrix Docs, I just want to give some missing details in this post.

Configuration

As already mentioned in the Citrix docs, don’t install python and pip3 on your NetScaler. I used my MacBook or any other Linux OS to connect to your Domain Controller (connection to your NetScaler isn’t necessary, you directly talk to your Active Directory) for running the script against to.

It’s important to copy the OTP Encryption Tool (located at \var\netscaler\otptool) from a latest 13.1 Build, older ones (13.0 or 12.1) sometimes including syntax issues and you will never get a running configuration.

The requirements to install with pip are the following, which are also located in requirements.txt:

asn1crypto==0.24.0
cffi==1.12.3
cryptography==2.6.1
gast==0.2.2
ldap3==2.5.2
pem==19.1.0
pyasn1==0.4.5
pycparser==2.19
pycryptodome==3.7.3
pycryptodomex==3.7.3
pyOpenSSL==19.0.0
six==1.12.0

The certificates (old and new) must contain both the certificate and the associated private key in the PEM or MERGED format (PFX is non supported). In my case, it worked without issues when I created a MERGED File. You can simply create one with your CERT and (unencrypted) KEY file:

cat certificate.cert certificate.key > certkey.merged

I recommend to test first on a testgroup, so the necessary commands should look like this:

#replace 10.10.10.10 with your preferred Domain Controller
#replace julian.jakob@contoso.local with your AD-User (which has read and write access to the OTP AD-Attribute)
#replace search_base with your Active Directory DN
#replace search_filter with your Active Directory Group DN
#replace source_attribute with your choosen OTP AD-Attriubute
#replace OTPEncryption with your current bound userDataEncryptionKey Certificate
#replace OTPEncryption2024 with your new userDataEncryptionKey Certificate


#Filter on a Group:
python3 main.py -Host 10.10.10.10 -Port 636 -username julian.jakob@contoso.local -search_base DC=contoso,DC=local -search_filter "(&(objectClass=user)(memberOf=CN=Testgroup1,OU=Groups,DC=sw,DC=contoso,DC=local))" -source_attribute CitrixOTP -operation 2 -cert_path OTPEncryption.merged -new_cert_path OTPEncryption2024.merged


#Filter on a Group with nested groups support:
python3 main.py -Host 10.10.10.10 -Port 636 -username julian.jakob@contoso.local -search_base DC=contoso,DC=local -search_filter "(&(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:=CN=Testgroup1,OU=Groups,DC=sw,DC=contoso,DC=local))" -source_attribute CitrixOTP -operation 2 -cert_path OTPEncryption.merged -new_cert_path OTPEncryption2024.merged

You’re getting some informations about the fetched, modified and not modified User-Attributes. Not modified can simply mean a User who hasn’t enrolled a NetScaler OTP – so the AD-Attribute is empty.

Example of running OTP Encryption Script

A Logfile called app.log is created during the runtime where you can verify every entry, here’s an example of a successful modified User:

29-Feb-23 15:35:10 - root - INFO [upgrade_cert.py:220-convert_to_json_and_store() ] - Update successful for CN=Julian Jakob,OU=Users,OU=Test,DC=contoso,DC=local 
29-Feb-23 15:35:10 - root - INFO [upgrade_cert.py:102-traverse_entries() ] - updation successful for the user CN=Julian Jakob,OU=Users,OU=Test,DC=contoso,DC=local
29-Feb-23 15:35:10 - root - INFO [upgrade_cert.py:132-decrypt_and_update() ] - verifying if the encryption is intact

After your fist successful tests, you can run the Tool against the whole Active Directory without a search filter:

python3 main.py -Host 10.10.10.10 -Port 636 -username julian.jakob@contoso.local -search_base DC=contoso,DC=local -search_filter "(&(objectClass=user))" -source_attribute CitrixOTP -operation 2 -cert_path OTPEncryption.merged -new_cert_path OTPEncryption2024.merged

As one last step, don’t miss to unbind your old certificate and bind the new one on the NetScaler for the encryption process:

unbind vpn global -userDataEncryptionKey OTPEncryption
bind vpn global -userDataEncryptionKey OTPEncryption2024

Summary

I hope this Post will save you some time struggling with the correct usage of the OTP Encryption Tool.

3 comments

  1. Hello Julian,

    As Citrix mention not to install python on ADC it look strange to me to not use otptool there. ADC already contains python installation. I have one restricted environment where it is not permitted to export private key of any certificate created in the box and thus using otptool outside ADC is not possible.
    As you have the knowledge how otptool works, did you tried to run it in ADC?

  2. Hi,
    Many thanks for your article.
    On the last step it’s important to unbind the certificate first, then bind the new certificate because we can only have one certificate binded at a time.

Leave a Reply

Your email address will not be published. Required fields are marked *