CyberArkAIM Deprecated

Deprecated. Use the CyberArk AIM v2 integration instead.

Authentication & Identity Management · CyberArk Central Credential Provider (CCP)

Details

IDCyberArkAIM
ProviderPalo Alto Networks
CategoryAuthentication & Identity Management
From Version5.0.0
Supported ModulesAgentix XSIAM

README

Deprecated. Use the CyberArk AIM v2 integration instead.

Configure CyberArkAIM on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for CyberArkAIM.
  3. Click Add instance to create and configure a new integration instance.
    • Name: a textual name for the integration instance.
    • Server URL (e.g. https://192.168.0.1)
    • Port
    • AppID as configured in AIM
    • Trust any certificate (not secure)
    • Use system proxy settings
    • Folder to search in safe
    • Safe to search in
    • isFetchCredentials
    • API Username
    • API Password
    • Credential names - comma-seperated list of credentials names in vault
  4. Click Test to validate the URLs, token, and connection.

Commands

You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. After you successfully execute a command, a DBot message appears in the War Room with the command details.

  1. Search for credentials: cyber-ark-aim-query
  2. Get a list of credentials: list-credentials
  3. Reset account password: reset-credentials
  4. Get information for an account: account-details

1. Search for credentials


Search credentials in CyberArk AIM. Only one result is returned.

Base Command

cyber-ark-aim-query

Input
Argument Name Description Required
username Username to query Optional
address Address to query Optional
safe Safe to query Optional
folder Folder to query Optional
object Object to query Optional
query Defines a free query using account properties, including Safe, folder, and object. When this method is specified, all other search criteria are ignored Optional
queryFormat Defines the query format, which can optionally use regular expressions Optional
reason The reason for retrieving the password. This reason will be audited in the Credential Provider audit log. Optional
database Defines search criteria according to the database account property Optional

 

Context Output
Path Type Description
CyberArk.AIM.Folder unknown Account folder
CyberArk.AIM.PasswordChangeInProcess unknown Is password change in process
CyberArk.AIM.Content unknown Account content
CyberArk.AIM.CreationMethod unknown Account creation method
CyberArk.AIM.Name unknown Account name
CyberArk.AIM.PolicyID unknown Account policy ID
CyberArk.AIM.CPMDisabled unknown Account CPM disabled
CyberArk.AIM.Address unknown Account address
CyberArk.AIM.Safe unknown Account safe
CyberArk.AIM.UserName unknown Account username
CyberArk.AIM.DeviceType unknown Account device type
 

2. Get a list of all credentials


Lists all credentials available.

Base Command

list-credentials

Input
Argument Name Description Required
identifier When used, command will return a specific credential Optional

 

Context Output

There is no context output for this command.

3. Reset account password


Resets the password for the specified account with a random password.

Base Command

reset-credentials

Input
Argument Name Description Required
immediateChangeByCPM Flag the CPM that the change is effective immediately Optional
accountId Account ID to reset password Required

 

Context Output

There is no context output for this command.

4. Get information for an account


This method returns information about an account. If more than one account meets the search criteria, only the first account will be returned.

Base Command

account-details

Input
Argument Name Description Required
keywords Keywords matching the account Required
safe Specify a safe instead of a specific instance Optional

 

Context Output

There is no context output for this command.

Configuration parameters

  • server — Server URL (e.g. https://192.168.0.1) (required)
  • port — Port
  • appid — AppID as configured in AIM (required)
  • username — API Username
  • password — API Password
  • isFetchCredentials — Fetches credentials
  • folder — Folder to search in safe (required)
  • safe — Safe to search in (required)
  • credentialNames — Credential names - comma-separated list of credentials names in vault
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (4)

  • account-details

    This method returns information about an account. If more than one account meets the search criteria, only the first account will be returned.

  • cyber-ark-aim-query

    Search credentials in CyberArk using arguments to narrow the search. Cannot return more than one result.

  • list-credentials

    Lists all credentials available

  • reset-credentials

    This method marks the account for an immediate password change by the CPM to a new random password.

var port = params.port;
var base = params.server.replace(/[\/]+$/, '') + (port ? (':' + port) : '');
var accountsUrl = base + '/AIMWebService/api/Accounts';
var authUrl = base + '/PasswordVault/WebServices/auth/Cyberark/CyberArkAuthenticationService.svc/';
var credentialsUrl = base + '/PasswordVault/WebServices/PIMServices.svc/Accounts';
var insecure = params.insecure;
var proxy = params.proxy;
var appid = params.appid;
var username = params.username;
var password = params.password;
var token;

var sendRequest = function(method, url, args) {
    var res = http(
        url + (method === 'GET' ? encodeToURLQuery(args) : ''),
        {
            Method: method,
            Body: method !== 'GET' ? JSON.stringify(args) : ''
        },
        insecure,
        proxy,
        false,
        false,
        30000
    );
    if (res.StatusCode !== 400 && (res.StatusCode < 200 || res.StatusCode >= 300)) {
        if (res.StatusCode === 404) {
            return undefined;
        }
        // if timeout, throw.
        if (res.StatusCode === -1) {
            throw 'Request credentials from CyberArk returned Timeout. Error: ' + res.Status;
        }
        throw 'Failed to reach ' + url + ' , request status code: ' + res.StatusCode + ' and Body: ' + res.Body + '.';
    }
    return JSON.parse(res.Body);
}

var sendRequestWithToken = function(method, url, args, returnPlainResponse) {
    var headers = {};
    headers["Content-Type"] = ["application/json"];
    if (!token) {
        var data = {
          username: username,
          password: password,
          useRadiusAuthentication: false,
          connectionNumber: 1
        };
        var tokenRes = http(
            authUrl + 'Logon',
            {
                Method: 'POST',
                Headers: headers,
                Body: JSON.stringify(data)
            },
            insecure,
            proxy
        );
        if (tokenRes.StatusCode !== 200) {
            throw 'Could not authenticate user ' + tokenRes.Body;
        }

        var tokenResObject = JSON.parse(tokenRes.Body);
        token = tokenResObject.CyberArkLogonResult;
    }

    headers["Authorization"] = [token];
    if (args.ImmediateChangeByCPM) {
        headers["ImmediateChangeByCPM"] = [args.ImmediateChangeByCPM];
        delete args.ImmediateChangeByCPM;
    }

    var res = http(
            url + (method === 'GET' ? encodeToURLQuery(args) : ''),
            {
                Method: method,
                Headers: headers,
                Body: method !== 'GET' ? JSON.stringify(args) : ''
            },
            insecure,
            proxy,
            false,
            false,
            30000
    );
    if (res.StatusCode !== 200) {
        throw 'Failed to receive valid answer: ' + res.Status;
    }

    return returnPlainResponse ? res : JSON.parse(res.Body);
};

var parseAccountsFromErrorMessage = function(message) {
    var credentials = [];
    // format: Too many password objects matching query [Folder=...;Safe=...] were found: (Safe=...;Folder=...;Object=... and Safe=...;Folder=...;Object=...) (Diagnostic Info: 41)
    var accounts = message.split("were found: (")[1];
    // format: Safe=...;Folder=...;Object=... and Safe=...;Folder=...;Object=...) (Diagnostic Info: 41)
    accounts = accounts.split(")")[0];
    // format: Safe=...;Folder=...;Object=... and Safe=...;Folder=...;Object=...
    accounts = accounts.split(" and ");
    accounts.forEach(function(accountString) {
        var crednetialDetails = {};
        crednetialDetails.name = accountString.split(";Object=")[1];
        credentials.push(crednetialDetails);
    });
    return credentials;
}

var resetCredentials = function(args) {
    sendRequestWithToken('PUT', credentialsUrl + '/' + args.accountId + '/ChangeCredentials', args, true);

    return {
        Type: entryTypes.note,
        ContentsFormat: formats.json,
        Contents: "Operation succeeded.",
        ReadableContentsFormat: formats.markdown
    };
};

var getAccountDetails = function(args) {
    var result = sendRequestWithToken('GET', credentialsUrl, args);
    if (!result) {
        return 'No results found';
    }

    return {
        Type: entryTypes.note,
        ContentsFormat: formats.json,
        Contents: result,
        EntryContext: {'CyberArk.AIM(val.Name==obj.Name).Accounts': result.accounts},
        ReadableContentsFormat: formats.markdown,
        HumanReadable: tableToMarkdown('Found ' + result.Count + ' accounts matching "' + args.Keywords + '". Displaying only the first:', result.accounts)
    };
};

var getCredentials = function(asList) {
    args.AppID = appid;
    args.Folder = params.folder;
    args.Safe = params.safe;

    var credsToFetch  = [];
    if (args.identifier) {
        credsToFetch.push(args.identifier);
        delete args.identifier;
    } else if (params.credentialNames) {
        credsToFetch = params.credentialNames.split(',');
    }

    var credentials = [];
    for (var i = 0; i < credsToFetch.length; i++) {
        args.Object = credsToFetch[i].trim();

        var result = sendRequest('GET', accountsUrl, args);
        if (result) {
            var itemToAdd = asList ? result : {
                    'user': result.UserName,
                    'password': result.Content,
                    'name': result.Name
                };
            credentials.push(itemToAdd);
        }
    }

    if (credentials.length === 0) {
        // no creds were fetched - log to server
        logInfo('No credentials were fetched for [' + credsToFetch.join(', ') + ']');
    }

    return asList ? credentials : JSON.stringify(credentials);
}

var queryCredentials = function() {
    args.AppID = appid;
    if (!args.folder) {
        args.Folder = params.folder;
    } else {
        args.Folder = args.folder;
    }
    if (!args.safe) {
        args.Safe = params.safe;
    } else {
        args.Safe = args.safe;
    }
    var argsKeys = Object.keys(args);
    cleanArgs = {};
    argsKeys.forEach(function(key) {
        var upperKey = key.charAt(0).toUpperCase() + key.substr(1);
        cleanArgs[upperKey] = args[key];
        delete args[key];
    });
    var result = sendRequest('GET', accountsUrl, cleanArgs);
    var res = result;
    var humanReadable = null;
    // If we received too many (limited by CyberArk) then return a warning.
    if (result && result.ErrorMsg && result.ErrorMsg.indexOf("Too many") > -1) {
        var accounts = parseAccountsFromErrorMessage(result.ErrorMsg);
        res = "Found " + accounts.length + " results or more, while can only get one. Please try to narrow down the search by adding more filters.";
        humanReadable = res;
    } else if (result && result.ErrorMsg) {
        res = "Error: " + result.ErrorMsg;
        humanReadable = res;
    } else {
       humanReadable = tableToMarkdown('Credentials Results', result);
    }
    return {
        Type: entryTypes.note,
        ContentsFormat: formats.json,
        Contents: res,
        ReadableContentsFormat: formats.markdown,
        HumanReadable: humanReadable
    };
}

var listCredentials = function() {
    var creds = getCredentials(true);

    for (var i = 0; i < creds.length; i++) {
        // delete password
        delete creds[i].Content;
    }

    return {
        Type: entryTypes.note,
        ContentsFormat: formats.json,
        Contents: creds,
        EntryContext: {'CyberArk.AIM(val.Name==obj.name)': creds},
        ReadableContentsFormat: formats.markdown,
        HumanReadable: tableToMarkdown('Credentials fetched from CyberArk AIM vault:', creds)
    };
}

function testModuleAndCredentials() {
    args.AppID = appid;
    args.Folder = params.folder;
    args.Safe = params.safe;

    var paramCredsString = params.credentialNames;
    if (!paramCredsString) {
        sendRequest('GET', accountsUrl, args);
    } else {
        var names = paramCredsString.split(',');
        for (var i = 0; i < names.length; i++) {
            var name = names[i].trim()
            args.Object = name
            // exception would be thrown if identifier (Object) does not exists
            var result = sendRequest('GET', accountsUrl, args);
            if (!result) {
                throw 'Could not find object for: "' + name + '"'
            }
        }
    }

    return 'ok';
}

switch (command) {
    case 'test-module':
        return testModuleAndCredentials();
    case 'fetch-credentials':
        return getCredentials();
    case 'cyber-ark-aim-query':
        return queryCredentials();
    case 'reset-credentials':
        return resetCredentials(args);
    case 'account-details':
        args.Safe = args.safe || params.safe;
        delete args.safe;
        args.Keywords = args.keywords;
        delete args.keywords;
        return getAccountDetails(args);
    case 'list-credentials':
        return listCredentials();
    default:
        throw 'Command "' + command + '" is not supported.';
}