Showing posts with label automation. Show all posts
Showing posts with label automation. Show all posts

Wednesday, March 16, 2016

Deploy Centrify and Join Active Directory automatically using a stand-alone Puppet script

A few months ago I published a post titled "Deploy Centrify and Join Active Directory with a simple Chef Recipe" as customary, after I get asked about something 3 times, it's time to create a post, but now using Puppet by PuppetLabs.  This post is identical to the Chef post, just different tools.

Disclaimers and Acknowledgements
  • 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.
  • I'm not Puppet, Chef or Bladelogic subject-matter experts, hence the use of a stand-alone script or recipe. 
  • Puppet Master server/slaves/node architecture is outside the scope of this post
  • This would not be possible without my customers/prospects asking and the tutorials available online.  Some great resources:
    - Introduction to Puppet:  https://docs.puppetlabs.com/guides/introduction.html
    - Willams' blog post "How to install Puppet in Stand-Alone mode on CentOS7"
    - Kudos to MaestroDev for the wget Puppet extension: https://forge.puppetlabs.com/maestrodev/wget
What is required?
  • An Active Directory domain
  • A Centrify zone (optional - if using Centrify in licensed mode/privilege management)
  • 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 as a YUM repository, as described in the the original orchestration article.
  • A second RHEL-derivative system to install Puppet (see below), this system must have DNS settings configured correctly.
Note:  Although it's possible for you to follow this and put together a working prototype, I strongly-encourage that you really explore the concepts  of DevOps/infrastructure as code.  The whole philosophy promotes constant improvement, this means that if you expect this to be a "set it and forget it" solution, I advise that you realign your expectations.

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

Planning
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.  Also, if you know what you're doing, you can extend this to other OSs, and platforms as well.

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 (detailed instructions here)
  • 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.
If you prepared this for the Chef article, you can skip to Puppet installation.

  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)
    utils.PNG

Install Puppet and the wget Extension
  1. Add the Puppet repository (you must find the proper repository for your RHEL version, version 7 shown)
    $ sudo rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm
  2. Install the bits
    $ yum install puppet
  3. Make sure your system's DNS settings are up to date (yes, no "localsystem.localdomain")
    Can you ping your own system by name and FQDN?
    What is the output of the hostname command?
    Run this:
    facter | grep hostname
    facter | grep fqdn
    if the output isincorrect, you must edit the /etc/hosts and /etc/resolv.conf and speak to your DNS admin to set things straight
  4. Logout and log back in to verify the ruby path
    $  sudo puppet module install maestrodev-wget
    You should be ready to get going.
Create and test your stand-alone Puppet Script
To recap, the sequence to automate Installation and joins is as follows:
  1. Retrieve a usable krb5.conf file
  2. Retrieve the keytab of a valid service account with minimum rights to join systems to the target AD OU, to the target zone (if using in zone mode) and if adding to a Computer role, with rights to add to the target AD groups.
  3. Install the Centrify Package and use the kinit tool to obtain a TGT
  4. Run adjoin with the proper options.
  5. Perform cleanup

Here is the Non-idenpotent Puppet Script:

# 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!)

include wget

# Variables for my environment (see blog post)
# domain is the most basic parameter to join Active Directory

$adname = "centrify.vms"  
# Notice that I could not use "domain" like in the Chef example.  
# That word seems to be reserved in Puppet

# In Zone Mode (licensed with UNIX identity and Access Control) the zone
# parameter corresponds is where the system will be placed.  Not needed
# if working in workstation or express mode.

$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=unix"

# 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 with different access rights and privileges.

$crole = "App Servers"

# nodes are the managed system in Puppet;  in a true deployment you can
# apply to individual systems or collections of systems.  Since this is not
# idempotent, you must specify the fqdn.

node "your-system-fqdn" {

# 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 (engcen6).

wget::fetch {"download a working krb5.conf":
  source             => 'http://engcen6.centrify.vms/centrify/utils/krb5.conf',
  destination        => '/temp/krb5.conf',
  timeout            => 0,
  verbose            => true,
  nocheckcertificate => true,
  before => Exec["kinit"]
}

# 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), centrify zone and the AD group that contains the "App Servers"computer
# role needless to say, you need to treat this file with care and if possible, 
# remove when complete.

wget::fetch {"download the ad-joiner keytab file":
  source             => 'http://engcen6.centrify.vms/centrify/utils/ad-joiner.keytab',
  destination        => '/temp/ad-joiner.keytab',
  timeout            => 0,
  verbose            => true,
  nocheckcertificate => true,
  before => Exec["kinit"]
}

# We leverage Puppet to ensure the files are present. This will be used later
# to guarantee proper sequencing.

file {"ad-joiner.keytab":
  ensure => present,
  path   => '/temp/ad-joiner.keytab'
}

file {"krb5.conf":
  ensure => present,
  path   => '/temp/krb5.conf'
}

# 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.  The before/subscribe and require Puppet directives guarantee proper 
# sequencing.

exec {"kinit":
  command =>  "/bin/env KRB5_CONFIG=/temp/krb5.conf /usr/share/centrifydc/kerberos/bin/kinit -kt /temp/ad-joiner.keytab ad-joiner",
  before => Exec["adjoin"],
  subscribe => [
        File["/temp/ad-joiner.keytab"],
        File["/temp/krb5.conf"],
  ],
  require => Package["CentrifyDC"],
}


# 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.  Puppet will simply make sure the package is present
# notice the differences, I declared this after the previous directives, when
# the package is a pre-requisite.

package {"CentrifyDC":
    ensure => 'installed',

}

# 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 Puppet experts can find ways to improve on this.  

exec { "adjoin":
  command => "/usr/sbin/adjoin -z $zone -c $ou -R \"$crole\" -V $adname",
  require => Package["CentrifyDC"]

}

# In the cleanup phase, we clear the TGT and delete the utility files
# Although the keytab provides very specific limited AD rights, always make
# a habit of cleaning-up.

exec {'kdestroy':
  command => '/bin/env KRB5_CONFIG=/tmp/krb5.conf /usr/share/centrifydc/kerberos/bin/kdestroy',
  require => Exec['adjoin'],
}

exec {"/bin/rm -f /temp/*":
  require => Exec['kdestroy'],
}

} # End of Script


Review the results
$ sudo puppet apply centrify-build.pp
Notice: Compiled catalog for engcen7.centrify.vms in environment production in 1.77 seconds
 Info: Applying configuration version '1458157258'
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/Package[CentrifyDC]/ensure: created
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/File[krb5.conf]/ensure: created
 Info: /Stage[main]/Main/Node[engcen7.centrify.vms]/File[krb5.conf]: Scheduling refresh of Exec[kinit]
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/Wget::Fetch[download a working krb5.conf]/Exec[wget-download a working krb5.conf]/returns: executed successfully
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/File[ad-joiner.keytab]/ensure: created
 Info: /Stage[main]/Main/Node[engcen7.centrify.vms]/File[ad-joiner.keytab]: Scheduling refresh of Exec[kinit]
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/Wget::Fetch[download the ad-joiner keytab file]/Exec[wget-download the ad-joiner keytab file]/returns: executed successfully
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/Exec[kinit]/returns: executed successfully
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/Exec[kinit]: Triggered 'refresh' from 2 events
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/Exec[adjoin]/returns: executed successfully
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/Exec[kdestroy]/returns: executed successfully
 Notice: /Stage[main]/Main/Node[engcen7.centrify.vms]/Exec[/bin/rm -f /temp/*]/returns: executed successfully
 Notice: Finished catalog run in 38.32 seconds

Verification Video


Saturday, November 28, 2015

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

Background
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.

Disclaimers
  • 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:  https://downloads.chef.io/chef-dk/
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

Planning
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)
    utils.PNG
Perform a basic installation of the ChefDK
  1. Go to https://downloads.chef.io/chef-dk/  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
    /opt/chefdk/embedded/bin/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
    end
    
    # 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
    end
    
    # 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"
    end
    
    # 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}"
    end
    
    
    # Cleanup
    execute 'kdestroy' do
      command "env KRB5_CONFIG=/tmp/krb5.conf /usr/share/centrifydc/kerberos/bin/kdestroy"
    end
    
    file '/tmp/ad-joiner.keytab' do
       action :delete
    end
    
    file '/tmp/krb5.conf' do
       action :delete
    end
  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
     [truncated]
      * 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



Adjustments
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 (http://learn.chef.io)
For a "removal" recipe, see the this Centrify Community post.

Friday, October 9, 2015

Utilities: install.sh

Background

Automation and orchestration are key capabilities of the modern IT infrastructure.  Whether organizations are using private or public clouds, tools like Bladelogic, System Center, Satellite, Chef, Casper, Puppet or homegrown scripts - software should be orchestration friendly.

Centrify Server Suite for UNIX, Linux, and Mac offers a facility that should be leveraged by any savvy IT infrastructure team.  The tool is a script called install.sh.

This script is shipped with the gzipped tarball for Centrify software, for example, here are the listings for a RHEL-based system (excluding the release notes):

  • adcheck-rhel4-x86_64
  • centrifyda-3.2.3-rhel4-x86_64.rpm
  • centrifydc-5.2.3-rhel4-x86_64.rpm
  • centrifydc-install.cfg
  • centrifydc-ldapproxy-5.2.3-rhel4-x86_64.rpm
  • centrifydc-nis-5.2.3-rhel4-x86_64.rpm
  • centrifydc-openssh-6.7p1-5.2.3-rhel4-x86_64.rpm
  • centrify-suite.cfg
  • install-express.sh -> install.sh
  • install.sh

Note that all the installation bits are shipped in the native package manager or the platform, this gives the opportunity to the administrator to bypass install.sh and use the native installer.  E.g.  to install only the base agent, you can run

rpm -Ivh centrifydc-5.2.3-rhel4-x86_64.rpm

Many admins just simply add the RPMs to their repositories and can use facilities like yum to install or maintain the package.

Capabilities of install.sh

  • Interactive install/join operations:  walks the user through a series of menus and options
  • Automatic with command options:  can be run manually or by an orchestration facility for installations and joins.
  • Automatic with an answer file:  any of the .CFG answer files can be used with install.sh
  • Kerberized:  install.sh calls adjoin and other utilities that can benefit from Kerberos keytab preauthentication.

What does install.sh do?

install.sh is a script;  it acts as an abstraction layer between the package manager of the native OS and any other tool or manual script.  This is very powerful because eliminates the nuances related to each operating system, architecture or distribution.

For example, some AIX systems use the installp facility, RHEL and derivatives use RPM, Debian derivatives like Ubuntu use dpkg, OS X systems use Install.app and so on;  install.sh allows for the administrator to have a QA tested way to install Centrify software and perform additional tasks.


When preparing for a release, Centrify will QA install.sh against all the supported platforms.


Basic Automation Playbook

What you need:
a) The keytab for an AD user that can join systems (or remove them) to the target OUs
For more info on how to create this, click here.
b) A krb5.conf file for a working system
d) Install.sh (or the native package manager utility)
e) If not using install.sh, you'll need adjoin (or adleave)

Sample Command Sequences

Sample 1:  In this sequence, we use an /temp/ad-joiner keytab with a /temp/krb5.conf and we'll use install.sh to install standard edition and join a zone called  myzone in the acme.test domain in the "My Servers" OU.

env KRB5_CONFIG=/temp/krb5.conf  /usr/share/centrifydc/kerberos/bin/kinit -kt /temp/ad-joiner.keytab ad-joiner

 ./install.sh  --std-suite  --adjoin_opt="acme.test -z myzone -c acme.test/My\ Servers"


Sample 1:  In this sequence, we use an /temp/ad-joiner keytab with a /temp/krb5.conf and we'll use install.sh to install standard edition and join a zone called  myzone in the corp.contoso.com domain in the "My Servers" OU.

env KRB5_CONFIG=/temp/krb5.conf  /usr/share/centrifydc/kerberos/bin/kinit -kt /temp/ad-joiner.keytab ad-joiner

 ./install.sh  --std-suite  --adjoin_opt="corp.contoso.com -z myzone -c corp.contoso.com/My\ Servers"

Sample 2:  In this sequence, we use an /temp/ad-joiner keytab with a /temp/krb5.conf and we'll use rpm to install the standard package and adjoin to join the Global zone in the corp.contoso.com domain and put the computer under the Centrify\Servers OU.

env KRB5_CONFIG=/temp/krb5.conf  /usr/share/centrifydc/kerberos/bin/kinit -kt /temp/ad-joiner.keytab ad-joiner

rpm -Ivh centrifydc-5.2.3-rhel4-x86_64.rpm

adjoin -z Global -c "ou=servers,ou=centrify" corp.contoso.com


install.sh Help file

This script installs (upgrades/uninstalls) Centrify Suite.
Only the superuser can run this script.

Usage:
  install.sh [-n|--ent-suite|--std-suite|--express] [-e] [-h] [-V] [-v ver] [-l log_file]

where:
  -n             Custom install/upgrade/uninstall in non-interactive mode.
  --ent-suite    Install Enterprise Suite in non-interactive mode.
  --std-suite    Install Standard Suite in non-interactive mode.
  --express      Install Centrify Express in non-interactive mode.
  --bundle       Install Centrify Suite using bundle.
  --suite-config <config_file>
                 Override default suite config file with <config_file>.
  -e             Uninstall (erase) CentrifyDC.
  -h, --help     Print out this usage and then exit.
  -V             Print out installer version and then exit.
  -v <ver>       Install CentrifyDC <ver> version.
                 Format: x.x.x or x.x.x-xxx. x is number.
  -l <log_file>  Override default log-file PATH with <log_file>.
  --rev <rev>    Package OS revision to install.
  --custom_rc    Return meaningful exit code.
  --override="<options>"
                 In non-interactive mode, override default options with <options> list.
                 Format: --override="CentrifyDC_openssh=n,CentrifyDA=R"
  --adjoin_opt="<adjoin_options>"
                 Override default adjoin command line options with <adjoin_options>.
  --enable-da    In non-interactive mode, once joined to a domain,
                 enable DA for all shells.
  --disable-da   In non-interactive mode, disable DA NSS mode after install.

Examples:
  ./install.sh        -n  --override="INSTALL=R,CentrifyDC_nis=Y,CentrifyDC_openssh=N,CentrifyDA=N"
  ./install.sh        --std-suite  --adjoin_opt="acme.test -p pass\$ -z t_zone -c acme.test/My\ Servers"
  ./install-bundle.sh --std-suite "--adjoin_opt=\"acme.test -p pass\\$ -z t_zone -c acme.test/My\\ Servers\""

Sunday, May 10, 2015

Scripting - Using Centrify PowerShell to Automate Access and Privilege Operations

Background

In some of the examples that we use in this blog, we leverage a basic reference design that consists of a Centrify Active Directory zone, a few computer roles, a UNIX and Windows SysAdmin role and some basic assignments at the Zone, Computer Role and System levels.  Since some of you have told me that you use the blog to follow along, I've decided to share the PowerShell code for this purpose.

There are several cast of characters that I create  (in this case, the Simpsons), but you can change it as needed.

Why post this?
As I meet with many of the current or prospective Centrify customers I see 3 common threads: many more of you are using public/private cloud (as evidenced by some of the recent posts) and want tools and examples of automation;  many of you are looking to leverage IT Service Management solutions for  workflow/approvals (like ServiceNow) and combine it with automation; this post provides some examples.

Disclaimer:  I am not a programmer.  I've made my forays into scripting in the past (mostly vbscript) but I'm not a PowerShell, Bash or any other type of programmer.  This is done for illustration purposes.  When working with scripts in production environments, you.must.add.error.handling!!!

The Basic Reference Design

The cadence will be the same as the GUI.  Create the zone, define rights, define roles, populate the roles and assign them.  These are considered the infrequent steps.
The normal operations are UNIX-enabling users, and performing role assignments directly or leveraging AD groups.  This is the same for Windows and UNIX.



PowerShell Modules

You'll need the Active Directory and the Centrify DirectManage PowerShell modules.

Import-Module ActiveDirectory
Import-Module Centrify.DirectControl.PowerShell

Notice that I'm assuming the default location.


Creating the Zone

$zone = New-CdmZone -Name "Model" -Description "Reference Zone" -Type hierarchical -Container "cn=Zones,ou=Unix,dc=example,dc=com"

Notice that I'm using a shortcut to create the zone and add it to a variable.  Obviously the Container assumes that your domain is example.com and there's a UNIX OU with a Zones SubOU contained within.

Defining the Rights

$cmd1 = New-CdmCommandRight -Zone $zone -Name "Run any command as root" -Pattern "*" -MatchPath "*" -DzdoRunAsUser root -Authentication user 

Creates the sensitive command to run any command as root and requests authentication.

$criteria = New-CdmMatchCriteria -Description "Event Viewer" -FileType "exe" -FileName "eventvwr.exe" -Path "C:\Windows\System32\"


$cmd2 = New-CdmApplicationRight -Zone $zone -Name "Audit Windows Event Log" -MatchCriteria $criteria -RunasSelfGroups "Builtin\Administrators"


Creates Event viewer as Administrator.  The first part is to create the application criteria (a Windows application may contain multiple criterion), then we create the right with the proper criteria.

$cmd3 = Get-CdmPamRight -Zone $zone -Name "sshd" 

This is getting the stock sshd right.  Keep in mind that work in most Linux, but probably you'll have to create something different for Ubuntu or Solaris.

$cmd4 = New-CdmCommandRight -Zone $zone -Name "Audit RHEL Secure Log" -Pattern "tail /var/log/secure" -DzshRunas root

This is another platform-dependent command right.  

$cmd5 = Get-CdmPamRight -Zone $zone -Name "login-all"

This gets, the stock "login-all" PAM right for the SysAdmin Role.

Defining the Roles

$role1 = New-CdmRole -Zone $zone -Name "Mixed Auditor" -UnixSysRights login, ssologin, nondzsh -WinSysRights remote

Defines the Mixed Auditor Role with the ability to log in with a password and with SSO to unix systems and via Citrix or RDP to Windows systems.

Add-CdmCommandRight -Right $cmd4 –Role $role1 
Add-CdmApplicationRight -Right $cmd2 –Role $role1 
Add-CdmPamRight  -Right $cmd3 –Role $role1 

The previous 3 commands add the unix command, windows application and ssh rights into the Mixed Auditor role.

$role2 = New-CdmRole -Zone $zone -Name "UNIX Sysadmin" -UnixSysRights login, ssologin, nondzsh 
Add-CdmCommandRight -Right $cmd1 –Role $role2
Add-CdmPamRight -Right $cmd5 –Role $role2

The defines the UNIX SysAdmin role and adds the "Run any command as root" and login-all PAM right.

Defining Computer Roles

Computer Roles are groupings of systems.  They may contain UNIX or Windows systems that exist within the zone.  Computer Roles are stored within AD Security groups, therefore we have to define some groups, and groups have to be put in an OU.  In this case an OU called Demo.

$oupath = (Get-ADOrganizationalUnit -Filter 'Name -like "Demo"').DistinguishedName
New-ADGroup -Name "Centrify-Model-CR-WebServers" -Path $oupath -GroupScope Global
New-ADGroup -Name "Centrify-Model-CR-DatabaseServers" -Path $oupath -GroupScope Global
$crgroup1 = Get-ADGroup -Filter 'Name -like "Centrify-Model-CR-WebServers"'
$crgroup2 = Get-ADGroup -Filter 'Name -like "Centrify-Model-CR-DatabaseServers"'

The naming convention is easy to figure out for these AD groups:  Centrify-NameofZone-Type of Group-Description.

$crweb = New-CdmComputerRole -Zone $zone -Name "Web Servers"  -Group $crgroup1
$crdb = New-CdmComputerRole -Zone $zone -Name "Database Servers" -Group $crgroup2

At this point there's an empty zone, with a basic security access and privilege model.

UNIX-Enabling Users

To access a UNIX/Linux system, users need to have a UNIX identity in the Centrify Zone in AD;  this is quite simple using PowerShell.  In addition, they must have a role as well.

New-CdmUserProfile -Zone $zone –User marge.simpson@example.com -login marge.simpson -UseAutoUid -AutoPrivateGroup –HomeDir "%{home}/%{user}" –Gecos "%{u:displayName}" –Shell "%{shell}"

New-CdmUserProfile -Zone $zone –User bart.simpson@example.com -login bart -UseAutoUid -AutoPrivateGroup –HomeDir "%{home}/%{user}" –Gecos "%{u:displayName}" –Shell "%{shell}"

New-CdmUserProfile -Zone $zone –User maggie.simpson@example.com –login maggie.simpson -UseAutoUid -AutoPrivateGroup –HomeDir "%{home}/%{user}" –Gecos "%{u:displayName}" –Shell "%{shell}"

New-CdmUserProfile -Zone $zone –User homer.simpson@example.com–login homer -UseAutoUid -AutoPrivateGroup –HomeDir "%{home}/%{user}" –Gecos "%{u:displayName}" –Shell "%{shell}"

Since this is a clean environment, I'm using very few overrides and all UID/GID info is generated based on the user's SID.  

Granting access and Assigning Roles

A permanent assignment at the zone level

$role1 = Get-CdmRole -Zone $zone -Name "UNIX SysAdmin"  
New-CdmRoleAssignment -Zone $zone -Role $role1 -ADTrustee marge.simpson@example.com

As discussed in previous postings, these are rare and only assigned to senior trusted admins

A permanent assignment at the computer role level (WebServers)

$role2 = Get-CdmRole -Zone $zone -Name "Mixed Auditor" 
$crweb = Get-CdmComputerRole -Zone $zone -Name "Web Servers" 

New-CdmRoleAssignment -ComputerRole $crweb  -Role $role2 -ADTrustee bart.simpson@example.com

Note that this is a mixed role.  If the computer role has IIS and Apache servers, this auditor can review both the event log and the secure log.

A time-bound role assignment (perhaps a change control Window or a break-glass scenario) to an individual system

$role3 = Get-CdmRole -Zone $zone -Name "UNIX login"  
$comp = Get-CdmManagedComputer -Zone $zone -Name "your-zone-enabled-system" 
New-CdmRoleAssignment -Computer $comp -Role $role3 -ADTrustee homer.simpson@example.com -StartTime (Get-Date) -EndTime (Get-Date).AddMinutes(60)

In this example, Homer is getting the ability to log in to this system for an hour.  

Video


Sunday, April 19, 2015

Automation - Adding a UNIX/Linux system to a Centrify Computer Role in Private/Public cloud scenarios

Background

Note from July 2015:  With the release of Centrify Suite 2015.1 (agent 5.2.3) adjoin has been modified to add the --computerrole parameter;  this in effect eliminates the need for the steps below.  I will leave the article intact for historical reasons, but if you're at 5.2.3 or above you don't need to do this anymore.

Back in August 2014, I wrote a blog posting illustrating how to use Centrify Kerberos tools like adkeytab to assist in automation scenarios while maintaining the least privilege model and separation of duties.

I also put together a consolidated post here: http://community.centrify.com/t5/Get-Started-How-To-s/HOWTO-Use-Centrify-Tools-for-Public-Private-Cloud-Automation/ba-p/20369

This post extends the use case to add the system to a computer role after the system ins joined.  As you know Centrify computer roles are a powerful way to group systems by adding them to AD security groups.  This increased flexibility allow for groupings of servers within zones.  When combining the knowledge of the original post and this one, you can accomplish the following:

  • Launch a UNIX/Linux template used in a private or public cloud scenario.
  • During post-installation, the system joins a zone and a computer role automatically without human intervention.
Variables:  
  • Domain to be joined
  • Zone to be joined
  • Computer role(s) to be joined
These parameters need to be passed to your automation or orchestration solution (or be part of your template for that type of system).

Implementation

Modifying the automation account permissions to add accounts to groups

So far, the automation account (ad-joiner in our example) only has the rights to add/move/change AD computer objects in an OU and to add/move/change computers in to the Centrify zone.  We will grant this account the ability to add/move/change members of groups that are in a specific OU.   In keeping with the least privilege model, we need to provide the account only the privileges it needs.

Like the previous example, we'll use the AD delegation wizard in the OU that contains the AD groups that are used to contain Centrify Computer Roles.  There is already a canned delegation task that suffices "Modify the membership of a group" 


Note:  this is a one-time process.

Adding the system to the appropriate Computer Role

There are several ways to accomplish this because ultimately the action is to add a computer object to an active Directory group.

In UNIX/Linux, using adedit, it's as simple as illustrated in this example ( 5 lines)

$ adedit  
# this opens the adedit TCL utility
> bind corp.centrifying.net   
# binds to the corp.centrifying.net domain or returned by adinfo -d
> package require are_lib  
# loads the required libraries
> add_user_to_group awscentos01$@corp.centrifying.net centrify-global-unix-cr-webservers@corp.centrifying.net 
# adds the awscentos01 computer object (append a $ to the output of adinfo -n) and joins it to the centrify-global-unix-cr-webservers AD group (you can pass as parameter or have as part of the template)
$ adflush 
# flushes the cache to the access controls are updated.  In older versions of the Centrify agent, this required a service restart so the machine re-authenticated against AD and refreshed the ACLs.

Notes:  
  1. This is the process that will repeat each time an instance is built.
  2. This is also the area that I've found that many prospects and customers encounter challenges.  Success in these cases has to do with simplicity and standardization.  For example, if I have a naming convention and I'm adhering to the best practices (e.g. a separate OU to store AD computer groups) then the logic of my script is very simple.  If I have NOT standardized and I have a centralized AD mess (or even worse, classic zones), then this will increase complexity significantly.
    For example.  If I'm using a script that expects 3 variables:
    - AD domain,

    - Hostname:  keep in mind, you can join a system to AD with one name, but the local honstname is different
    - Type of Server:  (e.g. database server, web server, PCI server, etc)
    In a standardized environment you can afford to get those variables from the output of some of the centrify or environment variables.  E.g.

    sh adedit /tools/scripts/add-member.tcl -d `adinfo -d` -n `adinfo -n` -r `echo $SERVERTYPE`

Alternative method - Using PowerShell

In the case you have multiple automation avenues, you can perform the same tasks above with PowerShell.

Import-Module ActiveDirectory 
# loads the required PowerShell Module
Get-ADGroup  centrify-global-unix-cr-webservers | Add-ADGroupMember -Members (Get-ADComputer -filter 'samAccountName -like "awscentos01$"') 
# Gets the centrify-global-unix-cr-webservers AD group and adds a member which is the the awscentos01 computer object.

Note:  Always perform cleanup after you're done.  Keytabs should be handled with the same sensitivity as private keys.

Implementation

Putting it all together in an AWS scenario (2 videos ~16 mins)

Description:


Verification

Sunday, August 24, 2014

Using Kerberos keytabs and Centrify tools to automate UNIX/Linux/Mac AD domain joins or unjoins

The Problem

Dynamic environments expand and contract based on organizational needs; this means that Unix, Linux, Mac OS X servers and workstations are built and decommissioned frequently.  Most recently, public/private cloud elasticity accentuates this issue and having an access controls solution like may end-up adding unnecessary complexity if it's not designed for this reality.

When joining a computer to the domain, the computer name (hostname) may not be known to pre-create the AD account, therefore an an authoritative join is the only choice; the issue here is that an AD account that has the ability to join computers into the domain (OU) and into the Centrify zone is required.

Fortunately, Centrify designed the Server Suite solution tool set with this reality in mind.  In this post, we will discuss how to add or remove systems from AD securely leveraging Kerberos keytabs and tools like adjoin and adleave.  Like all small projects, we'll use the Plan-Do-Check-Adjust methodology.

Requirements
  • Scripts should not store plain-text passwords
  • Tools must be automation-friendly
  • The least access and least privilege principles must be conserved
  • The Separation of Duties (SoD) principle must be met
Tools
  • Active Directory Users and Computers
  • Centrify CLI tools: adjoin, adleave, adkeytab
  • Kerberos tools:  kinit, kdestroy.

Planning

For a simple example, we'll consider the following planning steps:

  • Incorporate the Centrify agent bits into the infrastructure image, the agent can be installed and not joined.
  • An AD Service account with the ability to create, remove (or modify) computer objects to the target domain OU should be created.
  • That same AD service account should have the rights to join, remove and modify objects in the target Centrify zone.
  • A Kerberos keytab file needs to be created and securely put in a place where the script can use it.  Let's assume that the file will be securely copied to a local drive and deleted upon use.
    Note:  this is important, a Kerberos key table file needs to be to be treated with the same sensitivity as a private key.  They are not to be left behind on systems even if the account has been properly secured.
  • In addition to the keytab file, a krb5.conf file with the correct settings needs to be deployed to the unjoined system so the Kerberos tools can find a KDC (AD DC)
  • Naming conventions for the service account and the hostname need to be pre-established.  Keep in mind that computer account names have length limitations.
  • An AD OU for Unix/Linux or Mac computers is required to limit the scope of where the join account can perform joins.

Implementation (Do)

AD Join service account setup (1-time steps)
  1. Create the Active Directory service account by using ADUC.  Make sure that the account and its password do not expire.  In this example we'll use "ad-joiner" and the domain is corp.contoso.com
  2. In Active Directory users and computers, use the Delegate Control wizard to delegate the ability to create and delete computer objects.
  3. In the target Centrify zone, use the Delegate Zone Control wizard to give the service account the rights to join, remove and modify computers in the zone.
  4. In a Centrified system, use the adkeytab with the adopt option to create the Kerberos keytab file and randomize the password.  This will be performed with the root account so it is protected by that account.
    # /usr/sbin/adkeytab --adopt --user jerry.seinfeld--keytab ad-joiner.keytab  -V ad-joiner
    ADKeyTab version: CentrifyDC 5.1.3-482
    Options
    -------
    use machine ccache: no
    domain: corp.contoso.com
    server: null
    user: dwirth
    container: null
    account: ad-joiner
    trust: no
    des: no
    jerry.seinfeld@CORP.CONTOSO.COM's password:
    Attempting bind to corp.contoso.com site:Demo-Site server:dc1.corp.contoso.com: ccache:MEMORY:0x566940
    Bind successful to server dc.centrifyimage.vms
    Searching for AD Object: filter = (samAccountName=ad-joiner), root = DC=corp,DC=contoso,DC=com
    AD Object found: CN=ad-joiner,OU=Service Accounts,OU=Unix,DC=corp, DC=contoso,DC=com
    Key Version = 2
    Activating AD account: CN=ad-joiner,OU=Service Accounts,OU=Unix,DC=corp, DC=contoso,DC=com
    Account 'CN=ad-joiner,OU=Service Accounts,OU=Unix,DC=corp, DC=contoso,DC=com' All SPNs already present
    Adding managed account keys to configuration file: ad-joiner
    Changing account 'ad-joiner' password with user 'jerry.seinfeld@CORP.CONTOSO.COM' credentials.
    Searching for AD Object: filter = (samAccountName=AD-JOINER), root = DC=corp,DC=contoso,DC=com
    AD Object found: CN=ad-joiner,OU=Service Accounts,OU=Unix,DC=corp,DC=contoso,DC=com
    Key Version = 3
    Success: Adopt Account: ad-joiner
  5. Verify the keytab file with klist
    # /usr/share/centrifydc/kerberos/bin/klist -kt ad-joiner.keytab
    Keytab name: FILE:ad-joiner.keytab
    KVNO Timestamp         Principal
    ---- ----------------- ----------------------------------
    3 08/2414 22:22:55 ad-joiner1@CORP.CONTOSO.COM
    3 08/2414 22:22:55 ad-joiner1@CORP.CONTOSO.COM
    3 08/2414 22:22:55 ad-joiner1@CORP.CONTOSO.COM
    3 08/2414 22:22:55 ad-joiner1@CORP.CONTOSO.COM

Checking the Implementation (Do)

In order to verify that the keytab file works and can join or remove a system, you need an unjoined Unix, Linux or Mac system with the Centrify agent installed.
  1. Log into the system with a local account (that can elevate)
  2. Make the keytab file securely accessible.
  3. Copy the /etc/krb5.conf file from a working Centrified system to the local system:
    scp <account>@centrified.system:/etc/krb5.conf /etc/krb5.conf
  4. Use the kinit command with the kt option to get a ticket-granting-ticket as the ad-joiner account.
    /usr/share/centrifydc/kerberos/bin/kinit ad-joiner -kt ad-joiner.keytab
  5. Use the adjoin command without specifying the user option.  Adjoin is Kerberized and it will use the ad-joiner's ticket-granting ticket.
    # adjoin -z Model -c "ou=servers,ou=unix" corp.contoso.com
    Using domain controller:  dc2.corp.contoso.com writeable=true
    Join to domain: corp.contoso.com, zone: Model succesful

    Centrify DirectControl started
    Initializing cache
  6. At this point the computer has joined the domain.
  7. You can use it for the reverse with adleave.
    # adleave -r 
    Using domain controller:  dc2.corp.contoso.com writeable=true
    Left domain.
    Centrify DirectControl stopped.

Adjusting the Process

There are many opportunities to adjust this process and make it better.  Here are some examples:
  • The process can be part of a script that specifies things like zones, computer roles, etc.
  • ADEdit can be used to pre-create the account in the zone and move the computer to the proper computer role.
  • The keytab can be deleted from the local host as part of the script termination process process

Video