This workflow corresponds to n8n.io template #9865 — we link there as the canonical source.
This workflow follows the Executecommand → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "Gd16MTYoXemtNKQV",
"name": "PKI Certificate & CRL Monitor - Auto Expiration Alert System",
"tags": [],
"nodes": [
{
"id": "f534d56c-96c0-43c9-b050-71f118c2d83e",
"name": "Write Binary - TempFile : crlfile.der",
"type": "n8n-nodes-base.writeBinaryFile",
"onError": "continueErrorOutput",
"position": [
544,
224
],
"parameters": {
"options": {},
"fileName": "crlfile.der"
},
"typeVersion": 1
},
{
"id": "34380de6-6c48-49d4-bc78-53c21c052960",
"name": "B64 Encode : crlfile.der",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
736,
224
],
"parameters": {
"command": "=base64 -w0 crlfile.der"
},
"typeVersion": 1
},
{
"id": "e9f2ab03-bdf8-4869-8d49-100ce8fc001f",
"name": "OpenSSL Parse CRL : crlfile.der",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
928,
224
],
"parameters": {
"command": "=echo {{ $json.stdout }} | base64 -d | openssl crl -inform DER -text -noout"
},
"typeVersion": 1
},
{
"id": "36741ac9-ae4d-4875-99d0-08e6062fa6ae",
"name": "Parse Data OpenSSL output",
"type": "n8n-nodes-base.code",
"onError": "continueRegularOutput",
"position": [
544,
448
],
"parameters": {
"jsCode": "// A parancs eredm\u00e9nye a bemenet json stdout mez\u0151j\u00e9ben\nconst output = items[0].json.stdout;\n\n// Regex a Last Update kinyer\u00e9s\u00e9hez\nconst lastUpdateMatch = output.match(/Last Update:\\s*(.+)/);\nconst lastUpdate = lastUpdateMatch ? lastUpdateMatch[1].trim() : null;\n\n// Regex a Next Update kinyer\u00e9s\u00e9hez\nconst nextUpdateMatch = output.match(/Next Update:\\s*(.+)/);\nconst nextUpdate = nextUpdateMatch ? nextUpdateMatch[1].trim() : null;\n\n// Regex a CN kinyer\u00e9s\u00e9hez az Issuer sz\u00f6vegb\u0151l\nconst issuerMatch = output.match(/Issuer:(.+)/);\nlet cn = null;\nif (issuerMatch) {\n // issuer sz\u00f6veg, p\u00e9ld\u00e1ul: \" C=HU, L=Budapest, O=NetLock Kft., CN=NetLock K\u00f6zigazgat\u00e1si (Class B) Tan\u00fas\u00edtv\u00e1nykiad\u00f3, emailAddress=user@example.com\"\n const issuer = issuerMatch[1];\n const cnMatch = issuer.match(/CN=([^,]+)/);\n if (cnMatch) {\n cn = cnMatch[1].trim();\n }\n}\n\nreturn [\n {\n json: {\n lastUpdate,\n nextUpdate,\n issuerCN: cn\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "da9f9fa7-4673-4756-b46e-c321f7d96a5c",
"name": "Get CRL URL",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
64,
224
],
"parameters": {
"url": "={{ $('Loop Over Items -- Process Checking').item.json.urls }}",
"options": {
"timeout": 10000,
"fullResponse": true
},
"responseFormat": "file"
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "5511f825-df07-4860-bbb3-fa5d10ba409a",
"name": "nextUpdate - TimeFilter",
"type": "n8n-nodes-base.code",
"onError": "continueRegularOutput",
"position": [
736,
448
],
"parameters": {
"jsCode": "const lastUpdate = items[0].json.lastUpdate;\nconst nextUpdate = items[0].json.nextUpdate;\nconst issuerCN = items[0].json.issuerCN;\n\n// A \"nextUpdate\" stringb\u0151l Date objektum k\u00e9sz\u00edt\u00e9se\nconst nextUpdateDate = new Date(nextUpdate + ' UTC'); // Hozz\u00e1adva az UTC id\u0151z\u00f3na\n\nconst now = new Date();\n\n// K\u00fcl\u00f6nbs\u00e9g milliszekundumban\nconst diffMs = nextUpdateDate.getTime() - now.getTime();\n\n// K\u00fcl\u00f6nbs\u00e9g \u00f3r\u00e1kban\nconst diffHours = diffMs / (1000 * 60 * 60);\n\nlet crlStatus = null;\nif (diffHours < 17) {\n crlStatus = \"ALERT!\";\n}\nelse {\n crlStatus = \"READY!\";\n}\n\nreturn [\n {\n json: {\n lastUpdate,\n nextUpdate,\n issuerCN,\n crlStatus\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "c67c0c20-5c84-4719-bb04-87421a0a780d",
"name": "Good Or Evil",
"type": "n8n-nodes-base.if",
"onError": "continueRegularOutput",
"position": [
928,
448
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.crlStatus }}",
"value2": "ALERT!"
}
]
}
},
"retryOnFail": false,
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "b6ad3fe3-cc8f-42de-817f-e2e792b2ba0c",
"name": "Is this CRL ?",
"type": "n8n-nodes-base.if",
"onError": "continueRegularOutput",
"position": [
-304,
800
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.urls }}",
"value2": "crl=",
"operation": "contains"
},
{
"value1": "={{ $json.urls }}",
"value2": ".crl",
"operation": "contains"
}
]
},
"combineOperation": "any"
},
"retryOnFail": false,
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "dfe406c4-0265-4f66-ab1a-b66c853e6cef",
"name": "Execute With Manual Start",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-1504,
784
],
"parameters": {},
"typeVersion": 1
},
{
"id": "670d00ba-a16f-403e-b1d4-eb3c794d97d5",
"name": "Execute With Scheduled Start",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1504,
592
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 12
}
]
}
},
"typeVersion": 1
},
{
"id": "281ba72f-bb26-4357-90a9-8d763b1da10e",
"name": "Get Url From List",
"type": "n8n-nodes-base.splitOut",
"position": [
-800,
784
],
"parameters": {
"options": {
"destinationFieldName": "urls"
},
"fieldToSplitOut": "[''].urls"
},
"typeVersion": 1
},
{
"id": "fa23324d-488d-4283-a3a1-62ff8460f3c2",
"name": "Loop Over Items -- Process Checking",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-576,
784
],
"parameters": {
"options": {},
"batchSize": "=1"
},
"typeVersion": 3
},
{
"id": "19aae3c1-7d59-4ec7-ae8e-acf61e36558b",
"name": "Website Available?",
"type": "n8n-nodes-base.if",
"onError": "continueRegularOutput",
"position": [
496,
1520
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.statusCode }}",
"value2": 200,
"operation": "equal"
}
]
}
},
"retryOnFail": true,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "e360e1f4-71cb-4464-8202-918061e32af5",
"name": "Wait B4 Retry",
"type": "n8n-nodes-base.wait",
"position": [
720,
1584
],
"parameters": {},
"retryOnFail": false,
"typeVersion": 1.1
},
{
"id": "b7d85fc7-9e97-4131-b41d-d818194874a3",
"name": "Website Available Now?",
"type": "n8n-nodes-base.if",
"onError": "continueRegularOutput",
"position": [
1136,
1584
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.statusCode }}",
"value2": 200,
"operation": "equal"
}
]
}
},
"executeOnce": true,
"notesInFlow": false,
"retryOnFail": false,
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "79f9b18a-9949-4f49-a448-cc919f94b5b2",
"name": "Send Website Down - Telegram & SMS",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
1376,
1600
],
"parameters": {
"command": "=apk add curl\n\nexport TOKEN=\"YOUR-TELEGRAM-BOT-TOKEN\"\nexport CHAT_ID=\"YOUR-TELEGRAM-CHANNEL-ID\"\nexport MESSAGE=\"ALERT! The {{ $('Wait B4 Retry').item.json.urls }} !!!NOT AVAILABLE!!! Szolg\u00e1ltat\u00e1skies\u00e9s val\u00f3sz\u00edn\u0171s\u00edthet\u0151! Beavatkoz\u00e1st ig\u00e9nyel!\"\n\nuntil [ \"$(curl -s -o /dev/null -w '%{http_code}' -X POST \"https://api.telegram.org/bot$TOKEN/sendMessage\" -d chat_id=\"$CHAT_ID\" -d text=\"$MESSAGE\")\" = \"200\" ]; do\n echo \"Retry ...\"\n sleep 5 # wait 5 second before retry to send\ndone\n\nNUMBERS=\"+36301234567\"\n\nfor PHONE in $NUMBERS; do\n curl -X POST https://textbelt.com/text --data-urlencode phone=\"$PHONE\" --data-urlencode message=\"$MESSAGE\" -d key=YOUR-TEXTBELT-API-KEY\ndone"
},
"typeVersion": 1
},
{
"id": "e22d65ca-e905-427b-ab47-c957e7c11566",
"name": "Respose Extend With Requested URL",
"type": "n8n-nodes-base.set",
"position": [
256,
1520
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "38657d36-16fb-42b5-88e0-0bbe595ab75a",
"name": "urls",
"type": "string",
"value": "={{ $('Loop Over Items -- Process Checking').item.json.urls }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "c4ab3c1b-84d9-4daf-b34e-8c0587cf4e46",
"name": "Is this CA?",
"type": "n8n-nodes-base.if",
"onError": "continueRegularOutput",
"position": [
-128,
1088
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.urls }}",
"value2": "ca=",
"operation": "contains"
},
{
"value1": "={{ $json.urls }}",
"value2": ".crt",
"operation": "contains"
},
{
"value1": "={{ $json.urls }}",
"value2": ".cer",
"operation": "contains"
}
]
},
"combineOperation": "any"
},
"retryOnFail": false,
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "2ef0fb3b-2c24-4659-8513-29a9f7a56426",
"name": "Get Non-CRL/CA URL",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
48,
1520
],
"parameters": {
"url": "={{ $json.urls }}",
"options": {
"timeout": 10000,
"fullResponse": true
},
"responseFormat": "string"
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "385b159e-ff10-4808-8587-8457699b38fc",
"name": "Retry to Non-CRL/CA URL",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
928,
1584
],
"parameters": {
"url": "={{ $json.urls }}",
"options": {
"timeout": 10000,
"fullResponse": true
},
"responseFormat": "string"
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "5391174f-027e-45dc-96c3-563b4cacd18a",
"name": "nextUpdate - TimeFilter1",
"type": "n8n-nodes-base.code",
"onError": "continueRegularOutput",
"position": [
736,
1104
],
"parameters": {
"jsCode": "const notBefore = items[0].json.notBefore;\nconst notAfter = items[0].json.notAfter;\nconst subjectCN = items[0].json.subjectCN;\n\nconst notAfterDate = new Date(notAfter + ' UTC');\nconst now = new Date();\n\nlet caStatus = null;\n\nif (now > notAfterDate) {\n caStatus = \"EXPIRED!\";\n} else {\n const diffMs = notAfterDate.getTime() - now.getTime();\n const diffHours = diffMs / (1000 * 60 * 60);\n\n if (diffHours < 17) {\n caStatus = \"ALERT!\";\n } else {\n caStatus = \"READY!\";\n }\n}\n\nreturn [\n {\n json: {\n notBefore,\n notAfter,\n subjectCN,\n caStatus\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "f42134d4-2784-4144-97bb-3475943cedd1",
"name": "Get CA URL",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
64,
880
],
"parameters": {
"url": "={{ $('Loop Over Items -- Process Checking').item.json.urls }}",
"options": {
"timeout": 10000,
"fullResponse": true
},
"responseFormat": "file"
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "08e81b7b-8098-477d-b0a1-60da3a24e0ed",
"name": "Write Binary - TempFile : cacertfile.crt",
"type": "n8n-nodes-base.writeBinaryFile",
"onError": "continueErrorOutput",
"position": [
544,
880
],
"parameters": {
"options": {},
"fileName": "cacertfile.crt"
},
"typeVersion": 1
},
{
"id": "b1d772fb-a35e-493d-887f-48178d141079",
"name": "B64 Encode : cacertfile.crt",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
800,
880
],
"parameters": {
"command": "=base64 -w0 cacertfile.crt"
},
"typeVersion": 1
},
{
"id": "117820d2-0409-48ff-b405-bfebc25211ad",
"name": "OpenSSL Parse CA Cert : cacertfile.crt",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
1056,
880
],
"parameters": {
"command": "=echo {{ $json.stdout }} | base64 -d | openssl x509 -text -noout"
},
"typeVersion": 1
},
{
"id": "b14e139c-d012-438c-ba1d-135ebba7270a",
"name": "Parse Data OpenSSL CA output",
"type": "n8n-nodes-base.code",
"onError": "continueRegularOutput",
"position": [
544,
1104
],
"parameters": {
"jsCode": "const output = items[0].json.stdout;\n\nconst notBeforeMatch = output.match(/Not Before:\\s*(.+)/);\nconst notBefore = notBeforeMatch ? notBeforeMatch[1].trim() : null;\n\nconst notAfterMatch = output.match(/Not After\\s*:\\s*(.+)/);\nconst notAfter = notAfterMatch ? notAfterMatch[1].trim() : null;\n\nconst subjectMatch = output.match(/Subject:(.+)/);\nlet cn = null;\nif (subjectMatch) {\n const subject = subjectMatch[1];\n const cnMatch = subject.match(/CN=([^,]+)/);\n if (cnMatch) {\n cn = cnMatch[1].trim();\n }\n}\n\nreturn [\n {\n json: {\n notBefore,\n notAfter,\n subjectCN: cn\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "31e7d68c-76ed-4c82-84c1-4601964fe08c",
"name": "Alive?",
"type": "n8n-nodes-base.if",
"onError": "continueRegularOutput",
"position": [
928,
1104
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.caStatus }}",
"value2": "READY!",
"operation": "notEqual"
}
]
}
},
"retryOnFail": false,
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "ccc0773c-2959-4362-9d12-4997d3204766",
"name": "Set-Info for CA Alert",
"type": "n8n-nodes-base.set",
"position": [
1168,
1088
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "9f7b593a-b347-4fdf-92eb-39e87079846f",
"name": "notBefore",
"type": "string",
"value": "={{ $json.notBefore }}"
},
{
"id": "4e19e584-2a4c-4195-b214-1c38b9cbfc41",
"name": "notAfter",
"type": "string",
"value": "={{ $json.notAfter }}"
},
{
"id": "7728e719-2daf-4817-8943-d3816391b852",
"name": "subjectCN",
"type": "string",
"value": "={{ $json.subjectCN }}"
},
{
"id": "38657d36-16fb-42b5-88e0-0bbe595ab75a",
"name": "caStatus",
"type": "string",
"value": "={{ $json.caStatus }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "0365cd24-bdb4-4a0d-8170-49ac2b24066c",
"name": "Set-Info for CRL Alert",
"type": "n8n-nodes-base.set",
"position": [
1168,
432
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "9f7b593a-b347-4fdf-92eb-39e87079846f",
"name": "lastUpdate",
"type": "string",
"value": "={{ $json.lastUpdate }}"
},
{
"id": "4e19e584-2a4c-4195-b214-1c38b9cbfc41",
"name": "nextUpdate",
"type": "string",
"value": "={{ $json.nextUpdate }}"
},
{
"id": "7728e719-2daf-4817-8943-d3816391b852",
"name": "issuerCN",
"type": "string",
"value": "={{ $json.issuerCN }}"
},
{
"id": "38657d36-16fb-42b5-88e0-0bbe595ab75a",
"name": "crlStatus",
"type": "string",
"value": "={{ $json.crlStatus }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "1c2824e9-5194-406d-960e-5c7bfe9b82d7",
"name": "CRL Alert --- Telegam & SMS",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
1392,
432
],
"parameters": {
"command": "=apk add curl\n\nexport TOKEN=\"YOUR-TELEGRAM-BOT-TOKEN\"\nexport CHAT_ID=\"YOUR-TELEGRAM-CHANNEL-ID\"\nexport MESSAGE=\"{{ $json.crlStatus }} with {{ $json.issuerCN }} !!!CRL EXPIRATION!!! Will be under 17 hour ({{ $json.nextUpdate }})! Last updated: {{ $json.lastUpdate }}\"\n\ncurl -s -X POST \"https://api.telegram.org/bot$TOKEN/sendMessage\" -d chat_id=\"$CHAT_ID\" -d text=\"$MESSAGE\"\n\nNUMBERS=\"+36301234567\"\n\nfor PHONE in $NUMBERS; do\n curl -X POST https://textbelt.com/text --data-urlencode phone=\"$PHONE\" --data-urlencode message=\"$MESSAGE\" -d key=YOUR-TEXTBELT-API-KEY\ndone"
},
"typeVersion": 1
},
{
"id": "6810bfca-47d1-4998-b996-0f4f5446331d",
"name": "Collect Checking URL list",
"type": "n8n-nodes-base.executeCommand",
"position": [
-1264,
784
],
"parameters": {
"command": "=# Install required tools silently (for Debian/Ubuntu or Alpine)\nif command -v apt >/dev/null 2>&1; then\n apt update -y >/dev/null 2>&1\n apt install libxml2-utils curl jq -y >/dev/null 2>&1\nelif command -v apk >/dev/null 2>&1; then\n apk add libxml2-utils curl jq >/dev/null 2>&1\nfi\n\n# Download the sample TSL XML, quiet mode\nURL=\"http://www.nmhh.hu/tl/pub/HU_TL.xml\"\ncurl -s \"$URL\" -o /tmp/hu_tsl.xml\n\n# Extract all X509Certificate tags to one file, suppressing output\nxmllint --xpath '//*[local-name()=\"X509Certificate\"]/text()' /tmp/hu_tsl.xml 2>/dev/null | tr -d '\\r' > /tmp/cert_base64_all.txt\n\n# Split each base64 certificate chunk into a separate file, suppressing output\nawk -v RS='\\n\\n\\n' '{if(length($0)>50){i++; print $0 > (\"/tmp/cert_base64_\" i \".txt\")}}' /tmp/cert_base64_all.txt\n\n# Process each base64 file: create PEM files and save extracted URLs, suppressing output\nfor f in /tmp/cert_base64_*.txt; do\n pemfile=$(echo \"$f\" | sed 's/\\.txt$/.pem/')\n urlsfile=$(echo \"$f\" | sed 's/\\.txt$/_urls.txt/')\n echo \"-----BEGIN CERTIFICATE-----\" > \"$pemfile\"\n fold -w 64 \"$f\" >> \"$pemfile\"\n echo \"-----END CERTIFICATE-----\" >> \"$pemfile\"\n if openssl x509 -in \"$pemfile\" -noout 2>/dev/null; then\n openssl x509 -in \"$pemfile\" -noout -text | grep -E \"(CRL|URI:|CA Issuers)\" | head -10 > \"$urlsfile\"\n else\n rm -f \"$pemfile\"\n rm -f \"$urlsfile\"\n fi\ndone\n\n# Collect all URLs into one JSON file\necho \"{\" > /tmp/all_urls.json\necho ' \"urls\": {' >> /tmp/all_urls.json\ncounter=1\nfor f in /tmp/cert_base64_*.txt; do\n urlsfile=$(echo \"$f\" | sed 's/\\.txt$/_urls.txt/')\n while IFS= read -r line; do\n url=$(echo \"$line\" | grep -Eo 'http[s]?://[^ ]+')\n if [ -n \"$url\" ]; then\n echo \" \\\"URL $counter\\\": \\\"$url\\\",\" >> /tmp/all_urls.json\n counter=$((counter + 1))\n fi\n done < \"$urlsfile\"\ndone\nsed -i '$ s/,$//' /tmp/all_urls.json\necho \" }\" >> /tmp/all_urls.json\necho \"}\" >> /tmp/all_urls.json\n\n# Final output: only print JSON content\njq -c . /tmp/all_urls.json\n"
},
"typeVersion": 1
},
{
"id": "3d124c2e-ae21-45f4-b879-318c677b07ae",
"name": "Get Checking URL list to URL objects",
"type": "n8n-nodes-base.set",
"position": [
-1024,
784
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "8202a77a-25b2-4d31-b063-7bea3beae8ba",
"name": "",
"type": "object",
"value": "={{ $json.stdout }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "88035c47-2ac4-4132-bd3e-689f6911fc33",
"name": "CRL Available?",
"type": "n8n-nodes-base.if",
"onError": "continueRegularOutput",
"position": [
272,
224
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.statusCode }}",
"value2": 200,
"operation": "equal"
}
]
}
},
"retryOnFail": true,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "8f5be08c-4a9a-4208-88c9-9d5532137de1",
"name": "CA Available?",
"type": "n8n-nodes-base.if",
"onError": "continueRegularOutput",
"position": [
272,
880
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.statusCode }}",
"value2": 200,
"operation": "equal"
}
]
}
},
"retryOnFail": true,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "37eb326c-28f7-4f88-85e4-cbdb221d6239",
"name": "CA Alert --- Telegam & SMS",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
1392,
1088
],
"parameters": {
"command": "=apk add curl\n\nexport TOKEN=\"YOUR-TELEGRAM-BOT-TOKEN\"\nexport CHAT_ID=\"YOUR-TELEGRAM-CHANNEL-ID\"\nexport MESSAGE=\"{{ $json.caStatus }} with {{ $json.subjectCN }} !!!CA EXPIRATION PROBLEM!!! The expiration time: ({{ $json.notAfter }}) Last updated: ({{ $json.notBefore }})\"\n\ncurl -s -X POST \"https://api.telegram.org/bot$TOKEN/sendMessage\" -d chat_id=\"$CHAT_ID\" -d text=\"$MESSAGE\"\n\nNUMBERS=\"+36301234567\"\n\nfor PHONE in $NUMBERS; do\n curl -X POST https://textbelt.com/text --data-urlencode phone=\"$PHONE\" --data-urlencode message=\"$MESSAGE\" -d key=YOUR-TEXTBELT-API-KEY\ndone"
},
"typeVersion": 1
},
{
"id": "f5b5b6a4-9426-436a-96e0-338c6e3b680e",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1792,
320
],
"parameters": {
"width": 380,
"height": 252,
"content": "## PKI Certificate & CRL Monitor\n\nAutomated monitoring of Public Key Infrastructure components including CA certificates, Certificate Revocation Lists, and web services.\n\nExtracts certificate URLs from TSL XML, monitors expiration dates, and sends alerts via Telegram and SMS.\n\nRuns every 12 hours with 17-hour warning threshold."
},
"typeVersion": 1
},
{
"id": "f5843fd5-8822-437f-9be1-8cb9f18598aa",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1472,
960
],
"parameters": {
"width": 340,
"height": 276,
"content": "## TSL SOURCE CONFIGURATION\n\nDefault: Hungarian TSL from NMHH\nURL: http://www.nmhh.hu/tl/pub/HU_TL.xml\n\nTo change TSL source, edit the Collect Checking URL list node and modify the URL variable.\n\nInstalls required tools: libxml2-utils, curl, jq, OpenSSL"
},
"typeVersion": 1
},
{
"id": "e0c85228-143a-4aac-b0f0-8165d603a7e4",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1264,
480
],
"parameters": {
"width": 340,
"height": 276,
"content": "## URL Extraction Process\n\nDownloads TSL XML and extracts all X509Certificate tags.\n\nConverts base64 certificates to PEM format.\n\nParses with OpenSSL to extract CRL and CA Issuer URLs.\n\nOutputs JSON object with all discovered URLs for monitoring."
},
"typeVersion": 1
},
{
"id": "369236f0-0f08-4d85-94da-901153bb936b",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-928,
960
],
"parameters": {
"width": 300,
"height": 240,
"content": "## URL Processing Loop\n\nSplits URL list and processes each item sequentially in batches of 1.\n\nLoop continues until all URLs are checked.\n\nEach URL is classified as CRL, CA certificate, or other service."
},
"typeVersion": 1
},
{
"id": "61cb1e90-52bd-4ef8-b175-99804020e687",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 464,
"height": 200,
"content": "## CRL Monitoring Pipeline\n\n- Detects URLs containing crl= or .crl extension.\n- Downloads CRL file, parses with OpenSSL.\n- Extracts Last Update and Next Update times.\n- Alerts if Next Update is within 17 hours.\n- Skips unavailable CRLs and continues loop."
},
"typeVersion": 1
},
{
"id": "20b30a30-6b17-4383-a009-3ca1e9adbe24",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
672
],
"parameters": {
"width": 416,
"height": 200,
"content": "## CA Certificate Monitoring Pipeline\n\n- Detects URLs with ca=, .crt, or .cer extension.\n- Downloads certificate, parses with OpenSSL.\nExtracts Not Before and Not After dates.\n- Alerts if expiring within 17 hours or already expired.\n- Skips unavailable certificates and continues loop."
},
"typeVersion": 1
},
{
"id": "645d84ee-4e51-4708-aeb6-865d7acfc75f",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
48,
1328
],
"parameters": {
"width": 416,
"height": 176,
"content": "## Website Availability Monitoring\n\n- Checks non-CRL/CA URLs for HTTP 200 status.\n- Implements retry mechanism with wait period.\n- Sends alert if both initial and retry attempts fail.\n- Useful for detecting service outages."
},
"typeVersion": 1
},
{
"id": "90922bf9-4810-4191-bb9a-57ad10ee333e",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
1376,
96
],
"parameters": {
"width": 340,
"height": 300,
"content": "## ALERT CONFIGURATION\n\nThree alert nodes require configuration:\n1. CRL Alert - Telegram & SMS\n2. CA Alert - Telegram & SMS\n3. Website Down Alert - Telegram & SMS\n\nReplace placeholders:\n- YOUR-TELEGRAM-BOT-TOKEN\n- YOUR-TELEGRAM-CHANNEL-ID\n- +36301234567 (phone numbers)\n- YOUR-TEXTBELT-API-KEY"
},
"typeVersion": 1
},
{
"id": "f3749f4b-4afd-4d8b-b36e-3cc5f60a3d1b",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
640,
640
],
"parameters": {
"width": 332,
"height": 224,
"content": "## Threshold Configuration\n\nDefault warning: 17 hours before expiration\n\nTo modify:\n- CRL: Edit nextUpdate - TimeFilter node\n- CA: Edit nextUpdate - TimeFilter1 node\n\nChange condition: if (diffHours < 17)"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "4f3b1f4f-11dd-4366-a105-0b9c8efbfa2d",
"connections": {
"Alive?": {
"main": [
[
{
"node": "Set-Info for CA Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
},
"Get CA URL": {
"main": [
[
{
"node": "CA Available?",
"type": "main",
"index": 0
}
]
]
},
"Get CRL URL": {
"main": [
[
{
"node": "CRL Available?",
"type": "main",
"index": 0
}
]
]
},
"Is this CA?": {
"main": [
[
{
"node": "Get CA URL",
"type": "main",
"index": 0
}
],
[
{
"node": "Get Non-CRL/CA URL",
"type": "main",
"index": 0
}
]
]
},
"Good Or Evil": {
"main": [
[
{
"node": "Set-Info for CRL Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
},
"CA Available?": {
"main": [
[
{
"node": "Write Binary - TempFile : cacertfile.crt",
"type": "main",
"index": 0
}
],
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
},
"Is this CRL ?": {
"main": [
[
{
"node": "Get CRL URL",
"type": "main",
"index": 0
}
],
[
{
"node": "Is this CA?",
"type": "main",
"index": 0
}
]
]
},
"Wait B4 Retry": {
"main": [
[
{
"node": "Retry to Non-CRL/CA URL",
"type": "main",
"index": 0
}
]
]
},
"CRL Available?": {
"main": [
[
{
"node": "Write Binary - TempFile : crlfile.der",
"type": "main",
"index": 0
}
],
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
},
"Get Url From List": {
"main": [
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
},
"Get Non-CRL/CA URL": {
"main": [
[
{
"node": "Respose Extend With Requested URL",
"type": "main",
"index": 0
}
]
]
},
"Website Available?": {
"main": [
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait B4 Retry",
"type": "main",
"index": 0
}
]
]
},
"Set-Info for CA Alert": {
"main": [
[
{
"node": "CA Alert --- Telegam & SMS",
"type": "main",
"index": 0
}
]
]
},
"Set-Info for CRL Alert": {
"main": [
[
{
"node": "CRL Alert --- Telegam & SMS",
"type": "main",
"index": 0
}
]
]
},
"Website Available Now?": {
"main": [
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Website Down - Telegram & SMS",
"type": "main",
"index": 0
}
]
]
},
"Retry to Non-CRL/CA URL": {
"main": [
[
{
"node": "Website Available Now?",
"type": "main",
"index": 0
}
]
]
},
"nextUpdate - TimeFilter": {
"main": [
[
{
"node": "Good Or Evil",
"type": "main",
"index": 0
}
]
]
},
"B64 Encode : crlfile.der": {
"main": [
[
{
"node": "OpenSSL Parse CRL : crlfile.der",
"type": "main",
"index": 0
}
]
]
},
"nextUpdate - TimeFilter1": {
"main": [
[
{
"node": "Alive?",
"type": "main",
"index": 0
}
]
]
},
"Collect Checking URL list": {
"main": [
[
{
"node": "Get Checking URL list to URL objects",
"type": "main",
"index": 0
}
]
]
},
"Execute With Manual Start": {
"main": [
[
{
"node": "Collect Checking URL list",
"type": "main",
"index": 0
}
]
]
},
"Parse Data OpenSSL output": {
"main": [
[
{
"node": "nextUpdate - TimeFilter",
"type": "main",
"index": 0
}
]
]
},
"CA Alert --- Telegam & SMS": {
"main": [
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
},
"B64 Encode : cacertfile.crt": {
"main": [
[
{
"node": "OpenSSL Parse CA Cert : cacertfile.crt",
"type": "main",
"index": 0
}
]
]
},
"CRL Alert --- Telegam & SMS": {
"main": [
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
},
"Execute With Scheduled Start": {
"main": [
[
{
"node": "Collect Checking URL list",
"type": "main",
"index": 0
}
]
]
},
"Parse Data OpenSSL CA output": {
"main": [
[
{
"node": "nextUpdate - TimeFilter1",
"type": "main",
"index": 0
}
]
]
},
"OpenSSL Parse CRL : crlfile.der": {
"main": [
[
{
"node": "Parse Data OpenSSL output",
"type": "main",
"index": 0
}
]
]
},
"Respose Extend With Requested URL": {
"main": [
[
{
"node": "Website Available?",
"type": "main",
"index": 0
}
]
]
},
"Send Website Down - Telegram & SMS": {
"main": [
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items -- Process Checking": {
"main": [
[],
[
{
"node": "Is this CRL ?",
"type": "main",
"index": 0
}
]
]
},
"Get Checking URL list to URL objects": {
"main": [
[
{
"node": "Get Url From List",
"type": "main",
"index": 0
}
]
]
},
"Write Binary - TempFile : crlfile.der": {
"main": [
[
{
"node": "B64 Encode : crlfile.der",
"type": "main",
"index": 0
}
],
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
},
"OpenSSL Parse CA Cert : cacertfile.crt": {
"main": [
[
{
"node": "Parse Data OpenSSL CA output",
"type": "main",
"index": 0
}
]
]
},
"Write Binary - TempFile : cacertfile.crt": {
"main": [
[
{
"node": "B64 Encode : cacertfile.crt",
"type": "main",
"index": 0
}
],
[
{
"node": "Loop Over Items -- Process Checking",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n workflow provides automated monitoring of Public Key Infrastructure (PKI) components including CA certificates, Certificate Revocation Lists (CRLs), and associated web services. It extracts certificate information from the TSL (Trusted Service List) -- the Hungarian is…
Source: https://n8n.io/workflows/9865/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Track all n8n workflow failures with automatic error capture, severity classification, duplicate detection, Slack alerting, performance metrics, and log retention.
Extend N8N With Additional Tools. Uses telegram, telegramTrigger, httpRequest, spreadsheetFile. Event-driven trigger; 21 nodes.
This workflow extends n8n and uses R language graphic capabilities. This is a Telegram bot which fetches weather data via the openweathermap.org API, plots an image using ggoplot2 package from R and s
This n8n workflow automates the process of scraping Google Play Store reviews, analyzing app performance, and sending alerts for low-rated applications. It integrates with Bright Data for web scraping
Stay ahead of payment disputes with this automated n8n workflow that integrates Stripe, Slack, and ClickUp. Perfect for finance teams, payment ops specialists, and SaaS businesses, this template fetch