CyberArkAIM v2

The CyberArk Application Identity Manager (AIM) provides a secure safe in which to store your account credentials. Use this integration to retrieve the account credentials in CyberArk AIM.

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

Details

IDCyberArkAIM v2
ProviderPalo Alto Networks
CategoryAuthentication & Identity Management
From Version5.0.0
Docker Imagedemisto/ntlm:1.0.0.9067966
Supported ModulesAgentix XSIAM

README

The CyberArk Central Credential Provider (CCP) provides a secure safe in which to store your account credentials. Use this integration to retrieve the account credentials in CyberArk CCP. This integration fetches credentials. For more information, see Managing Credentials.

Authentication Options

The integration uses the Central Credential Provider and supports the following authentication methods:

  • OS User (Windows NTLM Authentication): Set the domain user and password in the credentials field. Make sure your CyberArk Server is configured to support NTLM authentication as documented here. Note that the user option may require specifying full domain\user.
  • Client Certificate Authentication: Enter the Certificate and Private key in the integration instance configuration parameters. Make sure to follow the instructions here to enable the Central Credential Provider to accept client authentication with client certificates.
  • Allowed Machines: Leave all authentication methods empty. Follow CyberArk’s instructions here to accept the Cortex XSOAR Server IP for the configured AppID.

Further information is available from CyberArk at:

  • https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-CP/Latest/en/Content/CP%20and%20ASCP/Application-Authentication-Methods-general.htm
  • https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-CP/Latest/en/Content/CCP/Configure_CCPWindows.htm

Configure CyberArkAIM v2 in Cortex

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for CyberArkCCP.
  3. Click Add instance to create and configure a new integration instance.
Parameter Description Required
Server URL and Port (e.g., https://example.net:1234)   True
AppID as configured in AIM   False
Folder to search in safe   False
Safe to search in   False
A comma-separated list of credential names in the safe. Partial names are not supported. If left empty, no credentials will be fetched. False
Username   False
Password   False
Certificate File as Text Add a certificate file in text format to use to connect to the CyberArk AIM server. False
Key File as Text   False
Fetch credentials   False
Trust any certificate (not secure)   False
Use system proxy settings   False

Commands

You can execute these commands from the 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.

cyberark-aim-list-credentials


Lists all available credentials according to the list of credential names configured.

Base Command

cyberark-aim-list-credentials

Input

There are no input arguments for this command.

Context Output

Path Type Description
CyberArkAIM.AccountType String The type of the account.
CyberArkAIM.Address String The address of the account.
CyberArkAIM.CPMStatus String The CMP status of the account.
CyberArkAIM.Domain String The domain of the account.
CyberArkAIM.Name String The credential name of the account.

Command Example


#### Context Example

{
“CyberArkAIM”: {
“AccountCategory”: “True”,
“AccountDescription”: “Built-in account for administering the computer/domain”,
“AccountDiscoveryDate”: “1573128798”,
“AccountEnabled”: “True”,
“AccountExpirationDate”: “0”,
“AccountOSGroups”: “Administrators”,
“AccountType”: “Domain”,
“Address”: “AIM.COM”,
“CPMDisabled”: “(CPM)Newly discovered dependency”,
“CPMStatus”: “success”,
“CreationMethod”: “AutoDetected”,
“DeviceType”: “Operating System”,
“DiscoveryPlatformType”: “Windows Domain”,
“Domain”: “AIM.COM”,
“Folder”: “Root”,
“LastLogonDate”: “1572451901”,
“LastPasswordSetDate”: “1566376303”,
“LastSuccessChange”: “1575910475”,
“LastSuccessReconciliation”: “1583521898”,
“LastSuccessVerification”: “1583256386”,
“LastTask”: “ReconcileTask”,
“LogonDomain”: “domain1”,
“MachineOSFamily”: “Server”,
“Name”: “name1”,
“OSVersion”: “Windows Server 2016 Standard”,
“OU”: “CN=Users,DC=COM”,
“PasswordChangeInProcess”: “False”,
“PasswordNeverExpires”: “True”,
“PolicyID”: “WinDomain”,
“RetriesCount”: “-1”,
“SID”: “sid”,
“Safe”: “Windows Domain Admins”,
“SequenceID”: “1”,
“Tags”: “DAdmin”,
“UserName”: “username1”
}
}
```

Human Readable Output

Results

AccountCategory AccountDescription AccountDiscoveryDate AccountEnabled AccountExpirationDate AccountOSGroups AccountType Address CPMDisabled CPMStatus CreationMethod DeviceType DiscoveryPlatformType Domain Folder LastLogonDate LastPasswordSetDate LastSuccessChange LastSuccessReconciliation LastSuccessVerification LastTask LogonDomain MachineOSFamily Name OSVersion OU PasswordChangeInProcess PasswordNeverExpires PolicyID RetriesCount SID Safe SequenceID Tags UserName
True Built-in account for administering the computer/domain 1573128798 True 0 Administrators Domain AIM.COM (CPM)Newly discovered dependency success AutoDetected Operating System Windows Domain AIM.COM Root 1572451901 1566376303 1575910475 1583521898 1583256386 ReconcileTask domain1 Server name1 Windows Server 2016 Standard CN=Users,DC=COM False True WinDomain -1 sid Windows Domain Admins 1 DAdmin username1

Configuration parameters

  • url — Server URL and Port (e.g., https://example.net:1234) (required)
  • app_id — AppID as configured in AIM
  • folder — Folder to search in safe
  • safe — Safe to search in
  • credential_names — A comma-separated list of credential names in the safe.
  • credentials — Username
  • cert_text — Certificate File as Text
  • key_text — Key File as Text
  • key_text_creds
  • isFetchCredentials — Fetch credentials
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (1)

  • cyberark-aim-list-credentials

    Lists all available credentials according to the list of credential names configured.

import tempfile

import demistomock as demisto  # noqa: F401

# disable insecure warnings
import urllib3
from CommonServerPython import *  # noqa: F401
from requests_ntlm import HttpNtlmAuth

from CommonServerUserPython import *

urllib3.disable_warnings()


class Client(BaseClient):
    def __init__(
        self,
        server_url: str,
        use_ssl: bool,
        proxy: bool,
        app_id: str,
        folder: str,
        safe: str,
        credentials_object: str,
        username: str,
        password: str,
        cert_text: str,
        key_text: str,
    ):
        super().__init__(base_url=server_url, verify=use_ssl, proxy=proxy)
        self._app_id = app_id
        self._folder = folder
        self._safe = safe
        self._credentials_list = argToList(credentials_object)
        self._username = username
        self._password = password
        self._cert_text = cert_text
        self._key_text = key_text
        self.auth = self.create_windows_authentication_param()
        self.crt, self.cf, self.kf = self.create_crt_param()

    def create_windows_authentication_param(self):
        auth = None
        if self._username:
            # if username and password were added - use ntlm authentication
            auth = HttpNtlmAuth(self._username, self._password)
        return auth

    def create_crt_param(self):
        if not self._cert_text and not self._key_text:
            return None, None, None
        elif not self._cert_text or not self._key_text:
            raise Exception("You can not configure either certificate text or key, both are required.")
        elif self._cert_text and self._key_text:
            cert_text_list = self._cert_text.split("-----")
            # replace spaces with newline characters
            cert_text_fixed = "-----".join(cert_text_list[:2] + [cert_text_list[2].replace(" ", "\n")] + cert_text_list[3:])
            cf = tempfile.NamedTemporaryFile(delete=False)
            cf.write(cert_text_fixed.encode())
            cf.flush()

            key_text_list = self._key_text.split("-----")
            # replace spaces with newline characters
            key_text_fixed = "-----".join(key_text_list[:2] + [key_text_list[2].replace(" ", "\n")] + key_text_list[3:])
            kf = tempfile.NamedTemporaryFile(delete=False)
            kf.write(key_text_fixed.encode())
            kf.flush()
            return (cf.name, kf.name), cf, kf
        return None

    def get_credentials(self, creds_object: str):
        url_suffix = "/AIMWebService/api/Accounts"
        body = {
            "AppID": self._app_id,
            "Safe": self._safe,
            "Object": creds_object,
        }
        if self._folder:
            body["Folder"] = self._folder

        return self._http_request("POST", url_suffix, json_data=body, auth=self.auth, cert=self.crt)

    def list_credentials(self):
        credential_result = [self.get_credentials(credentials) for credentials in self._credentials_list]
        return credential_result


def list_credentials_command(client):
    """Lists all credentials available.
    :param client: the client object with the given params
    :return: the credentials info without the explicit password
    """
    creds_list = client.list_credentials()
    for cred in creds_list:
        # the password value in the json appears under the key "Content"
        if "Content" in cred:
            del cred["Content"]
    # notice that the raw_response doesn't contain the password either
    results = CommandResults(
        outputs=creds_list,
        raw_response=creds_list,
        outputs_prefix="CyberArkAIM",
        outputs_key_field="Name",
    )
    return results


def fetch_credentials(client, args: dict):
    """Fetches the available credentials.
    :param client: the client object with the given params
    :param args: demisto args dict
    :return: a credentials object
    """
    creds_name = args.get("identifier")
    demisto.debug("name of cred used: ", creds_name)

    if creds_name:
        try:
            creds_list = [client.get_credentials(creds_name)]
        except Exception as e:
            demisto.debug(f"Could not fetch credentials: {creds_name}. Error: {e}")
            creds_list = []
    else:
        creds_list = client.list_credentials()
    credentials = []
    for cred in creds_list:
        credentials.append(
            {
                "user": cred.get("UserName"),
                "password": cred.get("Content"),
                "name": cred.get("Name") or cred.get("Object"),
            }
        )
    demisto.credentials(credentials)


def test_module(client: Client) -> str:
    """Performing a request to the AIM server with the given params
    :param client: the client object with the given params
    :return: ok if the request succeeded
    """
    if client._credentials_list:
        client.list_credentials()
    else:
        try:
            # Running a dummy credential just to check connection itself.
            client.get_credentials("test_cred")
        except DemistoException as e:
            if "Error in API call [500]" in e.message or "Error in API call [404]" in e.message:
                return "ok"
            else:
                raise e
    return "ok"


def main():
    params = demisto.params()

    url = params.get("url")
    use_ssl = not params.get("insecure", False)
    proxy = params.get("proxy", False)

    app_id = params.get("app_id")

    if not app_id:
        raise DemistoException("The 'AppID' parameter is required")

    folder = params.get("folder")
    safe = params.get("safe")
    credentials_object = params.get("credential_names") or ""

    cert_text = params.get("cert_text") or ""
    key_text = params.get("key_text_creds", {}).get("password") or params.get("key_text", "")

    username = ""
    password = ""
    if params.get("credentials"):
        # credentials are not mandatory in this integration
        username = params.get("credentials").get("identifier")
        password = params.get("credentials").get("password")

    try:
        client = Client(
            server_url=url,
            use_ssl=use_ssl,
            proxy=proxy,
            app_id=app_id,
            folder=folder,
            safe=safe,
            credentials_object=credentials_object,
            username=username,
            password=password,
            cert_text=cert_text,
            key_text=key_text,
        )

        command = demisto.command()
        demisto.debug(f"Command being called in CyberArk AIM is: {command}")

        if command == "test-module":
            return_results(test_module(client))
        elif command == "cyberark-aim-list-credentials":
            return_results(list_credentials_command(client))
        elif command == "fetch-credentials":
            fetch_credentials(client, demisto.args())

        else:
            raise NotImplementedError(f"{command} is not an existing CyberArk AIM command")
    except Exception as err:
        return_error(f"Unexpected error: {err!s}", error=traceback.format_exc())
    finally:
        try:
            if client.crt:
                cf_name, kf_name = client.crt
                if client.cf:
                    client.cf.close()
                    os.remove(cf_name)
                if client.cf:
                    client.kf.close()
                    os.remove(kf_name)
        except Exception as err:
            return_error(f"CyberArk AIM error: {err!s}")


if __name__ in ["__main__", "builtin", "builtins"]:
    main()