PKI证书与CRL监控器 - 自动过期警报系统
高级
这是一个自动化工作流,包含 44 个节点。主要使用 If, Set, Code, Wait, SplitOut 等节点。 监控PKI证书和CRL过期情况并发送Telegram和SMS警报
前置要求
- •可能需要目标 API 的认证凭证
使用的节点 (44)
分类
-
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "Gd16MTYoXemtNKQV",
"meta": {
"instanceId": "5c7ce220523e8664f49208a8be668a8dc6fab5f747ce4de865fa1309727919f1"
},
"name": "PKI 证书与 CRL 监控器 - 自动过期警报系统",
"tags": [],
"nodes": [
{
"id": "f534d56c-96c0-43c9-b050-71f118c2d83e",
"name": "写入二进制 - 临时文件 : 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": "Base64 编码 : 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 解析 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": "解析 OpenSSL 输出数据",
"type": "n8n-nodes-base.code",
"onError": "continueRegularOutput",
"position": [
544,
448
],
"parameters": {
"jsCode": "// A parancs eredménye a bemenet json stdout mezőjében\nconst output = items[0].json.stdout;\n\n// Regex a Last Update kinyeréséhez\nconst lastUpdateMatch = output.match(/Last Update:\\s*(.+)/);\nconst lastUpdate = lastUpdateMatch ? lastUpdateMatch[1].trim() : null;\n\n// Regex a Next Update kinyeréséhez\nconst nextUpdateMatch = output.match(/Next Update:\\s*(.+)/);\nconst nextUpdate = nextUpdateMatch ? nextUpdateMatch[1].trim() : null;\n\n// Regex a CN kinyeréséhez az Issuer szövegből\nconst issuerMatch = output.match(/Issuer:(.+)/);\nlet cn = null;\nif (issuerMatch) {\n // issuer szöveg, például: \" C=HU, L=Budapest, O=NetLock Kft., CN=NetLock Közigazgatási (Class B) Tanúsítványkiadó, emailAddress=info@netlock.hu\"\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": "获取 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": "下次更新时间 - 时间过滤器",
"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ől Date objektum készítése\nconst nextUpdateDate = new Date(nextUpdate + ' UTC'); // Hozzáadva az UTC időzóna\n\nconst now = new Date();\n\n// Különbség milliszekundumban\nconst diffMs = nextUpdateDate.getTime() - now.getTime();\n\n// Különbség órákban\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": "善与恶",
"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": "这是 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": "手动启动执行",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-1504,
784
],
"parameters": {},
"typeVersion": 1
},
{
"id": "670d00ba-a16f-403e-b1d4-eb3c794d97d5",
"name": "定时启动执行",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1504,
592
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 12
}
]
}
},
"typeVersion": 1
},
{
"id": "281ba72f-bb26-4357-90a9-8d763b1da10e",
"name": "从列表中获取 URL",
"type": "n8n-nodes-base.splitOut",
"position": [
-800,
784
],
"parameters": {
"options": {
"destinationFieldName": "urls"
},
"fieldToSplitOut": "[''].urls"
},
"typeVersion": 1
},
{
"id": "fa23324d-488d-4283-a3a1-62ff8460f3c2",
"name": "遍历项目 -- 处理检查",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-576,
784
],
"parameters": {
"options": {},
"batchSize": "=1"
},
"typeVersion": 3
},
{
"id": "19aae3c1-7d59-4ec7-ae8e-acf61e36558b",
"name": "网站可用?",
"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": "重试前等待",
"type": "n8n-nodes-base.wait",
"position": [
720,
1584
],
"webhookId": "b60239c1-eb64-4ea8-8af9-f37a7a13759a",
"parameters": {},
"retryOnFail": false,
"typeVersion": 1.1
},
{
"id": "b7d85fc7-9e97-4131-b41d-d818194874a3",
"name": "网站现在可用?",
"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": "发送网站宕机通知 - Telegram 和短信",
"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áltatáskiesés valószínűsíthető! Beavatkozást igényel!\"\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": "响应扩展包含请求的 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": "这是 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": "获取非 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": "重试非 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": "下次更新时间 - 时间过滤器1",
"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": "获取 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": "写入二进制 - 临时文件 : 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": "Base64 编码 : 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 解析 CA 证书 : 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": "解析 OpenSSL CA 输出数据",
"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": "存活?",
"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": "设置 CA 警报信息",
"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": "设置 CRL 警报信息",
"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 警报 --- Telegram 和短信",
"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": "收集检查 URL 列表",
"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": "将检查 URL 列表转换为 URL 对象",
"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 可用?",
"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 可用?",
"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 警报 --- Telegram 和短信",
"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": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1792,
320
],
"parameters": {
"width": 380,
"height": 252,
"content": "## PKI 证书与 CRL 监控器"
},
"typeVersion": 1
},
{
"id": "f5843fd5-8822-437f-9be1-8cb9f18598aa",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1472,
960
],
"parameters": {
"width": 340,
"height": 276,
"content": "## TSL 源配置"
},
"typeVersion": 1
},
{
"id": "e0c85228-143a-4aac-b0f0-8165d603a7e4",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1264,
480
],
"parameters": {
"width": 340,
"height": 276,
"content": "## URL 提取过程"
},
"typeVersion": 1
},
{
"id": "369236f0-0f08-4d85-94da-901153bb936b",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-928,
960
],
"parameters": {
"width": 300,
"height": 240,
"content": "## URL 处理循环"
},
"typeVersion": 1
},
{
"id": "61cb1e90-52bd-4ef8-b175-99804020e687",
"name": "便签4",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 464,
"height": 200,
"content": "## CRL 监控流程"
},
"typeVersion": 1
},
{
"id": "20b30a30-6b17-4383-a009-3ca1e9adbe24",
"name": "便签5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
672
],
"parameters": {
"width": 416,
"height": 200,
"content": "## CA 证书监控流程"
},
"typeVersion": 1
},
{
"id": "645d84ee-4e51-4708-aeb6-865d7acfc75f",
"name": "便签6",
"type": "n8n-nodes-base.stickyNote",
"position": [
48,
1328
],
"parameters": {
"width": 416,
"height": 176,
"content": "## 网站可用性监控"
},
"typeVersion": 1
},
{
"id": "90922bf9-4810-4191-bb9a-57ad10ee333e",
"name": "便签7",
"type": "n8n-nodes-base.stickyNote",
"position": [
1376,
96
],
"parameters": {
"width": 340,
"height": 300,
"content": "## 警报配置"
},
"typeVersion": 1
},
{
"id": "f3749f4b-4afd-4d8b-b36e-3cc5f60a3d1b",
"name": "便签8",
"type": "n8n-nodes-base.stickyNote",
"position": [
640,
640
],
"parameters": {
"width": 332,
"height": 224,
"content": "## 阈值配置"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"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
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
在可视化参考库中探索n8n节点
在可视化参考库中探索n8n节点
If
Ftp
Set
+93
113 节点I versus AI
其他
Telegram AI频道机器人 - 支持文本和图像响应的TGPT生成器
使用GPT-4和TGPT在Telegram频道中生成文本和图像响应
If
Set
Code
+8
22 节点Vigh Sandor
潜在客户开发与邮件工作流
使用Google Maps、SendGrid和AI自动化B2B潜在客户开发与邮件营销
If
Set
Code
+21
141 节点Ezema Kingsley Chibuzo
潜在客户开发
使用Google Maps生成潜在客户 - AlexK1919
使用Google Maps生成潜在客户
If
Set
Code
+13
42 节点Alex Kim
销售
(Duc)深度研究市场模板
集成PerplexityAI研究和OpenAI内容的多层级WordPress博客生成器
If
Set
Xml
+28
132 节点Daniel Ng
人工智能
WordPress博客自动化专业版(SEO主题)v2
WordPress自动博客专业版 - SEO主题内容自动化机器
If
Set
Xml
+21
63 节点Daniel Ng
人工智能