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:
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:
Lab Diagram
What you'll need:
Use Case
Implementation Overview
Install the ServiceNow Perl API
The full instructions and requirements are here:
http://wiki.servicenow.com/index.php?title=Perl_AP I#gsc.tab=0
Testing Connectivity with your ServiceNow Instance (Sample Script)
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:
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:
Configure Centrify-enhanced sudo (dzdo) to use the ServiceNow Requests validator
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.
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.
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.
Improvements
This is a lab blog post, therefore this is just a simple concept, but here are the improvements I'd make:
Quick Overview Video
Notes: ServiceNow, PCI DSS, SANS and ISO 27001 logos are registered trademarks of their respective owners.
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:
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: - 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
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
- Privileged user obtains a change control manager approval via ServiceNow workflow request.
The request has a change control window. (date/time range) - 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.
- 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. - If the request is a approved, the Centrify-enhanced sudo command is allowed to execute. If not, the user is notified.
Implementation Overview
- Install the ServiceNow Perl API
- Test ServiceNow Instance connectivity
- Optional: Protect the shared credential using Privilege Service
- Modify one of the sample scripts to work with ServiceNow Requests
- Modify the dzdo.validator script to call the ServiceNow Perl API script
- Implement the dzdo.validator via parameter or GPO
- Test your results
Install the ServiceNow Perl API
The full instructions and requirements are here:
http://wiki.servicenow.com/index.php?title=Perl_AP
- 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 - Download the Servicenow Perl API (link to 1.01 version) to your UNIX/Linux system
- 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-
Follow the prompts, once you have all the ServiceNow Perl API libraries installed to use with your scripts.Perl-API.zip $ unzip ServiceNoW-Perl-API.zip ## compile the files $ perl Makefile.PL $ make $ make test $ make install
Testing Connectivity with your ServiceNow Instance (Sample Script)
- 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"
$ 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.
#!/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
- Open the /etc/centrifydc/centrifydc.conf file for editing
- Uncomment the dzdo.validator and set it to our scripts
dzdo.validator: /usr/share/centrifydc/sbin/dzcheck.snow
- 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.
- 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.
- 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
- 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.
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.
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.