0

Monitor your STIR/SHAKEN Certificate using Cronitor

In this article we will describe how to monitor your Sansay S/S certificate for organizations that use Cronitor. Cronitor provides infrastructure monitoring as a service to monitor scheduled stats, application status, metrics and more.

This cronitor integration will track the days remaining for your STIR/SHAKEN certificate in addition to the certificate's repository (CR) availability and latency.

Since monitoring the days remaining is the integration that requires more detail and we will start with that.

To monitor your STIR/SHAKEN certificate days remaining we define a cronitor "Heartbeat" script.

This heartbeat script is set to report an event if user defined assertions fail to meet expectations. We have defined in the node.js script and cronitor.io success being > 30 days. If under < 30 days then it is an error condition that will follow any notifications or events you have configured in Cronitor.

  • Node.js: Make sure Node.js is installed on your system. You can download it from nodejs.org.
  • Sansay CR URL: You will need the URL from which the STIR/SHAKEN certificate can be downloaded (e.g. https://cr.sansay.com/.......)
  • Cronitor Account: Ensure you have a Cronitor account and access to create or modify monitors.
    • Cronitor Monitor URL: Create or configure a heartbeat monitor in Cronitor and obtain the monitor URL 
  1. Create Monitor

  2. Choose Heartbeat monitor type 

  3. Define the heartbeat. This will be customized by you.
    1. We recommend a cronjob schedule of 24 hours. This will need to match your node.js script runtime running once per day. 
  1. Create a .env file in the root directory of your project and add the following entries to store sensitive configuration details securely:
    1. CERTIFICATE_URL=<Sansay CR URL to your certificate>
    2. DAYS_LEFT_URL=<Your Cronitor monitor URL for days left>
    3. CRONITOR_API_KEY=<Your Cronitor API key>

Open a terminal in your project directory and run the following command to install necessary Node.js packages:

  • npm install axios dotenv cronitor
require('dotenv').config();
const axios = require('axios');
const { exec } = require('child_process');
const fs = require('fs');
// Load the URL for days left from .env
const CERTIFICATE_URL = process.env.CERTIFICATE_URL;
const DAYS_LEFT_URL = process.env.DAYS_LEFT_URL;
async function downloadCertificate() {
    try {
        const response = await axios({
            url: CERTIFICATE_URL,
            method: 'GET',
            responseType: 'arraybuffer'
        });

        if (response.status === 200) {
            fs.writeFileSync('certificate.pem', response.data);
            console.log('Certificate downloaded successfully');
            return true;

        } else {
            console.error(`Failed to download certificate: Status ${response.status}`);
            return false;
        }

    } catch (error) {
        console.error('Error downloading certificate:', error);
        return false;
    }
}


function inspectCertificate() {
    exec('openssl x509 -in certificate.pem -noout -enddate', (error, stdout, stderr) => {
        if (error) {
            console.error('Error inspecting the certificate:', error);
            return;
        }

        if (stderr) {
            console.error('OpenSSL Error:', stderr);
            return;
        }

        const endDateMatch = stdout.match(/notAfter=(.*)/);
        if (endDateMatch) {
            const endDate = new Date(endDateMatch[1].trim());
            const today = new Date();
            const timeDiff = endDate.getTime() - today.getTime();
            const daysUntilExpiry = Math.ceil(timeDiff / (1000 * 3600 * 24));
            console.log(`Certificate expires in ${daysUntilExpiry} days`);
            sendDaysLeftPing(daysUntilExpiry);
        }
    });
}


function sendDaysLeftPing(days) {
    // Start with the base URL
    let url = `${DAYS_LEFT_URL}`;
    // Conditionally add the 'state' parameter
    if (days <= 30) {
        url += '?state=fail';
    }

    // Append the 'msg' parameter
    // Use '&' if 'state=fail' was added, otherwise use '?'
    url += (days > 30 ? '?' : '&') + `msg=${encodeURIComponent(days + ' days left until certificate expires')}`;
    axios.get(url)
        .then(response => console.log(`Days left ping successful: ${days} days left`, response.status))
        .catch(error => console.error('Failed to ping Cronitor for days left', error));
}
async function main() {
    if (await downloadCertificate()) {
        inspectCertificate();
    }
}
main();

 

 

 

To monitor the availability and latency of your certificate you can create a Cronitor Check monitor type.

  1. Create a "Check" monitor type

  2. Define your certificate URL, acceptable criteria and notifications. We recommend every 15 minutes and latency under 250ms as general checks.

Reply

null