Skip to content

Event notification types

See the following sections for the type of notification you're configuring. Each section provides example CEL expressions.

Common Expression Language

The Common Expression Language (CEL) uses a simple syntax similar to expressions in C++, Java, JavaScript, and Go. CEL expressions are usually concise, single-line statements that evaluate to a single value. If the evaluation result is 'true', the system triggers a notification to the specified integration; otherwise, no action is taken.

Inputs to a CEL expression are called 'variables'. Each field within the event can be used as a variable in the CEL expression. CEL comes with standard language functions as defined in the official specification.

cert-manager unhealthy status for issuer resource

Use the following details of the event data that are available for filtering purposes in your CEL expression. See the example provided for specific use cases.

{
  "type": "evt.healthstatus.cert-manager-issuer.notready",
  "data": {
    "clusterId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "clusterName": "demo-cluster",
    "issuerName": "demo-issuer",
    "namespace": "demo-namespace",
    "resourceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "statusMessage": "Failed to register ACME account: Get \"https://invalid-url\": dial tcp: lookup invalid-url on 10.96.0.10:53: no such host",
    "statusReason": "ErrRegisterACMEAccount",
    "statusTransition": "2025-03-05T15:53:51Z"
  }
}

CEL expression examples

Use the following examples to create API requests for router configurations.

Unhealthy issuer CEL expression examples:

  • All unhealthy certificate manager issuer notifications:

    type == 'evt.healthstatus.cert-manager-issuer.notready'
    
  • Issuers in an unhealthy state for specific clusters:

    type == 'evt.healthstatus.cert-manager-issuer.notready' && (data.clusterId == 'clusterID-1' || data.clusterId == 'clusterID-2') |  (data.clusterId == 'clusterID-1' || data.clusterId == 'clusterID-2')
    
  • Unhealthy cert-manager issuer deployed in a specific namespace:

    type == 'evt.healthstatus.cert-manager-issuer.notready' && data.namespace == 'demo-namespace'
    
  • All cert-manager unhealthy and healthy state restored events:

    type.startsWith('evt.healthstatus.cert-manager-issuer')
    

cert-manager issuer resource healthy state restored

Use the following details of the event data that are available for filtering purposes in your CEL expression. See below the data example for specific examples.

{
  "type": "evt.healthstatus.cert-manager-issuer.active",
  "data": {
    "clusterId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "clusterName": "demo-cluster",
    "issuerName": "demo-issuer",
    "namespace": "demo-namespace",
    "resourceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "statusMessage": "The ACME account was registered with the ACME server",
    "statusReason": "ACMEAccountRegistered",
    "statusTransition": "2025-03-05T16:24:46Z",
    "unhealthyDuration": "30m13.049891s"
  }
}

CEL expression examples

  • All health state restored cert-manager issuer notifications:

    type == 'evt.healthstatus.cert-manager-issuer.active'
    
  • Specific issuer restored to healthy status:

    type == 'evt.healthstatus.cert-manager-issuer.notready' && data.issuerName == 'my-issuer'
    
  • All cert-manager unhealthy and healthy state restored events:

    type.startsWith('evt.healthstatus.cert-manager-issuer')
    

cert-manager unhealthy status for certificate resource

Use the following details of the event data that are available for filtering purposes in your CEL expression. See below the data example for specific examples.

{
    "type": "evt.healthstatus.cert-manager-certificate-resource.notready",
    "data": {
        "clusterName": "My Cluster",
        "clusterId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "certificateName": "test-cert",
        "namespace": "my-namespace",
        "issuerName": "missing-issuer",
        "statusMessage": "Issuing certificate as Secret does not exist",
        "unhealthyDuration": "166h51m46.031628918s",
        "statusReason": "DoesNotExist",
        "statusTransition": "2025-02-10T08:12:22Z",
        "subject": {
            "commonName": "example-service",
            "countries": [
                "US"
            ],
            "localities": [
                "South Lake City"
            ],
            "organizationalUnits": [
                "Engineering"
            ],
            "organizations": [
                "example.com"
            ],
            "provinces": [
                "Utah"
            ],
        },
        "SANs": {
            "DNS Names": [
                "example.com"
            ]
        },
    }
}

CEL expression examples

  • All cert-manager certificate resource unhealthy notifications:

    type == 'evt.healthstatus.cert-manager-certificate-resource.notready'
    
  • All cert-manager certificate resource unhealthy notifications for My Cluster:

    type == 'evt.healthstatus.cert-manager-certificate-resource.notready' && data.clusterName == 'My Cluster'
    
  • All cert-manager certificate resource unhealthy and healthy state restored events:

    type.startsWith('evt.healthstatus.cert-manager-certificate-resource')
    

cert-manager certificate resource healthy state restored

Use the following details of the event data that are available for filtering purposes in your CEL expression. See below the data example for specific examples.

{
    "type": "evt.healthstatus.cert-manager-certificate-resource.active",
    "data": {
      "SANs": {},
      "certificateName": "example-cert",
      "clusterId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "clusterName": "My Cluster",
      "issuerName": "my-selfsigned-issuer",
      "namespace": "default",
      "resourceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "statusMessage": "Certificate is up to date and has not expired",
      "statusReason": "Ready",
      "statusTransition": "2025-03-06T15:48:33Z",
      "subject": {
        "commonName": "example-service",
        "countries": [
          "US"
        ],
        "localities": [
          "South Lake City"
        ],
        "organizationalUnits": [
          "Engineering"
        ],
        "organizations": [
          "My Company"
        ],
        "provinces": [
          "Utah"
        ]
      },
      "unhealthyDuration": "6m24.21461s"
    }
}

CEL expression examples

  • All cert-manager certificate resource healthy state restored:

    type == 'evt.healthstatus.cert-manager-certificate-resource.active'
    
  • All cert-manager certificate resource healthy notifications for My Cluster:

    type == 'evt.healthstatus.cert-manager-certificate-resource.active' && data.clusterName == 'My Cluster'
    
  • All cert-manager certificate resource unhealthy and healthy state restored events:

    type.startsWith('evt.healthstatus.cert-manager-certificate-resource')
    

Certificate expiration

Certificate expiration notifications require the certificate monitoring service to be enabled and configured in Venafi Control Plane. After you verify your monitoring service configuration, you'll set up the routing for the notifications to be received in notification channel.

Enable and configure the global certificate monitoring service

Note

Setting up the monitoring configuration can also be done in the Venafi Control Plane UI. Note that any changes made to the monitoring configuration affects email and webhook notifications.

Before making any changes to the global configuration, let's first view the current configuration to see what needs to be updated.

You can view the current configuration by sending the following API request:

GET https://api.venafi.cloud/outagedetection/v1/inventorymonitoringconfig/CERTIFICATE_EXPIRATION
tppl-api-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
The response body should look something like this:

{
  "id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "companyId":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "configuration":{
    "inventoryMonitoringConfigurationType":"CERTIFICATE_EXPIRATION",
    "enabled":false,
    "thresholds":[],
    "applicationIds":[],
    "includeUnassignedCertificates":false
  }
}

Parameter descriptions

  • id - The unique ID of this inventory monitoring configuration.
  • companyId - The unique ID of your company.
  • inventoryMonitoringConfigurationType - The configuration type. For the purposes of this guide, the value should be CERTIFICATE_EXPIRATION.
  • enabled - Boolean that enables or disables this inventory monitor.
  • thresholds - Array of certificate expiration thresholds, in days, for when notifications will be sent. Limit is 3 values.
  • applicationIds - Array of application IDs that the webhook applies to. If blank, all applications are monitored. Notifications aren't sent for applications that aren't monitored, even if the application is specified in the webhook configuration (below). We strongly recommend monitoring all applications.
  • includeUnassignedCertificates - Boolean that enables or disables notifications for certificates that aren't assigned to an application.

Now that we've viewed the current configuration, we'll edit and enable the configuration. In this example, we'll do the following:

  • Enable certificate monitoring
  • Set notification thresholds of 5, 30, and 90 days
  • Specify two application IDs that this configuration should apply to
  • Disable notifications for unassigned certificates

We'll do this by sending the following request:

PUT https://api.venafi.cloud/outagedetection/v1/inventorymonitoringconfig/CERTIFICATE_EXPIRATION
tppl-api-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Content-Type: application/json

{
  "inventoryMonitoringConfiguration":{
    "inventoryMonitoringConfigurationType":"CERTIFICATE_EXPIRATION",
    "enabled":true,
    "thresholds":[
      5,
      30,
      90
    ],
    "applicationIds":[
      "4b7e4cd0-9009-11ed-95eb-4397cbb5e509",
      "56c28f10-9009-11ed-bb6f-1142ca678b4b"
    ],
    "includeUnassignedCertificates":false
  }
}
Additional request body examples

Monitor all applications:

{
  "inventoryMonitoringConfiguration":{
    "inventoryMonitoringConfigurationType":"CERTIFICATE_EXPIRATION",
    "enabled":true,
    "thresholds":[
     5,
     30,
     90
    ],
    "applicationIds":[

    ],
    "includeUnassignedCertificates":true
  }
}

Monitor only certificates assigned to any application:

{
  "inventoryMonitoringConfiguration":{
    "inventoryMonitoringConfigurationType":"CERTIFICATE_EXPIRATION",
    "enabled":true,
    "thresholds":[
     5,
     30,
     90
    ],
    "applicationIds":[

    ],
    "includeUnassignedCertificates":false
  }
}

Monitor all certificates assigned to specific applications and certificates not assigned:

{
  "inventoryMonitoringConfiguration":{
    "inventoryMonitoringConfigurationType":"CERTIFICATE_EXPIRATION",
    "enabled":true,
    "thresholds":[
     5,
     30,
     90
    ],
    "applicationIds":[
      "application-id-1",
      "application-id-2"

    ],
    "includeUnassignedCertificates":true
  }
}

Setting up the routing configuration

Event details:

{
  "type": "evt.policy.expiringcertificates.failed",
  "data": {
    "name": "Certificate Expiration Notification",
    "applicationIds": [
      "6ab46c90-acd7-11ef-8b23-f5be1d4bb686"
    ],
    "message": "Certificate Example.com, with id: 6f42f560-acd7-11ef-a386-5be8e97f7088, serial number: 00853F3D26CE90A8007B170DF85462F285, issued by: cn=example.com - 177115678443066294238404735833232044677,o=Example Co., assigned to: [Example-App] has 30 day(s) until expiration. Valid until: 2025-01-01 01:01:01. Please renew and provision the certificate to avoid a potential outage.",
    "notificationDate": "2024-11-27T16:38:38.212+00:00"
  }
}

CEL expression examples

  • All certificate expiration notifications for every monitored application:

    type == 'evt.policy.expiringcertificates.failed'
    
  • Certificate expiration notifications assigned to a particular application:

    type == 'evt.policy.expiringcertificates.failed' && '6ab46c90-acd7-11ef-8b23-f5be1d4bb686' in data.applicationIds
    

Other useful GraphQL requests

List all configured notification providers:

curl --request POST \
  --url https://api.venafi.cloud/graphql \
  --header 'tppl-api-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
  --header 'Content-Type: application/json' \
  --data '{
    "query": "query GetIntegrationsListData { integrations { nodes { id name enabled } } }",
    "operationName": "GetIntegrationsListData"
  }'

Delete a notification provider:

curl --request POST \
  --url https://api.venafi.cloud/graphql \
  --header 'tppl-api-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
  --header 'Content-Type: application/json' \
  --data '{
    "query": "mutation DeleteIntegrations($ids: [UUID!]!) { deleteIntegrations(ids: $ids) { ids __typename } }",
    "operationName": "DeleteIntegrations",
    "variables": {
      "ids": [
        "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
      ]
    }
  }'

List routing configurations:

curl --request POST \
  --url https://api.venafi.cloud/graphql \
  --header 'tppl-api-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
  --header 'Content-Type: application/json' \
  --data '{
    "query":" query SearchNotificationRoutingConfigurations { searchNotificationRoutingConfigurations { nodes { id enabled notificationRouterFilterConfig { notificationRouterCelExpression } } } }",
    "operationName":"SearchNotificationRoutingConfigurations"
  }'

Disable routing configurations:

curl --request POST \
  --url https://api.venafi.cloud/graphql \
  --header 'tppl-api-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
  --header 'Content-Type: application/json' \
  --data '{
    "query": "mutation UpdateNotificationRouter($id: UUID!, $enabled: Boolean) { updateNotificationRoutingConfiguration(id: $id, enabled: $enabled) { id enabled } }",
    "operationName": "UpdateNotificationRouter",
    "variables": {
      "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "enabled": false
    }
  }'

Delete routing configurations:

curl --request POST \
  --url https://api.venafi.cloud/graphql \
  --header 'tppl-api-key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
  --header 'Content-Type: application/json' \
  --data '{
  "query": "mutation DeleteNotificationRouting($deleteNotificationRoutingId: UUID!) { deleteNotificationRouting(id: $deleteNotificationRoutingId) { id } }",
  "operationName": "DeleteNotificationRouting",
  "variables": {
    "deleteNotificationRoutingId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }
}'