8
n8n 中文网amn8n.com

PKI证书与CRL监控器 - 自动过期警报系统

高级

这是一个自动化工作流,包含 44 个节点。主要使用 If, Set, Code, Wait, SplitOut 等节点。 监控PKI证书和CRL过期情况并发送Telegram和SMS警报

前置要求
  • 可能需要目标 API 的认证凭证

分类

-
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 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)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量44
分类-
节点类型12
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

外部链接
在 n8n.io 查看

分享此工作流