Reporting on failed workflow executions

Hello!

My organization has been transitioning more and more of our processes to workflows. One of our biggest issues has been the lack of operational logging for when a workflow fails. See Idea Workflows - Log Activity Success/Failures to | SailPoint Ideas Portal

Below is my attempt using PowerShell and API calls to cut down on some of the toil involved in checking workflows for errors.
It requires the use of:

  • Local server to schedule the script on
  • Service account to run the task
  • Azure key vault to store and retrieve secrets
  • An application registration with mail.send capabilities
  • A client ID and secret from SailPoint ISC

If you have done something else or perhaps more efficiently than this, please let me know!

## Get failed workflow executions

#region connect to Azure, Get secrets

# Update to require TLS 1.2
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;

# Parameters for AZ Connection
$Params = @{
    ApplicationId         = '' # App reg with list secret permissions to key vault
    Tenant                = '' # Tenant ID
    CertificateThumbPrint = '' # Certificate thumbprint of the cert signed/created by the svc account running the scheduled task on the server and uploaded to the app reg
}
$TenantId = "" # azure tenant ID needed for graph mail send
$null = Connect-AzAccount @Params # Connecting to azure $null prevents output

# Key vault info for SailPoint ID and secret
$kv = @{
    VaultName = '' # Name of the key vault with your SailPoint ISC Client ID and secret
    ClientID  = '' # Name of the client ID
    Secret    = '' # Name of the client secret
}

# Get SailPoint secret
Try
{
    $client_id = Get-AzKeyVaultSecret -VaultName $kv.VaultName -Name $kv.ClientId -AsPlainText
    $client_secret = Get-AzKeyVaultSecret -VaultName $kv.VaultName -Name $kv.Secret -AsPlainText

    $null = Disconnect-AzAccount
}
Catch
{
    Throw $_ # The script fails if unable to find client ID and secret
}
#endregion connect to Azure, Get secrets

#region get SailPoint ISC access token

# Use the id and secret to get and access token for SailPoint
$oAuthTokenBody = @{
    grant_type    = "client_credentials"
    client_id     = $client_id
    client_secret = $client_secret
}

# Create token acquisition url
$orgName = "" # Enter the org name here
$baseURL = "https://$orgName.api.identitynow.com"
$oAuthURI = "$baseUrl/oauth/token"

# SailPoint token acquisition and header information
$SPtoken = Invoke-RestMethod -Uri $oAuthURI -Method Post -Body $oAuthTokenBody -ErrorAction Stop

# Set header for API calls
$Headers = @{
    Authorization = "$($SPtoken.token_type) $($SPtoken.access_token)" 
}
#endregion get SailPoint ISC access token

#region get recent failed workflow executions

# Concatenate the URL
$url = $baseURL + "/v3" + "/workflows"

# Get all active workflows
$results = Invoke-RestMethod -Uri "$url" -Method Get -Headers $Headers 
$ActiveWorkflows = $results | Where-Object {$_.enabled -eq $true}

# Retrieve the executions run on each workflow and send email alert on new failures
$failedexecutions = foreach ($ActiveWorkflow in $ActiveWorkflows)
{

    $WFID = $ActiveWorkflow.ID # Workflow ID - this endpoint can only get the history of a specific workflow
    $url = $BaseURL + "/v3" + "/workflows" + "/$WFID"

    # Get all failed workflow executions for the workflow
    $results = Invoke-RestMethod -Uri "$url/executions?filters=status eq `"Failed`"" -Method Get -Headers $Headers

    # Date for comparing failed execution dates
    $date = (Get-Date (Get-Date).AddDays(-1) -Format "o") # This will set the date to 24 hours ago in the proper format

    # Create a custom object of only the executions that have failed in the last 24 hours
    foreach ($execution in $results)
    {
        if ($execution.startTime -gt $date)
        {
            [PSCustomObject]@{
                WorkflowName = $ActiveWorkflow.Name
                ID           = $execution.id
                StartTime    = $execution.startTime
                CloseTime    = $execution.closeTime
            }
        }
    }
}
#endregion get recent failed workflow executions

#region send mail notification
if ($failedexecutions) # If failures are present this email will be sent
{
    # Format failures from custom object to HTML
    $failedfragment = $failedexecutions | ConvertTo-Html -Fragment
    
    # Create message body and properties and send
    $MessageParams = @{
        subject        = "Action Required: Workflow failures detected"
        body           = @{
            contentType = 'HTML' 
            content     = "
                <body style='margin:0; padding:0; font-family:'Segoe UI',sans-serif'>
                    <table style='margin: 0px auto; border-collapse: separate; width: 90%;' width='90%' cellspacing='0' cellpadding='0' align='center'>
                        <tbody>
                            <tr>
                                <td style='width: 1.61812%;' colspan='2'>
                                    <h1 style='text-align: center;'>Workflow failure detected</h1>
                                </td>
                            </tr>
                            <tr>
                                <td style='padding: 30px 40px 10px; width: 1.61812%;' colspan='2'>
                                    <p style='font-size: 20px;'>What do you need to do?</p>
                                    <p>Find the reason for the failure an re-run the workflow.</p>
                                    Failures: $($failedexecutions.count)<br>
                                    $($failedfragment)
                                    </p>
                                </td>
                            </tr>
                        </tbody>"
        }
        "toRecipients" = @(
            @{
                "emailAddress" = @{"address" = "MailTo" }
            } ) 
        "ccRecipients" = @(
            @{
                "emailAddress" = @{"address" = "MailCC" }
            }
        )       
    }
    # Connect to MG Graph for Mail Send
    Connect-MgGraph -ClientId $params.ApplicationId -CertificateThumbprint $Params.CertificateThumbPrint -TenantId $TenantId
    Send-MgUserMail  -UserId [email protected] -Message $MessageParams
    Disconnect-MgGraph
}
else #If NO failures are present this email will be sent
{
    # Create message body and properties and send
    $MessageParams = @{
        subject        = "No workflow failures detected today"
        body           = @{
            contentType = 'HTML' 
            content     = "
                <body style='margin:0; padding:0; font-family:'Segoe UI',sans-serif'>
                    <table style='margin: 0px auto; border-collapse: separate; width: 90%;' width='90%' cellspacing='0' cellpadding='0' align='center'>
                        <tbody>
                            <tr>
                                <td style='width: 1.61812%;' colspan='2'>
                                    <h1 style='text-align: center;'>No workflow failures detected</h1>
                                </td>
                            </tr>
                            <tr>
                                <td style='padding: 30px 40px 10px; width: 1.61812%;' colspan='2'>
                                    <p style='font-size: 20px;'>What do you need to do?</p>
                                    <p>Nothing!</p>
                                    <p>Failures: $($failedexecutions.count)</p>
                                </td>
                            </tr>
                            
                        </tbody>"
        }
        "toRecipients" = @(
            @{
                "emailAddress" = @{"address" = "EmailTo" }
            } ) 
        "ccRecipients" = @(
            @{
                "emailAddress" = @{"address" = "EmailCC" }
            }
        )       
    }
    # Connect to MG Graph for Mail Send
    Connect-MgGraph -ClientId $params.ApplicationId -CertificateThumbprint $Params.CertificateThumbPrint -TenantId $TenantId
    Send-MgUserMail  -UserId [email protected] -Message $MessageParams
    Disconnect-MgGraph
}
#endregion send mail notification
1 Like

Not intending to be a joke, but you could probably do this in a workflow in IDN as well…
set up a Scheduled Trigger to run an HTTP request back to IDN to get the list of workflows

Then you would loop through the results to check if the status was failed, and send an email.

Hello Dylan, the intention was to not use workflows to find failures in workflows. In the past errors have come from workflows being degraded.

2 Likes