IBM Support

IBM Security Secret Server - REST API Perl Scripts

White Papers


Abstract

Getting started using Perl and Secret Server REST APIs.

Content

Secret Server web services can be called using scripts. This example demonstrates how to authenticate and retrieve a Secret programmatically in Perl.

If connecting to an Installed instance change the URL to match your site and specify the application name if configured.

This example runs using standard Perl modules and using Strawberry Perl v5.24.1.1. You may have to install REST::Client from CPAN which can be done by running:
cpanm REST::Client

This module makes interacting with REST-ful API's much easier.

The TSS script below leverages the API created in the ISSS with .pm extension file. The TokenResponse with .pm extension file defines an object that stores the authentication credentials for the session. The ErrorResponse with .pm extension file defines an object that stores error information should a REST request fail. And, the SecretModel with .pm extension file defines an object that stores the Secret information when requesting a particular Secret from the REST API.

ISSS.pl:
 
use REST::Client;
use JSON;

use ISSS;

# Enter your Secret Server web site here.
my $host = 'http://localhost';;

# Enter the application name, should it be defined.
my $applicationPath = '/secretserver';

my $false = 0;
my $true = 1;
my $usingSelfSignedCertificate = $true;

if ($usingSelfSignedCertificate) {
    # Disable hostname validation since this will fail with self-singed certs.
    $ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = $false;
}

# Initialize the ISSS Perl API with the connection information provided above.
my $isss = ISSS->new(
		secretServerUrl => $host,
		applicationPath => $applicationPath
	);

print "Username: ";
my $input = <STDIN>;
chomp $input;
my $username = $input;

print "Password: ";
$input = <STDIN>;
chomp $input;
my $password = $input;

# Authenticate to Secret Server
my $response = $isss->getToken($username, $password);
if (ref $response eq 'ErrorResponse') {
	$isss->handleError($response);
	exit();
}

# Persist the API token in our ISSS API session.
$isss->tokenResponse($response);

$password = undef;

print "Secret ID to retrieve: ";
$input = <STDIN>;
chomp $input;
my $secretId = $input;

# Retrieve a Secret from Secret Server by Secret ID.
$response = $isss->getSecret($secretId);
if (ref $response eq 'ErrorResponse') {
	$isss->handleError($response);
	exit();
}

# Read the SecretModel object
print 'Secret ' . $response->id . ' retrieved successfully. Secret name: ' . $response->name . "\r\n";


ISSS.pm:


package ISSS;

use REST::Client;
use JSON;

use TokenResponse;
use ErrorResponse;
use SecretModel;

use strict;

sub new {
	my($class, %args) = @_;

    my $self = {
    	client => REST::Client->new(),
    	secretServerUrl => undef,
    	applicationPath => undef,
    	tokenResponse => undef,
    	%args
    };
    bless $self, $class;

    $self->client->setHost($self->secretServerUrl);

    return($self);
}

sub client {
	my $self = shift;
	return $self->{client};
}

sub secretServerUrl {
	my $self = shift;
	return $self->{secretServerUrl};
}

sub applicationPath {
	my $self = shift;
	return $self->{applicationPath};
}

# Getter and setter so that API tokens can be reused through a session.
sub tokenResponse {
	my $self = shift;
	my $tokenResponse = shift;

	if ($tokenResponse ne undef) {
		$self->{tokenResponse} = $tokenResponse;
		return $tokenResponse;
	}

	return $self->{tokenResponse};
}

# Crafts a HTTP header for providing authentication to Secret Server.
sub getHeaders {
	my $self = shift;

	my $headers = {
		Accept => 'application/json',
		Authorization => 'Bearer ' . $self->tokenResponse->access_token 
	};

	return $headers;
}

sub handleError {
	my $self = shift;
	my $errorResponse = shift;

	print 'ERROR|' . $errorResponse->message . ' (Error Code: ' . $errorResponse->errorCode . ')' . "\r\n";
}

# Authenticates to Secret Server by POST'ing a Form URL Encoded content body containing sensitive credentials.
sub getToken {
	my $self = shift;
	my $username = shift;
	my $password = shift;

	my $postParams = $self->client->buildQuery([
			username => $username,
			password => $password,
			grant_type => "password"
		]);

	my $response = $self->client->POST($self->applicationPath . '/oauth2/token', substr($postParams, 1), {'Content-Type' => 'application/x-www-form-urlencoded'});
	
    if ($self->client->responseCode() ne 200) { 
        my $errorResponse = ErrorResponse->new(
                errorCode => $self->client->responseCode(), 
                message => "Unable to get token." 
            ); 
        
        return $errorResponse;
    }

    my $responseJson = from_json($response->responseContent);

	if (exists $responseJson->{'errorCode'}) {
		my $errorResponse = ErrorResponse->new(
				errorCode => $responseJson->{'errorCode'},
				message => $responseJson->{'message'}
			);

		return $errorResponse;
	}

	my $tokenResponse = TokenResponse->new(
			access_token => $responseJson->{'access_token'},
			token_type => $responseJson->{'token_type'},
			expires_in => $responseJson->{'expires_in'}
		);

	return $tokenResponse;
}

# Gets a Secret from Secret Server by GET'ing a specified Secret by ID and passing an authentication header containing our API token.
sub getSecret {
	my $self = shift;
	my @params = @_;
	my $secretId = $params[0];

	my $headers = $self->getHeaders();

	$self->client->GET($self->applicationPath . '/api/v1/secrets/' . $secretId, $headers);
    my $responseJson = from_json($self->client->responseContent());

	if (exists $responseJson->{'errorCode'}) {
		my $errorResponse = ErrorResponse->new(
				errorCode => $responseJson->{'errorCode'},
				message => $responseJson->{'message'}
			);

		return $errorResponse;
	}

	my $secretModel = SecretModel->new(
			id => $responseJson->{'id'},
			name => $responseJson->{'name'},
			secretTemplateId => $responseJson->{'secretTemplateId'},
			folderId => $responseJson->{'folderId'},
			active => $responseJson->{'active'},
			items => $responseJson->{'items'},
			launcherConnectAsSecretId => $responseJson->{'launcherConnectAsSecretId'},
			checkOutMinutesRemaining => $responseJson->{'checkOutMinutesRemaining'},
			checkedOut => $responseJson->{'checkedOut'},
			checkOutUserDisplayName => $responseJson->{'checkOutUserDisplayName'},
			checkOutUserId => $responseJson->{'checkOutUserId'},
			isRestricted => $responseJson->{'isRestricted'},
			isOutOfSync => $responseJson->{'isOutOfSync'},
			outOfSyncReason => $responseJson->{'outOfSyncReason'},
			autoChangeEnabled => $responseJson->{'autoChangeEnabled'},
			autoChangeNextPassword => $responseJson->{'autoChangeNextPassword'},
			requiresApprovalForAccess => $responseJson->{'requiresApprovalForAccess'},
			requiresComment => $responseJson->{'requiresComment'},
			checkOutEnabled => $responseJson->{'checkOutEnabled'},
			checkOutIntervalMinutes => $responseJson->{'checkOutIntervalMinutes'},
			checkOutChangePasswordEnabled => $responseJson->{'checkOutChangePasswordEnabled'},
			proxyEnabled => $responseJson->{'proxyEnabled'},
			sessionRecordingEnabled => $responseJson->{'sessionRecordingEnabled'},
			restrictSshCommands => $responseJson->{'restrictSshCommands'},
			allowOwnersUnrestrictedSshCommands => $responseJson->{'allowOwnersUnrestrictedSshCommands'},
			isDoubleLock => $responseJson->{'isDoubleLock'},
			doubleLockId => $responseJson->{'doubleLockId'},
			enableInheritPermissions => $responseJson->{'enableInheritPermissions'},
			passwordTypeWebScriptId => $responseJson->{'passwordTypeWebScriptId'},
			siteId => $responseJson->{'siteId'},
			enableInheritSecretPolicy => $responseJson->{'enableInheritSecretPolicy'},
			secretPolicyId => $responseJson->{'secretPolicyId'},
			lastHeartBeatStatus => $responseJson->{'lastHeartBeatStatus'},
			lastHeartBeatCheck => $responseJson->{'lastHeartBeatCheck'},
			failedPasswordChangeAttempts => $responseJson->{'failedPasswordChangeAttempts'},
			lastPasswordChangeAttempt => $responseJson->{'lastPasswordChangeAttempt'},
			secretTemplateName => $responseJson->{'secretTemplateName'},
			responseCodes => $responseJson->{'responseCodes'}
		);

	return $secretModel;
}

1;





package TokenResponse;

use warnings;
use strict;

sub new {
	my $class = shift;
	my %options = @_;

	my $self = {
		access_token => undef,
		token_type => undef,
		expires_in => undef,
		%options
	};
	bless $self, $class;
	
	return $self;
}

sub access_token {
	my $self = shift;
	return $self->{access_token};
}

sub token_type {
	my $self = shift;
	return $self->{token_type};
}

sub expires_in {
	my $self = shift;
	return $self->{expires_in};
}

1;



package ErrorResponse;

use warnings;
use strict;

sub new {
	my $class = shift;
	my %options = @_;

	my $self = {
		errorCode => undef,
		message =>  undef,
		%options
	};
	bless $self, $class;
	
	return $self;
}

sub errorCode {
	my $self = shift;
	return $self->{errorCode};
}

sub message {
	my $self = shift;
	return $self->{message};
}

1;



package SecretModel;

use warnings;
use strict;

sub new {
	my $class = shift;
	my %options = @_;

	my $self = {
		id => undef,
		name => undef,
		secretTemplateId => undef,
		folderId => undef,
		active => undef,
		items => undef,
		launcherConnectAsSecretId => undef,
		checkOutMinutesRemaining => undef,
		checkedOut => undef,
		checkOutUserDisplayName => undef,
		checkOutUserId => undef,
		isRestricted => undef,
		isOutOfSync => undef,
		outOfSyncReason => undef,
		autoChangeEnabled => undef,
		autoChangeNextPassword => undef,
		requiresApprovalForAccess => undef,
		requiresComment => undef,
		checkOutEnabled => undef,
		checkOutIntervalMinutes => undef,
		checkOutChangePasswordEnabled => undef,
		proxyEnabled => undef,
		sessionRecordingEnabled => undef,
		restrictSshCommands => undef,
		allowOwnersUnrestrictedSshCommands => undef,
		isDoubleLock => undef,
		doubleLockId => undef,
		enableInheritPermissions => undef,
		passwordTypeWebScriptId => undef,
		siteId => undef,
		enableInheritSecretPolicy => undef,
		secretPolicyId => undef,
		lastHeartBeatStatus => undef,
		lastHeartBeatCheck => undef,
		failedPasswordChangeAttempts => undef,
		lastPasswordChangeAttempt => undef,
		secretTemplateName => undef,
		responseCodes => undef,
		%options
	};
	bless $self, $class;
	
	return $self;
}

sub id {
  my $self = shift;
  return $self->{id};
}

sub name {
  my $self = shift;
  return $self->{name};
}

sub secretTemplateId {
  my $self = shift;
  return $self->{secretTemplateId};
}

sub folderId {
  my $self = shift;
  return $self->{folderId};
}

sub active {
  my $self = shift;
  return $self->{active};
}

sub items {
  my $self = shift;
  return $self->{items};
}

sub launcherConnectAsSecretId {
  my $self = shift;
  return $self->{launcherConnectAsSecretId};
}

sub checkOutMinutesRemaining {
  my $self = shift;
  return $self->{checkOutMinutesRemaining};
}

sub checkedOut {
  my $self = shift;
  return $self->{checkedOut};
}

sub checkOutUserDisplayName {
  my $self = shift;
  return $self->{checkOutUserDisplayName};
}

sub checkOutUserId {
  my $self = shift;
  return $self->{checkOutUserId};
}

sub isRestricted {
  my $self = shift;
  return $self->{isRestricted};
}

sub isOutOfSync {
  my $self = shift;
  return $self->{isOutOfSync};
}

sub outOfSyncReason {
  my $self = shift;
  return $self->{outOfSyncReason};
}

sub autoChangeEnabled {
  my $self = shift;
  return $self->{autoChangeEnabled};
}

sub autoChangeNextPassword {
  my $self = shift;
  return $self->{autoChangeNextPassword};
}

sub requiresApprovalForAccess {
  my $self = shift;
  return $self->{requiresApprovalForAccess};
}

sub requiresComment {
  my $self = shift;
  return $self->{requiresComment};
}

sub checkOutEnabled {
  my $self = shift;
  return $self->{checkOutEnabled};
}

sub checkOutIntervalMinutes {
  my $self = shift;
  return $self->{checkOutIntervalMinutes};
}

sub checkOutChangePasswordEnabled {
  my $self = shift;
  return $self->{checkOutChangePasswordEnabled};
}

sub proxyEnabled {
  my $self = shift;
  return $self->{proxyEnabled};
}

sub sessionRecordingEnabled {
  my $self = shift;
  return $self->{sessionRecordingEnabled};
}

sub restrictSshCommands {
  my $self = shift;
  return $self->{restrictSshCommands};
}

sub allowOwnersUnrestrictedSshCommands {
  my $self = shift;
  return $self->{allowOwnersUnrestrictedSshCommands};
}

sub isDoubleLock {
  my $self = shift;
  return $self->{isDoubleLock};
}

sub doubleLockId {
  my $self = shift;
  return $self->{doubleLockId};
}

sub enableInheritPermissions {
  my $self = shift;
  return $self->{enableInheritPermissions};
}

sub passwordTypeWebScriptId {
  my $self = shift;
  return $self->{passwordTypeWebScriptId};
}

sub siteId {
  my $self = shift;
  return $self->{siteId};
}

sub enableInheritSecretPolicy {
  my $self = shift;
  return $self->{enableInheritSecretPolicy};
}

sub secretPolicyId {
  my $self = shift;
  return $self->{secretPolicyId};
}

sub lastHeartBeatStatus {
  my $self = shift;
  return $self->{lastHeartBeatStatus};
}

sub lastHeartBeatCheck {
  my $self = shift;
  return $self->{lastHeartBeatCheck};
}

sub failedPasswordChangeAttempts {
  my $self = shift;
  return $self->{failedPasswordChangeAttempts};
}

sub lastPasswordChangeAttempt {
  my $self = shift;
  return $self->{lastPasswordChangeAttempt};
}

sub secretTemplateName {
  my $self = shift;
  return $self->{secretTemplateName};
}

sub responseCodes {
  my $self = shift;
  return $self->{responseCodes};
}

1;


[{"Business Unit":{"code":"BU059","label":"IBM Software w\/o TPS"},"Product":{"code":"SSWHLP","label":"IBM Security Secret Server"},"Component":"REST APIs","Platform":[{"code":"PF033","label":"Windows"}],"Version":"10.6;10.7","Edition":"","Line of Business":{"code":"LOB24","label":"Security Software"}}]

Document Information

More support for:
IBM Security Secret Server

Software version:
10.6, 10.7

Operating system(s):
Windows

Document number:
1136260

Modified date:
18 December 2019

UID

ibm11136260

Manage My Notification Subscriptions