Перейти к содержимому
Integration

Отслеживайте срок действия сертификата SSL с помощью REST API

| 6 min read

Проверьте даты истечения срока действия сертификата SSL, эмитентов и заголовки безопасности для любого домена с двумя конечными точками API. Включает примеры действий GitHub, Node.js и Slack.

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

SSL-сертификат с истекшим сроком действия переводит ваш сайт в автономный режим и отображает предупреждение браузера, которое пугает удаленные клиенты. Сертификаты Let's Encrypt автоматически обновляются, но неправильно настроен DNS, не выполняются задания cron, а забытые вручную сертификаты по-прежнему вызывают сбои в работе. Вам нужен способ контролировать срок действия даты во всех ваших доменах.

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

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

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

Запустите это по расписанию cron или интегрируйте в существующий конвейер проверки работоспособности. Promise.all вызов проверяет все домены одновременно, поэтому общее количество время выполнения остается близким к задержке одного вызова 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 заголовок для более высоких лимитов.
  • Еженедельное задание cron GitHub Actions с 30-дневным порогом выявляет сбои продления. прежде чем они прекратят работу.
  • Объедините обе конечные точки для запуска мониторинга срока действия сертификата и заголовка безопасности. аудиты в одном скрипте.

FAQ

Как проверить срок действия сертификата SSL через API?
Отправьте запрос POST на https://api.botoi.com/v1/ssl-cert/certificate с телом JSON, содержащим домен. Ответ включает поля valid_from, valid_to иdays_until_expiry сертификата. Никакого OpenSSL 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?
Еженедельно — хороший базовый уровень для большинства команд. Сертификаты Let's Encrypt обновляются каждые 90 дней с автоматическим продлением за 30 дней до истечения срока действия. Еженедельная проверка с порогом предупреждения в 30 дней дает вам достаточно времени, чтобы исправить ошибки продления до истечения срока действия сертификата.
Работает ли это с самозаверяющими или внутренними сертификатами?
API подключается к домену через общедоступный Интернет, поэтому он работает с любым сертификатом, передаваемым через порт 443. Самозаверяющие сертификаты будут возвращать сведения о сертификате, но в поле эмитента будет отображаться самозаверяющий объект вместо доверенного центра сертификации.

Начните разработку с botoi

150+ API-эндпоинтов для поиска, обработки текста, генерации изображений и утилит для разработчиков. Бесплатный тариф, без банковской карты.