تخطي إلى المحتوى
Integration

مراقبة انتهاء صلاحية شهادة SSL باستخدام REST API

| 6 min read

تحقق من تواريخ انتهاء صلاحية شهادة SSL ومصدريها ورؤوس الأمان لأي مجال به نقطتي نهاية لواجهة برمجة التطبيقات. يتضمن أمثلة تنبيهات GitHub وNode.js وSlack.

Green padlock icon on a browser address bar
Photo by Towfiqu barbhuiya on Unsplash

شهادة SSL منتهية الصلاحية تجعل موقعك غير متصل بالإنترنت وتعرض تحذيرًا مخيفًا للمتصفح العملاء بعيدا. دعونا نقوم بتشفير الشهادات التي يتم تجديدها تلقائيًا، ولكن تم تكوين DNS بشكل خاطئ، وفشلت مهام cron، ولا تزال الشهادات اليدوية المنسية تسبب انقطاع الخدمة. أنت بحاجة إلى وسيلة لمراقبة انتهاء الصلاحية التواريخ عبر جميع المجالات الخاصة بك.

توفر واجهة برمجة تطبيقات botoi نقطتي نهاية لهذا الغرض. يقوم أحد الأشخاص بإرجاع تفاصيل الشهادة (المصدر، تواريخ الصلاحية، الأيام حتى انتهاء الصلاحية). والآخر يتحقق من دعم HTTPS ويفحص الأمان رؤوس. وهي تغطي معًا كلاً من مراقبة انتهاء الصلاحية وتدقيق الوضع الأمني.

احصل على تفاصيل الشهادة باستخدام /v1/ssl-cert/certificate

تتصل نقطة النهاية هذه بالمجال، وتقرأ شهادة TLS، وترجع منظمة البيانات التي يمكنك تحليلها بأي لغة.

curl -X POST https://api.botoi.com/v1/ssl-cert/certificate \\
  -H "Content-Type: application/json" \\
  -d '{"domain": "stripe.com"}'

إجابة:

{
  "success": true,
  "data": {
    "domain": "stripe.com",
    "subject": "CN=stripe.com",
    "issuer": "C=US, O=Let's Encrypt, CN=E6",
    "valid_from": "2026-02-18T00:00:00.000Z",
    "valid_to": "2026-05-19T00:00:00.000Z",
    "days_until_expiry": 51,
    "serial": "04:A3:9B:7C:2D:1E:8F:00:5A:B2:C4:D6:E8:F0:12:34",
    "fingerprint": "A1:B2:C3:D4:E5:F6:78:90:AB:CD:EF:01:23:45:67:89",
    "san": ["stripe.com", "*.stripe.com"]
  }
}

ال days_until_expiry الحقل هو الذي ستنشئ تنبيهات حوله. ال san تعرض المصفوفة جميع المجالات التي تغطيها الشهادة، وهي مفيدة للتحقق تتضمن شهادات أحرف البدل النطاقات الفرعية التي تتوقعها.

تحقق من دعم HTTPS ورؤوس الأمان باستخدام /v1/ssl

إن معرفة أن شهادتك صالحة ليست كافية. أنت أيضًا تريد تأكيد هذا الأمان الرؤوس مثل HSTS وCSP موجودة. ال /v1/ssl نقطة النهاية تتعامل مع ذلك.

curl -X POST https://api.botoi.com/v1/ssl \\
  -H "Content-Type: application/json" \\
  -d '{"domain": "stripe.com"}'

إجابة:

{
  "success": true,
  "data": {
    "domain": "stripe.com",
    "ssl_supported": true,
    "protocol": "TLSv1.3",
    "headers": {
      "strict-transport-security": "max-age=63072000; includeSubDomains; preload",
      "content-security-policy": "default-src 'self'; script-src 'self' js.stripe.com",
      "x-frame-options": "SAMEORIGIN",
      "x-content-type-options": "nosniff",
      "referrer-policy": "strict-origin-when-cross-origin"
    }
  }
}

ال ssl_supported يؤكد المنطق المنطقي على عمل HTTPS. ال headers أسطح الكائنات HSTS وCSP وX-Frame-Options وX-Content-Type-Options وReferrer-Policy. تشير الرؤوس المفقودة إلى وجود ثغرات في تكوين الأمان لديك. بروتوكول TLS أقل من 1.2 هو العلم الأحمر.

إجراءات GitHub: فحص SSL أسبوعيًا للمشكلات التي تم إنشاؤها تلقائيًا

يتم تشغيل سير العمل هذا كل يوم اثنين، ويتحقق من قائمة النطاقات، ويفتح مشكلة GitHub إذا تنتهي صلاحية أي شهادة خلال 30 يومًا. يخلق .github/workflows/ssl-check.yml:

name: SSL Expiry Check

on:
  schedule:
    # Every Monday at 9:00 UTC
    - cron: '0 9 * * 1'
  workflow_dispatch:

jobs:
  check-ssl:
    runs-on: ubuntu-latest
    steps:
      - name: Check SSL certificates
        run: |
          DOMAINS=("stripe.com" "api.stripe.com" "dashboard.stripe.com")
          THRESHOLD=30
          FAILURES=""

          for DOMAIN in "\\\${DOMAINS[@]}"; do
            RESPONSE=\$(curl -s -X POST https://api.botoi.com/v1/ssl-cert/certificate \\
              -H "Content-Type: application/json" \\
              -d "{\\"domain\\": \\"\$DOMAIN\\"}")

            DAYS=\$(echo "\$RESPONSE" | jq -r '.data.days_until_expiry')
            ISSUER=\$(echo "\$RESPONSE" | jq -r '.data.issuer')
            EXPIRY=\$(echo "\$RESPONSE" | jq -r '.data.valid_to')

            echo "## \$DOMAIN" >> \$GITHUB_STEP_SUMMARY
            echo "- Expires: \$EXPIRY" >> \$GITHUB_STEP_SUMMARY
            echo "- Days left: \$DAYS" >> \$GITHUB_STEP_SUMMARY
            echo "- Issuer: \$ISSUER" >> \$GITHUB_STEP_SUMMARY
            echo "" >> \$GITHUB_STEP_SUMMARY

            if [ "\$DAYS" -lt "\$THRESHOLD" ]; then
              FAILURES="\$FAILURES\\n- \$DOMAIN expires in \$DAYS days (\$EXPIRY)"
            fi
          done

          if [ -n "\$FAILURES" ]; then
            echo "::error::Certificates expiring within \$THRESHOLD days:\$FAILURES"
            exit 1
          fi

          echo "All certificates have more than \$THRESHOLD days remaining."

      - name: Open GitHub issue on failure
        if: failure()
        uses: actions/github-script@v7
        with:
          script: |
            await github.rest.issues.create({
              owner: context.repo.owner,
              repo: context.repo.repo,
              title: 'SSL certificate expiring soon',
              body: 'The weekly SSL check found certificates expiring within 30 days. See the [workflow run](' + context.serverUrl + '/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId + ') for details.',
              labels: ['infrastructure', 'urgent']
            });

يتكرر سير العمل عبر كل مجال، ويستعلم عن واجهة برمجة التطبيقات (API)، ويتراكم حالات الفشل. إذا أي شهادة تقل عن حد الـ 30 يومًا، فإنها تفشل في المهمة وتنشئ GitHub القضية الموسومة infrastructure و urgent. يظهر ملخص الوظيفة التقرير الكامل لكل مجال.

يُعدِّل DOMAINS و THRESHOLD لتتناسب مع الإعداد الخاص بك. الحرة يتعامل المستوى مع ما يصل إلى 100 طلب يوميًا، وهو ما يغطي حوالي 14 نطاقًا يتم فحصها أسبوعيًا.

Node.js: مراقبة مجالات متعددة في البرنامج النصي

للتكامل في مكدس المراقبة الخاص بك، إليك البرنامج النصي Node.js الذي يتحقق مجموعة من المجالات المتوازية وشهادات على وشك الانتهاء:

const DOMAINS = [
  "stripe.com",
  "api.stripe.com",
  "dashboard.stripe.com",
  "docs.stripe.com",
];

const THRESHOLD_DAYS = 30;

async function checkCert(domain) {
  const res = await fetch("https://api.botoi.com/v1/ssl-cert/certificate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-Api-Key": process.env.BOTOI_API_KEY,
    },
    body: JSON.stringify({ domain }),
  });
  const { data } = await res.json();
  return { domain, ...data };
}

async function checkAll() {
  const results = await Promise.all(DOMAINS.map(checkCert));
  const expiring = results.filter(
    (r) => r.days_until_expiry < THRESHOLD_DAYS
  );

  console.log("SSL Certificate Report");
  console.log("=".repeat(50));

  for (const r of results) {
    const status =
      r.days_until_expiry < THRESHOLD_DAYS ? "WARNING" : "OK";
    console.log(
      \`[\\\${status}] \\\${r.domain} - \\\${r.days_until_expiry} days left (expires \\\${r.valid_to})\`
    );
  }

  if (expiring.length > 0) {
    console.log(
      \`\\n\\\${expiring.length} certificate(s) expiring within \\\${THRESHOLD_DAYS} days.\`
    );
  }

  return { results, expiring };
}

checkAll();

قم بتشغيل هذا وفقًا لجدول كرون أو قم بدمجه في خط أنابيب الفحص الصحي الموجود لديك. ال Promise.all call يتحقق من جميع المجالات بشكل متزامن، وبالتالي فإن المجموع يظل وقت التنفيذ قريبًا من زمن الوصول لاستدعاء واجهة برمجة التطبيقات (API) واحد.

تنبيه Slack webhook عند انتهاء صلاحية الشهادة قريبًا

قم بإقران التحقق من الشهادة مع خطاف الويب الوارد من Slack لإعلام فريقك عندما الشهادة تحتاج إلى اهتمام:

async function sendSlackAlert(domain, daysLeft, validTo) {
  const webhookUrl = process.env.SLACK_WEBHOOK_URL;

  await fetch(webhookUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      text: \`:rotating_light: SSL certificate for \\\${domain} expires in \\\${daysLeft} days\`,
      blocks: [
        {
          type: "section",
          text: {
            type: "mrkdwn",
            text: [
              "*SSL Certificate Expiry Warning*",
              \`Domain: \\\`\\\${domain}\\\`\`,
              \`Days remaining: *\\\${daysLeft}*\`,
              \`Expires: \\\${validTo}\`,
            ].join("\\n"),
          },
        },
      ],
    }),
  });
}

// After running the certificate check
async function checkAndAlert() {
  const DOMAINS = ["stripe.com", "api.stripe.com"];

  for (const domain of DOMAINS) {
    const res = await fetch(
      "https://api.botoi.com/v1/ssl-cert/certificate",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-Api-Key": process.env.BOTOI_API_KEY,
        },
        body: JSON.stringify({ domain }),
      }
    );
    const { data } = await res.json();

    if (data.days_until_expiry < 30) {
      await sendSlackAlert(domain, data.days_until_expiry, data.valid_to);
    }
  }
}

checkAndAlert();

تتضمن الرسالة النطاق والأيام المتبقية وتاريخ انتهاء الصلاحية. يرى فريقك تنبيه في Slack ويمكنه التحقق قبل انتهاء صلاحية الشهادة.

التدقيق الأمني ​​الكامل: الجمع بين نقطتي النهاية

للحصول على صورة كاملة، قم بتشغيل نقطتي النهاية بالتوازي لكل مجال. هذا يعطيك بيانات انتهاء صلاحية الشهادة وتغطية رأس الأمان في مسار واحد:

async function auditSsl(domain) {
  const [cert, ssl] = await Promise.all([
    fetch("https://api.botoi.com/v1/ssl-cert/certificate", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Api-Key": process.env.BOTOI_API_KEY,
      },
      body: JSON.stringify({ domain }),
    }).then((r) => r.json()),

    fetch("https://api.botoi.com/v1/ssl", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Api-Key": process.env.BOTOI_API_KEY,
      },
      body: JSON.stringify({ domain }),
    }).then((r) => r.json()),
  ]);

  const issues = [];

  // Certificate checks
  if (cert.data.days_until_expiry < 30) {
    issues.push(\`Certificate expires in \\\${cert.data.days_until_expiry} days\`);
  }

  // Security header checks
  const headers = ssl.data.headers || {};
  if (!headers["strict-transport-security"]) {
    issues.push("Missing HSTS header");
  }
  if (!headers["content-security-policy"]) {
    issues.push("Missing Content-Security-Policy header");
  }
  if (!headers["x-frame-options"]) {
    issues.push("Missing X-Frame-Options header");
  }

  return { domain, cert: cert.data, ssl: ssl.data, issues };
}

// Run audit across all domains
const domains = ["stripe.com", "api.stripe.com"];
Promise.all(domains.map(auditSsl)).then((results) => {
  for (const r of results) {
    console.log(\`\\n\\\${r.domain}:\`);
    console.log(\`  Certificate: \\\${r.cert.days_until_expiry} days left\`);
    console.log(\`  TLS: \\\${r.ssl.protocol}\`);
    console.log(\`  Issues: \\\${r.issues.length === 0 ? "None" : r.issues.join(", ")}\`);
  }
});

يُبلغ هذا البرنامج النصي عن انتهاء صلاحية الشهادة وإصدار بروتوكول TLS والأمان المفقود رؤوس لكل مجال. قم بإضافته إلى المراجعة الأمنية الأسبوعية الخاصة بك أو قم بتوصيله إلى حسابك لوحة الاستجابة للحوادث.

النقاط الرئيسية

  • /v1/ssl-cert/certificate إرجاع المصدر وتواريخ الصلاحية، days_until_expiryوالرقم التسلسلي وبصمة الإصبع وقائمة SAN لأي جهاز شهادة TLS الخاصة بالمجال.
  • /v1/ssl التحقق من دعم HTTPS، والإبلاغ عن إصدار بروتوكول TLS، و عمليات المسح لـ HSTS وCSP وX-Frame-Options وX-Content-Type-Options وReferrer-Policy رؤوس.
  • تعمل كلا نقطتي النهاية بشكل مجهول بمعدل 5 طلبات في الدقيقة. تمرير ان X-Api-Key رأس للحدود الأعلى.
  • تكتشف مهمة GitHub Actions cron الأسبوعية بحد أقصى 30 يومًا فشل التجديد قبل أن تصبح انقطاعات.
  • اجمع بين نقطتي النهاية لتشغيل مراقبة انتهاء صلاحية الشهادة ورأس الأمان عمليات التدقيق في برنامج نصي واحد.

FAQ

كيف أتحقق من انتهاء صلاحية شهادة SSL عبر واجهة برمجة التطبيقات؟
أرسل طلب POST إلى https://api.botoi.com/v1/ssl-cert/certificate باستخدام نص JSON يحتوي على المجال. تتضمن الاستجابة حقول الشهادة valid_from وvalid_to وdays_until_expiry. لا حاجة لـ opensl CLI أو فحص المتصفح اليدوي.
ما الفرق بين /v1/ssl-cert/certificate و/v1/ssl؟
تقوم نقطة النهاية /v1/ssl-cert/certificate بإرجاع تفاصيل الشهادة: المُصدر والموضوع والرقم التسلسلي وتواريخ الصلاحية والأيام حتى انتهاء الصلاحية. تتحقق نقطة النهاية /v1/ssl مما إذا كان HTTPS مدعومًا وتفحص رؤوس الأمان مثل HSTS وCSP وX-Frame-Options وReferrer-Policy. استخدم الأول لمراقبة انتهاء الصلاحية والثاني لعمليات التدقيق الأمني.
هل يمكنني التحقق من شهادات SSL بدون مفتاح API؟
نعم. يسمح الوصول المجهول بـ 5 طلبات في الدقيقة و100 طلب في اليوم مع تحديد المعدل على أساس IP. لا يلزم الاشتراك أو مفتاح API. للحصول على إنتاجية أعلى، تبدأ الخطط المدفوعة بسعر 9 دولارات شهريًا.
كم مرة يجب أن أتحقق من انتهاء صلاحية شهادة SSL؟
الأسبوعية هي خط أساس جيد لمعظم الفرق. دعونا نقوم بتشفير الشهادات كل 90 يومًا مع التجديد التلقائي قبل 30 يومًا من انتهاء الصلاحية. يمنحك الفحص الأسبوعي مع حد تحذير مدته 30 يومًا وقتًا كافيًا لإصلاح فشل التجديد قبل انتهاء صلاحية الشهادة.
هل يعمل هذا مع الشهادات الموقعة ذاتيًا أو الداخلية؟
تتصل واجهة برمجة التطبيقات (API) بالمجال عبر الإنترنت العام، لذا فهي تعمل مع أي شهادة يتم تقديمها على المنفذ 443. ستعيد الشهادات الموقعة ذاتيًا تفاصيل الشهادة، لكن حقل المُصدر سيُظهر الكيان الموقع ذاتيًا بدلاً من مرجع مصدق موثوق به.

ابدأ البناء مع botoi

أكثر من 150 نقطة نهاية API للبحث ومعالجة النصوص وتوليد الصور وأدوات المطورين. باقة مجانية، بدون بطاقة ائتمان.