Saturday, November 28, 2015

Deploy Centrify and Join Active Directory automatically with a simple Chef recipe

This article provides a quick-and-dirty Chef recipe that deploys the Centrify agent, authenticates against AD, joins Active Directory, joins a Centrify zone and a computer role.  This article is a modified version of a Centrify community post I authored.

  • This article provides a "quick basic configuration";  in a true deployment you have to account for high-availability, replication, security, package integrity, supported platforms, supported versions, change control, etc. 
  • All names, logos and trademarks used in this articles correspond to their existing owners.
  • We are not YUM or Chef subject-matter experts.  This would not be possible without the excellent tutorials provided by Chef Software.
What is required?
  • An Active Directory domain with a zone (you can make it work in workstation/express mode)
  • A Centrify zone and a Computer Role  (optional)
  • An Active Directory service account for joins and removals, plus a keytab for the account and a usable krb5.conf file.  Read this article if you want to know how to create the service account and obtain the keytab.
  • A RHEL-based system with enough storage for the Centrify RPM packages for each platform (or just for the subset you need to support).
    This system has to be set up like the original article with a YUM repo and the Centrify bits.
  • A second RHEL-derivative system with the ChefDK installed to test the recipe locally.
    To download the ChefDK, go to this site:
Note:  Although it's possible for you to follow this and put together a working prototype, I strongly-encourage that you really explore the concept of infrastructure as code.
Finally, By no means what's outlined here is ready for production.  Check out the reading list below.

Example Diagram
Chef Blog - Diagram.png

Implementation Steps

The goal of this lab is to be able to deploy the Centrify bits in a RedHat, CentOS, Scientific or Oracle system in a consistent way.  The 'core' process without checking for major dependencies or issues is to:
  1. Install Centrify DirectControl
  2. Authenticate against Active Directory with an account with minimal rights
  3. Join Active Directory
Building Blocks
  • YUM Repository with Centrify RPMs (completed in the previous lab)
  • AD account + keytab (steps outlined in a previous post)
  • Usable krb5.conf:  You can copy this file from any Centrified system; however, depending on where you're onboarding the system, you want to edit the file only with the DCs that are reachable to the new system.

Make the krb5.conf and service account keytab available to your infrastructure
In the original article, we piggy-backed on the Apache webserver as the transport for our repository.  Now we're going to create another folder for utilities (utils for short) and copy the keytab and krb5.conf file.

  1. Create a folder under /var/www/html
    $ sudo mkdir /var/www/html/centrify/utils
  2. Copy the RPMs to the folder.$ cd /path/to/files
    $ sudo mv krb5.conf  /var/www/html/centrify/utils
    $ sudo mv ad-joiner.keytab  /var/www/html/centrify/utils
  3. Set the proper permissions in the folder
    chmod -R ugo+rX /var/www/html/centrify/utils
  4. Verify that the files are accessible via the web server (you may have to check the firewall settings)
Perform a basic installation of the ChefDK
  1. Go to  and download the latest ChefDK bits.
  2. Install the bits
    $ dzdo rpm -Uvh chefdk-0.10.0-1.el7.x86_64.rpm
  3. Set the ruby path to the Chef-provided version
    $ echo 'eval "$(chef shell-init bash)"' >> ~/.bash_profile
  4. Logout and log back in to verify the ruby path
    $  which ruby
Create and test your stand-alone Chef Recipe
  1. Create a file
    $ vi install-centrifydc.rb
    Here are the contents of my file
    # This stand-alone recipe will install the Centrify Agent on RHEL derivatives, 
    # joins Active Directory and places the system in a Computer Role
    # Notes: This recipe is not idempotent (achieving this is up to you!)
    # Variables for my environment (see blog post)
    # domain is the most basic parameter to join Active Directory
    domain = 'centrify.vms'
    # in Zone Mode (licensed with UNIX identity and Access Control) the zone
    # parameter corresponds is where the system will be placed
    zone = 'Global'
    # OU is where your computer object will be placed in Active Directory
    # your ad-joiner account should be able to join systems to this container
    ou = 'ou=servers,ou=centrifyse'
    # A Computer role is one of the ways to group systems and define access 
    # control a system may be a member of multiple computer roles.  
    # E.g.  a LAMP system may be accessible by Web Admins, Developers and 
    # DBAs
    crole = 'PCI Servers'
    # In a pre-requiste blog entry, I outlined how to create a YUM repository for 
    # RHEL and derivatives.  This means that you need a yum or apt repo with 
    # the Centrify packages.  Per Chef, the default action will be to install the package.
    package 'CentrifyDC'
    # Centrify's utilities are Kerberized, this means that they will use the current
    # user's Kerberos TGT to attempt the transaction against AD.  However, in a 
    # virgin system, there are no working krb5.conf files, therefore kinit won't know
    # how to find a KDC to authenticate against.  This is why we need a krb5.conf 
    # file from a working system (or that points to a reachable Domain Controller), 
    # in the previous blog entry, we piggy-backed on an Apache Web server to serve those files.
    remote_file '/tmp/krb5.conf' do
      source 'http://linux2.centrify.vms/centrify/utils/krb5.conf'
      owner 'root'
      group 'root'
      mode '0644'
      action :create
    # The keytab corresponds to a service account that has the minimal rights, in 
    # this case, the rights to write a computer object in the designated container 
    # (ou) needless to say, you need to treat this file with care and if posible, 
    # remove when complete.
    remote_file '/tmp/ad-joiner.keytab' do
      source 'http://linux2.centrify.vms/centrify/utils/ad-joiner.keytab'
      owner 'root'
      group 'root'
      mode '0644'
      action :create
    # In this command, we authenticate against AD with the keytab of our service 
    # account.  Note that we are using the usable krb5.conf file so kinit can reach
    # a KDC (domain controller).  The end-result is that root (or sudo) user will
    # have a TGT and you don't need to put keys, hashes or passwords in your script.
    execute 'kinit' do
      command "env KRB5_CONFIG=/tmp/krb5.conf /usr/share/centrifydc/kerberos/bin/kinit -kt /tmp/ad-joiner.keytab ad-joiner"
    # Finally we run adjoin.  At this point we are using the variables from my 
    # environment.  Although in doing so, we broke the 'idempotent principles, I'm 
    # certain that Chef experts will understand how to implement an independent cookbook
    execute 'adjoin' do
       command "/usr/sbin/adjoin -z #{zone} -c #{ou} -R \"#{crole}\" -V #{domain}"
    # Cleanup
    execute 'kdestroy' do
      command "env KRB5_CONFIG=/tmp/krb5.conf /usr/share/centrifydc/kerberos/bin/kdestroy"
    file '/tmp/ad-joiner.keytab' do
       action :delete
    file '/tmp/krb5.conf' do
       action :delete
  2. Verify the recipe
    $ sudo chef-apply install-centrifydc.rb
    Recipe: (chef-apply cookbook)::(chef-apply recipe)
      * yum_package[CentrifyDC] action install
        - install version 5.2.3-429 of package CentrifyDC
      * remote_file[/tmp/krb5.conf] action create
        - create new file /tmp/krb5.conf
        - update content in file /tmp/krb5.conf from none to 186d5f
      * execute[kinit] action run
        - execute env KRB5_CONFIG=/tmp/krb5.conf /usr/share/centrifydc/kerberos/bin/kinit -kt /tmp/ad-joiner.keytab ad-joiner
      * execute[adjoin] action run
        - execute /usr/sbin/adjoin -z Global -c ou=servers,ou=UNIX -R "App Servers" -V centrify.vms

Verification Video

There are absolutely many improvements that can be made.   Here are a few that come to mind (in no specific order):

  • Check for Perl:  CentrifyDC requires Perl 5.8 and up.
  • Chek for DC connectivity:  You can potentially check for connectivity to KDCs prior to attempting to authenticate.
  • Inspect the name of the system:  In keeping with AD Naming conventions, we should check for length and uniqueness in the forest prior to join.
  • Check if the system is already joined or in the desired zone/forest.
  • Inspect the IP/DNS configuration:  Maybe the TCP/IP and DNS config is not right.
  • Perform a Dynamic DNS update using addns:  After join, you can use addns to get the system registered with Microsoft DNS
  • Obtain Certificates with ADCert:  If the system is used for SSL communications, you can get the cert manually using adcert.
  • Manage centrifydc.conf:  There are some basic parameters that may not be manageable via GPO (e.g. DMZ) that can be managed from there.
  • New Information:  Centrify DirectControl can provide information to Chef regarding the AD topology.
  • Add dependent packages:  LDAP Proxy or Centrify DirectAudit/DirectSecure come to mind.
  • Most importantly:  This requires a cookbook!  Make it as idempotent as possible!

Reading List
Although any capable IT admin is able to spend a few hours and make something like this work, my advice is to explore deeper the concepts around 'Infrastructure as Code'; I'm of the opinion that it's a game-changing paradigm.  I recommend (still reading):
  • RESTFul Web APIs (Richardson)
  • Test-Driven Infrastructure with Chef (Nelson-Smith)
  • Learn Chef Tutorials at (
For a "removal" recipe, see the this Centrify Community post.

No comments:

Post a Comment