VenafiTLSProtect

Retrieves information about certificates stored in Venafi.

IT Services · CyberArk Certificate Manager Self-Hosted

Details

IDVenafiTLSProtect
ProviderCyberArk
CategoryIT Services
From Version6.9.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Retrieves information about certificates stored in Venafi.

Configure CyberArk Certificate Manager on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for CyberArk Certificate Manager.
  3. Click Add instance to create and configure a new integration instance.

    Parameter Required
    Server URL (e.g., https://192.168.0.1) True
    User Name True
    Password True
    Client ID True
    Trust any certificate (not secure) False
    Use system proxy settings False
  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.

venafi-get-certificates


Gets Venafi certificates query. All dates are in 2016-11-12T00:00:00.0000000Z format. For additional field information, see: https://ao-tlspd.dev.ven-eco.com/aperture/help/Content/SDK/WebSDK/r-SDK-Certificates-search-attribute.htm and https://ao-tlspd.dev.ven-eco.com/aperture/help/Content/SDK/WebSDK/r-SDK-Certificates-search-status.htm

Base Command

venafi-get-certificates

Input

Argument Name Description Required
CreatedOn The date on which the certificated was created. Specify YYYY-MM-DD or the ISO 8601 format. Optional
CreatedOnGreater Find certificates created after this date. Specify YYYY-MM-DD or the ISO 8601 format. Optional
CreatedOnLess Find certificates created before this date. Specify YYYY-MM-DD or the ISO 8601 format. Optional
Disabled Include only certificates that are enabled 0 or disabled 1. Optional
InError Whether to include only certificates that are in an error state (1) or not in an error state (0). Optional
ValidationState Validation state. Possible values are: Blank, Success, Failure. Optional
ManagementType Management type. Possible values are: Unassigned, Monitoring, Enrollment, Provisioning. Optional
Name Name of the certificate object. Optional
NetworkValidationDisabled Whether to include only certificates with network validation disabled (1) or enabled (0). Optional
ParentDn The full path to the parent of the object in Trust Protection Platform (e.g., \VED\Policy\Engineering,\VED\Policy\HR). Optional
ParentDnRecursive The specific folder from which to retrieve certificates. (The subfolders will also be scanned.) Accepts a single value. Optional
PendingWorkflow Whether to include only certificates that are pending workflow resolution (have an outstanding workflow ticket). Optional
Stage Comma-separated list of stages in the certificate lifecycle. Will retrieve certificates at one or more of the stages. Optional
StageGreater Find certificates with a stage greater than the specified stage (does not include specified stage). Optional
StageLess Stage before which to retrieve certificates. Optional
ValidationDisabled Whether to include only certificates with validation disabled (1) or enabled (0). Optional
C Find certificates by Country attribute of Subject DN. Optional
CN Find certificates by Common name attribute of Subject DN. Optional
Issuer Find certificates by issuer. Use the CN ,O, L, S, and C values from the certificate request. Surround the complete value within double quotes (“). If a value already has double quotes, escape them with a second set of double quotes. For example, OU=”“(c) 2020 Entrust, Inc. - for authorized use only””. Optional
KeyAlgorithm Algorithm for the public key in the certificate (e.g., RSA, DSA). Optional
KeySize Comma-separated list of the bit size of the public key in the certificate (e.g., 2048). Optional
KeySizeGreater The size for which the public key size is greater than. Optional
KeySizeLess The size for which the public key size is less than. Optional
L Find certificates by Locality/City attribute of Subject Distinguished Name (SDN). Optional
O Find certificates by Organization attribute of Subject DN. Optional
S Find certificates by State/Province attribute of Subject DN. Optional
Serial Serial number of the certificate. Optional
SignatureAlgorithm The algorithm used to sign the certificate (e.g., SHA1RSA). Optional
ValidFrom Date on which the certificate was issued (e.g., 2015- 10-08T19:15:35.6431456Z or 2015-10-08). Optional
ValidTo Date on which the certificate expires (e.g., 2015-10- 08T19:15:35.6431456Z or 2015-10-08). Optional
ValidToGreater Date after which the certificates expire. Optional
ValidToLess Date before which the certificates expire. Optional
Limit The maximum number of certificates to return. Default value = 50. Optional

Context Output

Path Type Description
Venafi.Certificate.CreatedOn date The exact date and time when the certificate object was created.
Venafi.Certificate.DN string The DN of the certificate.
Venafi.Certificate.Name string The name of the certificate.
Venafi.Certificate.ParentDN string The full path to the parent of the object in Trust Protection Platform.
Venafi.Certificate.SchemaClass string The class name of the certificate object.
Venafi.Certificate.ID string The certificate object GUID.
Venafi.Certificate.X509 dictionary Enrolled or issued certificate information: CN, Issuer, KeyAlgorithm, KeySize, SANS, Serial, Subject, Thumbprint, ValidFrom, ValidTo.

venafi-get-certificate-details


Uses a certificate GUID to extract more details from the certificate store.

Base Command

venafi-get-certificate-details

Input

Argument Name Description Required
guid The ID of the certificate. Get certificates ID by running the command “venafi-get-certificates”. Required

Context Output

Path Type Description
Venafi.Certificate.ID string The certificate object GUID.
Venafi.Certificate.ParentDN string The full path to the parent of the object in Trust Protection Platform.
Venafi.Certificate.CreatedOn date The exact date and time when the Certificate object was created.
Venafi.Certificate.DN string The DN of the certificate.
Venafi.Certificate.Name string The name of the certificate.
Venafi.Certificate.SchemaClass string The class name of the certificate object.
Venafi.Certificate.Approver string An array of one or more users or groups who are certificate approvers.
Venafi.Certificate.CertificateAuthorityDN string The CA template that is required for certificate renewal.
Venafi.Certificate.Contact string An array of one or more users or groups who receive event notifications. The events notify people about certificate expiration and validation failures.
Venafi.Certificate.Description string Certificate description.
Venafi.Certificate.ManagedBy string Certificate manager.
Venafi.Certificate.ManagementType string The level of management that the Trust Protection Platform applies to the certificate.
Venafi.Certificate.CertificateDetails.AIAKeyIdentifier string Authority key identifier.
Venafi.Certificate.CertificateDetails.Issuer string The CN, O, L, S, and C values from the certificate request.
Venafi.Certificate.CertificateDetails.Serial string The unique serial number that the CA assigned to the certificate.
Venafi.Certificate.CertificateDetails.Subject string The CN, O, L, S, and C values from the certificate request.
Venafi.Certificate.CertificateDetails.Thumbprint string The SHA1 thumbprint hash of the certificate.
Venafi.Certificate.CertificateDetails.ValidFrom string Certificate validation start date.
Venafi.Certificate.CertificateDetails.ValidTo string Certificate validation end time.
Venafi.Certificate.CertificateDetails.AIACAIssuerURL array Available only when the certificate was issued by a well-configured CA. An array of Authority Information Access (AIA). Shows the CA issuer link and the CA’s certificate details. May also include Online Certificate Status Protocol (OCSP) information about revocation.
Venafi.Certificate.CertificateDetails.CN string The Common Name attribute of Subject Distinguished Name (DN).
Venafi.Certificate.CertificateDetails.EnhancedKeyUsage string The PKI Server Authentication object identifier (OID).
Venafi.Certificate.CertificateDetails.KeyAlgorithm string The algorithm for the public key.
Venafi.Certificate.CertificateDetails.KeySize string Only available for RSA certificates. The bit size of the public key.
Venafi.Certificate.CertificateDetails.KeyUsage string A list of Key Usage extension values that describe the purpose of the public key.
Venafi.Certificate.CertificateDetails.OU string An array of Organization Units or names.
Venafi.Certificate.CertificateDetails.PublicKeyHash string The public key hash string. Available only when the certificate has a private key.
Venafi.Certificate.CertificateDetails.SKIKeyIdentifier string The generated Subject Key Identifier (SKI).
Venafi.Certificate.CertificateDetails.SignatureAlgorithm string The signature algorithm for signing the certificate.
Venafi.Certificate.CertificateDetails.SignatureAlgorithmOID string The Signature Object ID for signing the certificate.
Venafi.Certificate.CertificateDetails.StoreAdded string The Date Time stamp when the private key was added to the store.
Venafi.Certificate.CertificateDetails.SubjectAltNameDNS string An array of Domain Name System (DNS) SANs.
Venafi.Certificate.CertificateDetails.SubjectAltNameEmail string An array of Email SANs. Based on RFC 822.
Venafi.Certificate.CertificateDetails.SubjectAltNameOtherNameUPN string An array of User Principal Name (UPN) SANs.
Venafi.Certificate.CertificateDetails.SubjectAltNameIPAddress string An array of IP address SANs.
Venafi.Certificate.CertificateDetails.SubjectAltNameURI string An array of Uniform Resource Indicator (URI) SANs.
Venafi.Certificate.CreatedBy string The object that initiated enrollment or provisioning changes. The default is Web SDK.
Venafi.Certificate.Origin string Filter by origin.
Venafi.Certificate.ProcessingDetails dictionary Absent when the certificate is not currently processing in the Trust Protection Platform lifecycle: InError, InProcess, Stage, Status, TicketDN.
Venafi.Certificate.RenewalDetails dictionary A list of certificate renewal information.
Venafi.Certificate.ValidationDetails dictionary A list of host identity information and the overall certificate validation state result. If no validation occurred, only the lastvalidationstateupdate field appears. All other validationdetails fields are absent.

Configuration parameters

  • server — Server URL (e.g., https://192.168.0.1) (required)
  • credentials — User Name (required)
  • client_id — Client ID (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (2)

  • venafi-get-certificate-details

    Uses a certificate GUID to extract more details from the certificate store.

  • venafi-get-certificates

    Gets Venafi certificates query. All dates are in 2016-11-12T00:00:00.0000000Z format. For additional field information, see: https://ao-tlspd.dev.ven-eco.com/aperture/help/Content/SDK/WebSDK/r-SDK-Certificates-search-attribute.htm and https://ao-tlspd.dev.ven-eco.com/aperture/help/Content/SDK/WebSDK/r-SDK-Certificates-search-status.htm

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401
from CommonServerUserPython import *  # noqa
import urllib3
from typing import Any

# Disable insecure warnings
urllib3.disable_warnings()

""" CONSTANTS """
DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"  # ISO8601 format with UTC, default in XSOAR
MINUTES_BEFORE_TOKEN_EXPIRED = 2
CONTEXT_OUTPUT_BASE_PATH = "Venafi.Certificate"

""" CLIENT CLASS """


class Client(BaseClient):
    """
    Client class to interact with the service API
    """

    def __init__(self, base_url: str, verify: bool, proxy: bool, username: str, password: str, client_id: str):
        super().__init__(base_url=base_url, verify=verify, proxy=proxy)
        self.token = self.login(client_id, username, password)

    def login(self, client_id: str, username: str, password: str) -> str:
        """
         Log into the Venafi API using the provided credentials.
         If it's the first time logging in, it will create a new token, save it to the integration context, and log in.
         Otherwise,
             - if the token is expired, it will use the refresh token (if not expired), save it to the integration context.
             - if the token is valid, it will log in.
             - if both token and refresh token are expired, it will create a new token using credentials.

         Args:
             client_id (str): The client ID of the user.
             username (str): The username of the user.
             password (str): The password of the user.

        Returns:
             str: The token of the user.
        """

        integration_context = get_integration_context()

        if token := integration_context.get("access_token"):
            access_until = integration_context.get("access_until")
            if access_until and not self.is_token_expired(access_until):
                demisto.debug("Access token is valid, will use it to login")
                return token

            elif refresh_token := integration_context.get("refresh_token"):
                refresh_until = integration_context.get("refresh_until")
                if refresh_until and not self.is_token_expired(refresh_until):
                    demisto.debug("Refresh token is valid, will use it to get new access token")
                    json_data = {"client_id": client_id, "refresh_token": refresh_token}
                    return self.create_new_token(json_data, is_token_exist=True)

        json_data = {"username": username, "password": password, "client_id": client_id, "scope": "certificate"}
        return self.create_new_token(json_data, is_token_exist=False)

    def is_token_expired(self, expires_date: int) -> bool:
        """
        This method checks if the token is expired.

        Args:
            expires_date (int): The timestamp of the expiration date of the token.

        Returns:
            bool: True if the token is expired, False otherwise.
        """

        timestamp_utc_now = int(get_current_time().timestamp())
        return timestamp_utc_now > expires_date

    def create_new_token(self, json_data: dict, is_token_exist: bool) -> str:
        """
        Creation of a new API token.

        Args:
            json_data (dict): The data that contain user credentials.
            is_token_exist (bool): Rather token exist or not

        Returns:
            str: The new token
        """

        if is_token_exist:
            url_suffix = "/vedauth/authorize/token"
        else:
            url_suffix = "/vedauth/authorize/oauth"

        access_token_obj = self._http_request(
            method="POST",
            url_suffix=url_suffix,
            headers={"Content-Type": "application/json"},
            data=json.dumps(json_data),
        )

        access_token = access_token_obj.get("access_token", "")
        refresh_token = access_token_obj.get("refresh_token", "")
        access_until = arg_to_number(access_token_obj.get("expires")) or int(get_current_time().timestamp())
        refresh_until = arg_to_number(access_token_obj.get("refresh_until")) or int(get_current_time().timestamp())

        set_integration_context(
            {
                "access_token": access_token,
                "refresh_token": refresh_token,
                "access_until": access_until,
                "refresh_until": refresh_until,
            }
        )

        return access_token

    def get_certificates(self, args: dict[str, Any]) -> dict:
        """
        This method creates the HTTP request to retrieve the certificates the user has.

        Args:
            args (dict): The arguments for the command passed to the request.

        Returns:
            dict: The response object.
        """

        headers = {"Authorization": f"Bearer {self.token}"}

        return self._http_request(method="GET", url_suffix="/vedsdk/certificates/", headers=headers, params=args)

    def get_certificate_details(self, guid: str) -> dict:
        """
        This method creates the HTTP request to retrieve certificate details.

        Args:
            guid (str): The GUID of the certificate.

        Returns:
            dict: The response object.
        """

        headers = {"Authorization": f"Bearer {self.token}"}
        url_suffix = f"/vedsdk/certificates/{guid}"

        return self._http_request(method="GET", url_suffix=url_suffix, headers=headers)


""" COMMAND FUNCTIONS """


def test_module(client: Client) -> str:
    """Tests API connectivity and authentication'

    Returning 'ok' indicates that the integration works like it is supposed to.
    Connection to the service is successful.
    Raises exceptions if something goes wrong.

    :type client: ``Client``
    :param client: client to use

    :return: 'ok' if test passed, anything else will fail the test.
    :rtype: ``str``
    """

    try:
        test_empty_args: Dict = {}
        client.get_certificates(test_empty_args)
    except DemistoException as e:
        raise e

    return "ok"


def get_certificates_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Get all the certificates belong to a user.

    Args:
        client (Client): A Venafi client.
        args (dict): The arguments for the command passed to the request.
    Returns:
        A CommandResult object with an outputs, raw_response and readable table, in case of a successful action.
    """

    response = client.get_certificates(args)
    certificates = response.get("Certificates", [])
    adjusted_certificates = edit_response(certificates)
    markdown_table = tableToMarkdown(
        "Venafi certificates", adjusted_certificates, headers=["CreatedOn", "DN", "Name", "ParentDn", "SchemaClass", "ID"]
    )

    return CommandResults(
        outputs_prefix=CONTEXT_OUTPUT_BASE_PATH,
        outputs=adjusted_certificates,
        raw_response=response,
        readable_output=markdown_table,
        outputs_key_field="ID",
    )


def get_certificate_details_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Get certificate details.

    Args:
        client (Client): A Venafi client.
        args (dict): The arguments for the command passed to the request.
    Returns:
        A CommandResult object with an outputs, raw response and readable table, in case of a successful action.
    """

    guid: str = args.get("guid", "")
    response = client.get_certificate_details(guid)
    if response.get("Guid"):
        # Add ID to response for backward compatible with V1 and remove redundant guid entry
        response["ID"] = response.pop("Guid").strip("{}")

    markdown_table = tableToMarkdown(
        "Venafi certificate details", response, headers=["CreatedOn", "DN", "Name", "ParentDn", "SchemaClass", "ID"]
    )

    return CommandResults(
        outputs_prefix=CONTEXT_OUTPUT_BASE_PATH,
        outputs=response,
        raw_response=response if response else {},
        readable_output=markdown_table,
        outputs_key_field="ID",
    )


""" HELPER FUNCTIONS """


def edit_response(certificates: list) -> list:
    """
    Delete links list from the response and add ID entry.

    Args:
        certificates (list): List of certificates
    Returns:
        certificates (list): List of certificates with ID entry but without _links and guid entries.
    """

    for certificate in certificates:
        certificate["ID"] = certificate.get("Guid", "").strip("{}")
        del certificate["Guid"]
        if certificate.get("_links"):
            del certificate["_links"]

    return certificates


""" MAIN FUNCTION """


def main() -> None:  # pragma: no cover
    """
    main function, parses params and runs command functions

    :return:
    :rtype:
    """

    demisto_params = demisto.params()
    base_url = demisto_params.get("server", "https://ao-tlspd.dev.ven-eco.com")
    username = demisto_params.get("credentials", {}).get("identifier")
    password = demisto_params.get("credentials", {}).get("password")
    client_id = demisto_params.get("client_id")
    verify_certificate = not demisto_params.get("insecure", False)
    proxy = demisto_params.get("proxy", False)
    command = demisto.command()
    demisto.debug(f"Command being called is {command}")
    try:
        client = Client(
            base_url=base_url, verify=verify_certificate, username=username, password=password, client_id=client_id, proxy=proxy
        )

        args = demisto.args()
        if command == "test-module":
            return_results(test_module(client))
        elif command == "venafi-get-certificates":
            return_results(get_certificates_command(client, args))
        elif command == "venafi-get-certificate-details":
            return_results(get_certificate_details_command(client, args))
        else:
            raise NotImplementedError(f"{command} command is not implemented.")

    except Exception as e:
        if "Forbidden" in str(e) or "Authorization" in str(e):
            return_error("Authorization Error: make sure API Key is correctly set")
        else:
            return_error(f"Failed to execute {command} command.\nError:\n{str(e)}")


""" ENTRY POINT """

if __name__ in ("__main__", "__builtin__", "builtins"):
    main()