Langsung ke konten
Integration

Pantau masa berlaku sertifikat SSL dengan REST API

| 6 min read

Periksa tanggal kedaluwarsa sertifikat SSL, penerbit, dan header keamanan untuk domain apa pun dengan dua titik akhir API. Termasuk contoh peringatan GitHub Actions, Node.js, dan Slack.

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

Sertifikat SSL yang kedaluwarsa menjadikan situs Anda offline dan menampilkan peringatan browser yang menakutkan pelanggan pergi. Mari Enkripsi pembaruan otomatis sertifikat, tetapi DNS salah dikonfigurasi, tugas cron gagal, dan sertifikat manual yang terlupakan masih menyebabkan pemadaman. Anda memerlukan cara untuk memantau kedaluwarsa tanggal di seluruh domain Anda.

Botoi API menyediakan dua titik akhir untuk ini. Seseorang mengembalikan rincian sertifikat (penerbit, tanggal berlaku, hari sampai kadaluwarsa). Yang lainnya memeriksa dukungan HTTPS dan memindai keamanan header. Secara keseluruhan, keduanya mencakup pemantauan masa berlaku dan audit postur keamanan.

Dapatkan detail sertifikat dengan /v1/ssl-cert/certificate

Titik akhir ini terhubung ke domain, membaca sertifikat TLS, dan mengembalikan secara terstruktur data yang dapat Anda urai dalam bahasa apa pun.

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

Tanggapan:

{
  "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"]
  }
}

Itu days_until_expiry bidang adalah bidang tempat Anda akan membuat peringatan. Itu san array menunjukkan semua domain yang dicakup oleh sertifikat, berguna untuk verifikasi sertifikat wildcard tersebut menyertakan subdomain yang Anda harapkan.

Periksa dukungan HTTPS dan header keamanan dengan /v1/ssl

Mengetahui sertifikat Anda valid saja tidak cukup. Anda juga ingin mengonfirmasi keamanan itu header seperti HSTS dan CSP sudah ada. Itu /v1/ssl titik akhir menangani itu.

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

Tanggapan:

{
  "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"
    }
  }
}

Itu ssl_supported boolean mengonfirmasi HTTPS berfungsi. Itu headers permukaan objek HSTS, CSP, X-Frame-Options, X-Content-Type-Options, dan Referrer-Policy. Header yang hilang menunjukkan kesenjangan dalam konfigurasi keamanan Anda. Protokol TLS di bawah 1.2 adalah bendera merah.

Tindakan GitHub: pemeriksaan SSL mingguan dengan masalah yang dibuat secara otomatis

Alur kerja ini berjalan setiap hari Senin, memeriksa daftar domain, dan membuka masalah GitHub jika sertifikat apa pun akan kedaluwarsa dalam waktu 30 hari. Membuat .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']
            });

Alur kerja berputar melalui setiap domain, menanyakan API, dan mengumpulkan kegagalan. Jika sertifikat apa pun yang berada di bawah ambang batas 30 hari, maka akan gagal dan membuat GitHub masalah yang ditandai infrastructure Dan urgent. Ringkasan pekerjaan menunjukkan laporan lengkap untuk setiap domain.

Menyesuaikan DOMAINS Dan THRESHOLD untuk mencocokkan pengaturan Anda. Gratis tier menangani hingga 100 permintaan per hari, yang mencakup ~14 domain yang diperiksa setiap minggu.

Node.js: memantau beberapa domain dalam sebuah skrip

Untuk integrasi ke tumpukan pemantauan Anda sendiri, inilah skrip Node.js yang memeriksanya serangkaian domain secara paralel dan menandai sertifikat yang hampir habis masa berlakunya:

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();

Jalankan ini pada jadwal cron atau integrasikan ke dalam pipeline pemeriksaan kesehatan Anda yang sudah ada. Itu Promise.all panggilan memeriksa semua domain secara bersamaan, jadi totalnya waktu eksekusi tetap mendekati latensi satu panggilan API.

Peringatan webhook kendur ketika masa berlaku sertifikat akan segera habis

Pasangkan pemeriksaan sertifikat dengan webhook masuk Slack untuk memberi tahu tim Anda ketika a sertifikat perlu mendapat perhatian:

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();

Pesan tersebut mencakup domain, sisa hari, dan tanggal kedaluwarsa. Tim Anda melihat waspada di Slack dan dapat menyelidiki sebelum masa berlaku sertifikat habis.

Audit keamanan penuh: gabungkan kedua titik akhir

Untuk gambaran lengkap, jalankan kedua titik akhir secara paralel per domain. Ini memberi Anda data kedaluwarsa sertifikat dan cakupan header keamanan dalam satu pass:

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(", ")}\`);
  }
});

Skrip ini melaporkan masa berlaku sertifikat, versi protokol TLS, dan keamanan yang hilang header untuk setiap domain. Tambahkan ke tinjauan keamanan mingguan Anda atau kirimkan ke Anda dasbor respons insiden.

Poin-poin penting

  • /v1/ssl-cert/certificate mengembalikan penerbit, tanggal validitas, days_until_expiry, nomor seri, sidik jari, dan daftar SAN untuk apa pun sertifikat TLS domain.
  • /v1/ssl memeriksa dukungan HTTPS, melaporkan versi protokol TLS, dan memindai HSTS, CSP, X-Frame-Options, X-Content-Type-Options, dan Referrer-Policy header.
  • Kedua titik akhir bekerja secara anonim dengan 5 permintaan per menit. Lulus sebuah X-Api-Key header untuk batas yang lebih tinggi.
  • Pekerjaan cron GitHub Actions mingguan dengan ambang batas 30 hari mendeteksi kegagalan pembaruan sebelum terjadi pemadaman.
  • Gabungkan kedua titik akhir untuk menjalankan pemantauan kedaluwarsa sertifikat dan header keamanan audit dalam satu skrip.

FAQ

Bagaimana cara memeriksa masa berlaku sertifikat SSL melalui API?
Kirim permintaan POST ke https://api.botoi.com/v1/ssl-cert/certificate dengan isi JSON yang berisi domain. Responsnya mencakup bidang valid_from, valid_to, dan hari_until_expiry sertifikat. Tidak diperlukan CLI openssl atau pemeriksaan browser manual.
Apa perbedaan antara /v1/ssl-cert/certificate dan /v1/ssl?
Titik akhir /v1/ssl-cert/certificate mengembalikan detail sertifikat: penerbit, subjek, nomor seri, tanggal validitas, dan hari hingga kedaluwarsa. Titik akhir /v1/ssl memeriksa apakah HTTPS didukung dan memindai header keamanan seperti HSTS, CSP, X-Frame-Options, dan Referrer-Policy. Gunakan yang pertama untuk pemantauan kedaluwarsa dan yang kedua untuk audit keamanan.
Bisakah saya memeriksa sertifikat SSL tanpa kunci API?
Ya. Akses anonim memungkinkan 5 permintaan per menit dan 100 permintaan per hari dengan pembatasan tarif berbasis IP. Tidak diperlukan pendaftaran atau kunci API. Untuk throughput yang lebih tinggi, paket berbayar mulai dari $9/bulan.
Seberapa sering saya harus memeriksa masa berlaku sertifikat SSL?
Mingguan adalah dasar yang baik untuk sebagian besar tim. Mari Enkripsi sertifikat diperbarui setiap 90 hari dengan perpanjangan otomatis 30 hari sebelum habis masa berlakunya. Pemeriksaan mingguan dengan ambang peringatan 30 hari memberi Anda cukup waktu untuk memperbaiki kegagalan perpanjangan sebelum masa berlaku sertifikat habis.
Apakah ini berfungsi dengan sertifikat yang ditandatangani sendiri atau internal?
API terhubung ke domain melalui internet publik, sehingga dapat berfungsi dengan sertifikat apa pun yang disajikan pada port 443. Sertifikat yang ditandatangani sendiri akan mengembalikan detail sertifikat, namun bidang penerbit akan menampilkan entitas yang ditandatangani sendiri, bukan CA tepercaya.

Mulai membangun dengan botoi

150+ endpoint API untuk pencarian, pemrosesan teks, pembuatan gambar, dan utilitas developer. Paket gratis, tanpa kartu kredit.