Tuesday, September 20, 2016

Using Centrify-enhanced sudo (dzdo) validator with ServiceNow requests

Background
Regulatory frameworks have evolved to require documented evidence of approval for development or infrastructure-related change control.  These activities usually require the exercise of elevated privileges.  Some examples of these requirements and guidelines can be found on PCI DSS, SANS Critical Security controls, ISO 27001 and others:
  doc-approvals.png

Centrify DirectAuthorize and DirectAudit provide end-to-end, role-based access controls for UNIX, Linux and Windows, in addition it provides mechanisms for validation and tracking of changes via ticketing or request systems.

Requirements
We've had customers that have two categories of requirements:
  • Tracking activities related to a particular change control or approved request
    For example: We want to track all privileged activities related to a change control in my security operations dashboard.
    We covered this on this on the original dzdo validator article.  When privileges are elevated, entries in both syslog or DirectAuthorize get created automatically.
    Using Centrify-enhanced sudo:
    $ dzdo tail /var/log/messages
    Enter the change control ticket number:1255
    
    syslog:
    Nov  7 15:04:39 engcen6 dzcheck.sample[35173]: User "dwirth@centrify.vms" will run "/usr/bin/tail /var/log/messages" as "root" with ticket number "1255"
    
    DA Console:
    DirectAudit Analyzer - dzdo.validator event.jpg
  • Implementing controls to prevent unauthorized changes
    For example:  We want to make sure that any privilege elevation is only allowed with an approved request.
    This lab covers a basic lab setup to implement this requirement.

Lab Diagram
dzdo-validator-lab.png

What you'll need:
  • Centrify Standard Edition and a Centrify Zone with some UNIX roles defined
  • An AD-joined UNIX or Linux  system in the Centrify zone
    The system should be able to reach the ServiceNow instance directly, via proxy or via ServiceNow MIDServer.
  • A DirectAuthorize role for UNIX
  • A ServiceNow instance (Fuji release minimum) and a shared credential or token to query existing requests
    Make sure that the credential only has the minimal rights (e.g. read-only) for your requests.
  • Optional:  Centrify Privilege Service (Saas or On-Prem) to vault the SN user's credential. 

Use Case
  1. Privileged user obtains a change control manager approval via ServiceNow workflow request.
    The request has a change control window.  (date/time range)
  2. During the request validity timeframe, the privileged user needs to perform activities (using Centrify-ehnanced sudo) and when the commands are issued, the SN request number has to be provided.
  3. The dzdo.validator script uses the ServiceNow Perl API to validate if the request is approved or not.
    Additional validations can be added like user, time-range, etc;  these won't be covered for blog brevity.
  4. If the request is a approved, the Centrify-enhanced sudo command is allowed to execute.  If not, the user is notified.

Implementation  Overview
  1. Install the ServiceNow Perl API
  2. Test ServiceNow Instance connectivity
  3. Optional:  Protect the shared credential using Privilege Service
  4. Modify one of the sample scripts to work with ServiceNow Requests
  5. Modify the dzdo.validator script to call the ServiceNow Perl API script
  6. Implement the dzdo.validator via parameter or GPO
  7. Test your results

Install the ServiceNow Perl API
The full instructions and requirements are here: 
http://wiki.servicenow.com/index.php?title=Perl_API#gsc.tab=0
  1. Make sure you have the appropriate Perl plugins  (e.g. CentOS 6.x):
    SOAP::Lite  (e.g. yum install perl-SOAP-Lite)
    Crypt::SSLeay (e.g. yum install perl-Crypt-SSLeay)
    IO::Socket::SSL ( e.g. yum install perl-IO-Socket-SSL)
    File::Basename
    MIME::Types (e.g. yum install perl-MIME-Types)
    MIME::Type
    MIME::Base64
  2. Download the Servicenow Perl API  (link to 1.01 version) to your UNIX/Linux system
  3. Unzip the file in a new folder and run the following commands:
    ## create a new folder, download and unzip
    $ mkdir SN
    $ cd SN
    $ wget http://wiki.servicenow.com/images/e/e5/ServiceNow-Perl-API.zip
    $ unzip ServiceNoW-Perl-API.zip
    ## compile the files  
    $ perl Makefile.PL
    $ make
    $ make test
    $ make install
    Follow the prompts, once you have all the ServiceNow Perl API libraries installed to use with your scripts.

Testing Connectivity with your ServiceNow Instance (Sample Script)
  1. Create a new file with these contents
    # This script retrieves all the requests from your servicenow instance
    # it is used to test connectivity.
    #!/usr/bin/perl -w
    
    use ServiceNow;
    use ServiceNow::Configuration;
    
    # This example uses Centrify Privilege Service's AAPM capability
    # by checking-out the password from the vault at runtime, we eliminate
    # the need to use a cleartext password in this script.
    # uses cgetaccount to check out the password for your-SN-user for 3 mins.
    # Alternatively you can enable OAuth and use Tokens (recommended)
    
    $SN_PASSWD = `cgetaccount -s -t 3 your-SN-user`;
    
    my $CONFIG = ServiceNow::Configuration->new();
    
    $CONFIG->setSoapEndPoint("https://your-instance.service-now.com/");
    $CONFIG->setUserName("your-SN-user");
    $CONFIG->setUserPassword($SN_PASSWD);
    
    my $SN = ServiceNow->new($CONFIG);
    
    my @requests = $SN->queryRequestedItem();
    my $count = scalar(@requests);
    print "Number of requests=" . $count . "\n";
    foreach my $request (@requests) {
        print "Request number: $request->{'number'}\n";
        print "Requested by: $request->{'sys_created_by'}\n";
        print "Date Created: $request->{'sys_created_on'}\n";
        print "Approval Status: $request->{'approval'}\n";
        print "\n"
    
 2. To test the script, add the execution flag and run it
$ chmod +x checksn.sh
$ ./inc2.sh
Number of requests=34
Request number: RITM0000002
Requested by: fred.luddy
Date Created: 2016-05-02 18:15:39
Approval Status: requested

Request number: RITM0000004
Requested by: fred.luddy
Date Created: 2016-09-03 17:15:39
Approval Status: requested

Request number: RITM0000005
Requested by: fred.luddy
Date Created: 2016-05-22 19:15:43
Approval Status: requested
[output truncated]


Modify the Sample Script to work with Individual Ticket Numbers
To do this, you need to change the script to require arguments and check for usage.   The modified lines would look like this:

#!/usr/bin/perl -w

# You're checking for arguments here.  If there are no arguments
# show the usage and exit.  E.g.  checksn RTM00005

if (@ARGV)  {

# The previous program can go here.  Make sure you modify this line
# to look like this:

my @requests = $SN->queryRequestedItem({'number'=> $1})


}  else {
          print "USAGE:  checksn [ServiceNow Request ID]\n"
}
   
Note that there's no error logic for requests that are not found.  We're going to have to add this later.

Modify the dzdo.validator script to to use the ServiceNow Perl API script
 Centrify provides a sample dzdo validator script called dzcheck.sample.  This script exists under /usr/share/centrifydc/bin.
With the author's limited scripting knowledge we were able to modify it to work this way:

  • Initialize the proper libraries and variables
  • Retrieve the password for the ServiceNow user (your-user) and store it in SN_PASSWD
  • Connect to ServiceNow instance
  • Prompt the user for a Change Control number
  • If the number is not found, log to syslog and the user will not be allowed to run the command
  • If the number is found but the status is not approved, log to syslog and the user will not be allowed to run the command
  • If the number is found and approved, log to syslog and allow the end user to run the command.
Note that additional error logic and checks can be added.

#!/bin/sh /usr/share/centrifydc/perl/run
# A modified demo for Centrify-enhanced sudo (dzdo) validator 
# Modified to work with ServiceNow Requests

use strict;

use lib "../perl";
use lib '/usr/share/centrifydc/perl';
use CentrifyDC::Logger;

use ServiceNow;
use ServiceNow::Configuration;
# Use privilege service to retrieve SN shared account password
# Alternatively, you can modify the script to use an OAuth token 
my $SN_PASSWD = `cgetaccount -s -t 3 your-user`;

my $dzdo_user=$ENV{DZDO_USER};
my $dzdo_command=$ENV{DZDO_COMMAND};
my $dzdo_runasuser=$ENV{DZDO_RUNASUSER};

my $CONFIG = ServiceNow::Configuration->new();

$CONFIG->setSoapEndPoint("https://your-instance.service-now.com/");
$CONFIG->setUserName("your-user");
$CONFIG->setUserPassword($SN_PASSWD);

my $SN = ServiceNow->new($CONFIG);
my $logger = CentrifyDC::Logger->new('dzcheck');

printf STDERR "Enter the change control ticket number: ";
my $user_input=<>;

my @requests = $SN->queryRequestedItem({'number' => $user_input});

# Check if request(s) exist, if not, exit (1)
if (scalar(@requests)==0)
{
  system "adsendaudittrailevent", "-t", "tkt_id", "-i", "$user_input";
  $logger->log('INFO', "Change control ticket number: %s", $user_input);
  $logger->log('INFO', "User \"%s\" will not be allowed to run \"%s\" as \"%s\" with ticket number (REASON:not found) \"%s\"", $dzdo_user, $dzdo_command, $dzdo_runasuser, $user_input);

  exit 1;
}

foreach my $request (@requests) {

my $req_status =  $request->{'approval'};

# Exit if request is not in approved status
if ($req_status ne "approved")
    {
     system "adsendaudittrailevent", "-t", "tkt_id", "-i", "$user_input";
     $logger->log('INFO', "Change control ticket number: %s", $user_input);
     $logger->log('INFO', "User \"%s\" will not be allowed to run \"%s\" as \"%s\" with ticket number (REASON:not approved) \"%s\"", $dzdo_user, $dzdo_command, $dzdo_runasuser, $user_input,$req_status);
  exit 2;
     }
}

# Run command and log if request is approved
system "adsendaudittrailevent", "-t", "tkt_id", "-i", "$user_input";
my $logger = CentrifyDC::Logger->new('dzcheck');

$logger->log('INFO', "Change control ticket number: %s", $user_input);
$logger->log('INFO', "User \"%s\" will run \"%s\" as \"%s\" with ticket number \"%s\"", $dzdo_user, $dzdo_command, $dzdo_runasuser, $user_input);

exit 0;
I've saved this script as dzcheck.snow in the same location.

Configure Centrify-enhanced sudo (dzdo) to use the ServiceNow Requests validator
  1. Open the /etc/centrifydc/centrifydc.conf file for editing
  2. Uncomment the dzdo.validator and set it to our scripts
    dzdo.validator: /usr/share/centrifydc/sbin/dzcheck.snow
  3.  Perform and adreload (or restart the agent)

Testing
We'll use a modified version of the sample script to check the requests for validity first, then we'll try to flush the cache using dzdo.
  1. Ticket does not exist  (ABC123)
    Request verification
    $ ./sncheck ABC123
    Request not found.
    $ dzdo adflush
    Enter the change control ticket number: ABC123
    Sorry, user dwirth is not allowed to execute '/usr/sbin/adflush' as root on engcen6.centrify.vms.
    
    # syslog contents
    Sep 20 18:00:52 engcen6 dzcheck.snow[35963]: Change control ticket number: ABC123
    Sep 20 18:00:52 engcen6 dzcheck.snow[35963]: User "dwirth@centrify.vms" will not be allowed to run "/usr/sbin/adflush" as "root" with ticket number (REASON:not found) "ABC123#012"
    Sep 20 18:00:52 engcen6 adclient[1526]: INFO  AUDIT_TRAIL|Centrify Suite|dzdo|1.0|1|dzdo denied|5|user=dwirth(type:ad,dwirth@CENTRIFY.VMS) pid=35961 utc=1474412452436 centrifyEventID=30001 status=DENIED service=dzdo command=/usr/sbin/adflush runas=root reason=Dzdo Validator checks failed. Do not permit to continue the privileged command.
  2. Ticket is not approved (RITM0010022)
    Request verification:
    $ ./sncheck RITM0010022
    number of requests=1
    Request number: RITM0010022
    Requested by: robertson.pimentel@centrify.com
    Date Created: 2016-09-16 16:55:06
    Approval Status: requested

    $ dzdo adflush
    Enter the change control ticket number: RITM0010022
    Sorry, user dwirth is not allowed to execute '/usr/sbin/adflush' as root on engcen6.centrify.vms.
    
    # syslog content
    Sep 20 18:03:04 engcen6 dzcheck.snow[36011]: Change control ticket number: RITM0010022
    Sep 20 18:03:04 engcen6 dzcheck.snow[36011]: User "dwirth@centrify.vms" will not be allowed to run "/usr/sbin/adflush" as "root" with ticket number (REASON:not approved) "RITM0010022#012"
    Sep 20 18:03:04 engcen6 adclient[1526]: INFO  AUDIT_TRAIL|Centrify Suite|dzdo|1.0|1|dzdo denied|5|user=dwirth(type:ad,dwirth@CENTRIFY.VMS) pid=36009 utc=1474412584884 centrifyEventID=30001 status=DENIED service=dzdo command=/usr/sbin/adflush runas=root reason=Dzdo Validator checks failed. Do not permit to continue the privileged command
  3. Ticket is approved (RITM001003)
    $ ./sncheck RITM0010003
    number of requests=1
    Request number: RITM0010003
    Requested by: diego.jimenez@centrify.com
    Date Created: 2016-09-11 14:57:57
    Approval Status: approved

    $ dzdo adflush
    Enter the change control ticket number: RITM0010003
    Demo Password:
    DNS cache flushed successfully.
    Authorization cache store flushed successfully.
    GC and DC caches expired successfully.
    The auditing service's name cache has been successfully flushed.
    The DirectAudit installation information cache has been successfully flushed.
    
    # syslog content
    Sep 20 18:06:22 engcen6 dzcheck.snow[36108]: Change control ticket number: RITM0010003
    Sep 20 18:06:22 engcen6 dzcheck.snow[36108]: User "dwirth@centrify.vms" will run "/usr/sbin/adflush" as "root" with ticket number "RITM0010003#012"
    Sep 20 18:06:22 engcen6 adclient[1526]: INFO  AUDIT_TRAIL|Centrify Suite|dzdo|1.0|0|dzdo granted|5|user=dwirth(type:ad,dwirth@CENTRIFY.VMS) pid=36106 utc=1474412782119 centrifyEventID=30000 status=GRANTED service=dzdo command=/usr/sbin/adflush runas=root role=UNIX Sysadmin/Global env=(none)

Benefits if you're using DirectAudit
If you have Enterprise Edition, DirectAudit's events will contain information about the Change Control and you can now search for all activity related to an individual change control number.
ben-da.png

Benefits if you're using the Centrify Splunk App
The Splunk App will display reports on the reasons why the privilege elevation failed.  You can also add alerts based on this to identify any privileged user trying to fish.
ben-splunk.png

Improvements
This is a lab blog post, therefore this is just a simple concept, but here are the improvements I'd make:
  • Use OAuth tokens for ServiceNow instead of a shared credential
    http://wiki.servicenow.com/index.php?title=OAuth_Setup#gsc.tab=0
  • Compare the date of execution with the change control date range (we only did simple checks)
  • Provide better feedback to the user interactively
  • Allow the user to create a request if it's not in the system and notify the approver (cli-driven workflow)

Quick Overview Video

 Notes:  ServiceNow, PCI DSS, SANS and ISO 27001 logos are registered trademarks of their respective owners.

Monday, September 12, 2016

Enabling Centrify Identity Service and Privilege Service for Smart Card Authentication

Background
Many governmental and commercial organizations have implemented smart cards as their preferred method for Multi-factor Authentication.  This post explains how to configure Centrify Identity Service (CIS) or Centrify Privilege Service (CPS) to provide authentication using Smart Cards.  This article provides the configuration steps to enable Smartcard (certificate)-based authentication for CIS or CPS.

How it works
Generally, cryptographic credentials (user certificates) are stored in the smart card (PIV or CAC card) and the system has a dedicated reader.   Upon successful authentication (credentials verified and PIN submitted) the operating system or application will use a standard protocol (like Kerberos) or a one-time-code to grant access to the system or application.

For example, Centrify Server Suite allows the user of Kerberos for SSO to applications like Secure Shell (SSH).  Our DirectAuthorize can enforce if the user is allowed to log in with a password or with Kerberos/GSSAPI only.

In the case of Identity Service and Privilege Service, we use a Centrify capability called Zero Sign-on (SZO).  SZO provides a one-time token to use for authentication if the Authentication Profile that applies to the user is configured for Certificate-based Authentication.  All the user needs to do is navigate to the CIS/CPS site, select the smart card certificate and PIN.
pki-cis-cps.png
This setup provides strong authentication to access Apps or for Privileged Identity Management scenarios.

What you'll need:
  1. An instance of Centrify Identity Service App+ or Privilege Service  (CPS can be SaaS or On-Prem)
  2. Public Key Infrastructure Infrastructure  (Enterprise CA, Revocation Infrastructure, well-configured PKI clients) and understanding of how the subject name is being provisioned.
  3. A copy of the Certificate Chain (or Root CA) for your PKI infrastructure.
  4. A SmartCard or Yubikey configured for authentication into your environment.
    This post contains instructions to set up a lab. See "Lab - Base Setup"
Strong Disclaimer:  This is a PKI-related topic.  You should always be workign with your PKI SME with anything related to certificates, trust chains, revocations, etc.

Configuration Overview
The configuration depends on the deployment option of the service.
  1. Configuring the Root CA in Identity Service App+ or Privilege Service
  2. Configuring a Policy that allows for Integrated Windows Authentication
  3. Testing the configuration
  4. Appendix:  Configure Privilege Service On-Premises CNAME and Zero Sign-on SSL Certificate
Configuring the Root CA in Identity Service App+ or Privilege Service (SaaS)
  1. Sign-in to Cloud Manager
  2. Go to Settings > Authentication > Certificate Authorities
    Note:  If you can't see the Certificate Authorities option, you're not running the App+ edition or in the case of Privilege Service on-premises, you have to perform the activation steps (see below).
  3. Press Add and complete the follwing information:
    add-ca.png
    Name:  descriptive name of the CA
    Extract login name from:  The options are
    a) Principal Name from Subject Alternate Name
    b) E-mail address field from Subject Alternate Name
    c) Username from Subject
  4. Click Browse and select the location of the root ca certificate.
  5. If you are confident that you have a highly-distributed (Internal & Internet facing) Certificate revocation infrastructure, check the "Enable Client Certificate Revocation Check" if you are not sure un-check the box for now.
    Note:  If you don't know what PKI certificate revocation is, it's time to find your in-house PKI expert and get him or her involved.  This is a serious topic.
  6. Press Save
Configuring a Policy that allows for Integrated Windows Authentication
  1. Sign-in to Cloud Manager
  2. Go to Policies > [Select your Test Policy] > Expand User Security Policies > Login Authentication
  3. Set the "Enable authentication policy controls" setting to Yes, if not selected.
  4. Scroll down to "Other Settings" and make sure that the "Allow IWA connections..." is checked.  Then note the following:
    Note: Certificate-based authentication bypasses the login authentication rules set up for that profile.  The key settings are:
    cert-options.png
    The first setting "Use certificates for authentication..." is the main switch.  If you un-check this box, the users in scope for this policy won't be able to use smart cards for authentication.  This bypasses any controls set under "Login Authentication" in the preceding section.
    The second setting  "Set identity cookie..."  controls whether the cookie is set for the browser.   I would not set this flag if you expect users to access via non-managed systems.
    The third setting "Accept connections using certificate..." defines whether if users logging in with smart cards or certs are treated as "strongly-authenticated"

    Make your selections based on your desired security posture.
  5. Press Save.

Testing your configuration
  1.  Navigate to your Identity Service or Privilege Service URL
  2. Depending if your browser is configured correctly, you'll see any of the following pop-ups will come up:
    cert-challenge.png
  3. After selecting the Certificate on the Smart Card, you'll be prompted for the PIN:
    pin-cert.png
  4. Once you type-in the PIN, you'll be redirected to the appropriate portal (User | Cloud Manager | Privilege Manager).

Quick Setup Video


Appendix 1:  Enabling Certificate Authorities for Centrify Privilege Service (On-Premises)
Background:  Centrify Privilege Service can be deployed on premises on a Windows Server 2012 R2 system.  You need a CNAME record for the Zero Sign-On website and a x.509 certificate with that DNS name.

Pre-requisite tasks:
a) Set-up a DNS CNAME record to with the name hostname[zso].domain.name pointing to the hostname.domain.name.  E.g. if your system name is app1.corp.contoso.com, create a CNAME record to app1zso.corp.contoso.com and point it to the original host name.
b) You need an SSL Certificate with the DNSname for the SZO special host.

  1. Log in to the server hosting Centrify Privilege Service
  2. Open an Administrative PowerShell and navigate to %Programfiles%\Centrify\Centrify Identity Platform\Scripts
  3. Run the setup_certauth.ps1 script.   The program will ask if the pre-requisites have been met.
    setup_certhauth.png
  4. Confirm and you'll be prompted to provide the x.509 (SSL) cert for the SZO site.
  5. Once completed, you can return to Cloud Manager and perform the steps outlined above in the:  "Configuring the Root CA in Identity Service App+ or Privilege Service (SaaS)" section.

Other Resources and Related Topics
Documentation:  https://stage-docs.centrify.com/en/centrify/adminref/index.html?version=141#page/cloudhelp%2FCloud_Policy.13.html
Centrify's support for Derived Credentials: 
- Blog: https://www.centrify.com/products/identity-service/emm/derived-credentials/

- Docs:  https://docs.centrify.com/en/centrify/adminref/index.html?version=141#page/cloudhelp%2FderivedCreds.html

This article was originally written as a Centrify Tech Blog.