Dec 19th, 2018: [EN][Heartbeat] Configure a TLS expiration notification using Heartbeat

In my previous blog on uptime monitoring, we had discussed the general availability of Heartbeat and its main functionalities. In a nutshell, Heartbeat is a lightweight shipper which executes periodic checks to verify whether an endpoint is up or down, then reports this information along with other useful metrics to Elasticsearch. This information is automatically displayed in pre-built Kibana dashboards for turnkey uptime monitoring.

In this blog I would like to cover one of the new features we’ve added to Heartbeat, TLS information. Starting from 6.5, Heartbeat, will retrieve TLS information from the end point it is checking.

In a heartbeat document, the field will have the following structure:

"tls": {
    "certificate_not_valid_before": "2016-01-18T00:00:00.000Z"
    "certificate_not_valid_after": "2019-03-27T12:00:00.000Z",
    "certificates": ["-----BEGIN CERTIFICATE-----\nMIIFJzC..."],
    "rtt": {"handshake": {"us": 131673}},
  }

Let’s examine two fields "certificate_not_valid_before" and "certificate_not_valid_after". Those are date fields which provide the TLS certificate’s date metadata.

Ok, so what can we do with those fields?

With this useful information, we can create an alert (a watch), to send notifications when a specific certification is about to expire.

To do so, let’s navigate to the Watcher section.

In Kibana go to “Management” ->”ElasticSearch” ->”Watcher” (you would need a gold license at the minimum to access it). We will then need to create an advance watch and replace the default JSON
tls_advent
with the following one :

{
  "trigger": {
    "schedule": {
      "interval": "1d"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          "heartbeat-*"
        ],
        "types": [],
        "body": {
          "size": 0,
          "query": {
            "range": {
              "tls.certificate_not_valid_after": {
                "lte": "now+30d"
              }
            }
          },
          "aggs": {
            "byid": {
              "terms": {
                "field": "monitor.id"
              }
            }
          }
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": {
        "gte": 1
      }
    }
  },
  "actions": {
    "my-logging-action": {
      "logging": {
        "level": "info",
        "text": "The certificates for {{#ctx.payload.aggregations.byid.buckets}}{{key}}{{/ctx.payload.aggregations.byid.buckets}} will expire soon!."
      }
    }
  }
}

Simple, right? Ok, done! Not really.

Let’s examine what we just did:

In the first section of the watch we set the interval of the alert

{
  "trigger": {
    "schedule": {
      "interval": "1d"
    }
  },

The interval will determine how often we want the alert to run, on this example the interval is set for 1 day ("1d"), you can use seconds (s), minutes (m) if needed. (use a short interval e.g. “10s” for testing purposes, then when the alert is working as expected, change it to the desire interval e.g. day/week).

In the second part we defined on which indices the alert should be applied on, you should modify “heartbeat-*” to the index that heartbeat is indexing its information to.

 "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          "heartbeat-*"

Next, we want to decide on the alert condition, in this example we will trigger the alert on every certificate which will expire in the next 10 years (for testing purposes only), in a real world scenario you would likely to change it for 30 days or more (e.g. “now+30d”).

   "types": [],
        "body": {
          "size": 0,
          "query": {
            "range": {
              "tls.certificate_not_valid_after": {
                "lte": "now+10y"

The last section is the alert actions, which specify what happens when the watch condition is met. In this example we configured the alert to print a message to our logs using the name of the end point. In this example, if we monitor our web page “https://www.elastic.co”, the message on the logs would be “The certificates for https://www.elastic.co will expire soon!.”

  "actions": {
    "my-logging-action": {
      "logging": {
        "level": "info",
        "text": "The certificates for {{#ctx.payload.aggregations.byid.buckets}}{{key}}{{/ctx.payload.aggregations.byid.buckets}} will expire soon!."
      }
    }
  }

You can configure additional actions such as: email, webhook, index, hipchat, Slack, and pagerduty.

That’s it, you can now hit the save button and activate the alert. Following this you should see the following lines in Elasticsearch logs.

Now you can define your own alerts, conditions and actions.

Watcher & Heartbeat resources
I hope you find this tutorial useful. For more information on our alerting capabilities visit our watcher page on our documentation to learn more.

If you have questions, please engage with us on the Heartbeat Discuss forum, and if you find any issues or would like to file an enhancement request, please do so on github

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.