18 December,19 at 11:50 AM
Background
Note: this is a companion article to the blog post titled: "[HOWTO] Orchestration Basics - Using a Chef recipe to deploy Centrify and join Active Directory"; these posts are relatively identical, the only difference is the tool.
In the field, we often get inquiries on deployment, governance or orchestration frameworks. Common questions range from: how do I deploy the Centrify client? or How do I establish an approval flow for the Access Control model that you facilitate?
Sometimes we also hear these questions: We use Ansible | Bladelogic | Chef | Puppet in on premise or with our IaaS (cloud) deployment, how would I go about deploying your product using those tools?
These are important questions, especially in the age of private/public clouds and elastic environments. Some of you are adopting frameworks like OpenStack, Amazon AWS or Microsoft Azure that underneath use these toolsets.
At Centrify we have invested heavily through the years to make sure that the products "just work". From a deployment perspective, we our messaging is consistent:
In other words, Centrify software is easier to use in these scenarios than what the typical IT Infrastructure lead may think.
Disclaimers and Acknowledgements
What is required?
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
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:
Building Blocks
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.
Install Puppet and the wget Extension
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 straightCreate and test your stand-alone Puppet Script
To recap, the sequence to automate Installation and joins is as follows:
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
Verify the recipe
$ 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
Adjustments
There are absolutely many improvements that can be made. Here are a few that come to mind (in no specific order):