CertSpotterCT logAPIWeb 担当者

CertSpotter API の使い方|定期監視の実装

ドメイン番人8 分で読めます
目次

CertSpotter API のデータフロー

この記事でわかること

  • CertSpotter API のエンドポイントとレスポンス形式
  • curl で叩く最小例
  • cron で日次監視して Slack 通知する構成
  • 監視運用のレート制限と Webhook の使い分け

CertSpotter API とは

CertSpotter は SSLMate 社が提供する CT log(Certificate Transparency log、SSL 証明書の公開台帳)監視サービスです。Web 画面からドメインを登録すればメール通知が来る一方、自社の監視基盤に組み込みたい場合は Public API を叩くことになります。CertSpotter の基本機能と料金体系は CertSpotter の使い方|ドメイン監視の始め方 に整理しているので、本稿は API 利用に絞って解説します。

CT log そのものの概念は CT log とは|中小企業向け を参照してください。簡単に言うと「世界中で発行された SSL 証明書が全件記録される公開台帳」で、CertSpotter API はその台帳を集約済みのインデックス越しに自社ドメインだけ抜き出す窓口です。

エンドポイントとレスポンス形式

CertSpotter Public API の主要エンドポイントは 1 つだけです。

GET https://api.certspotter.com/v1/issuances

主なクエリパラメータ:

  • domain: 監視対象のドメイン(例: example.co.jp
  • include_subdomains: true でサブドメインも含める
  • expand: dns_names issuer cert のうち欲しいフィールドを指定
  • after: 前回取得した issuance id。差分取得に使う

レスポンスは JSON 配列で、各要素は以下のような構造です(一部抜粋)。

[
  {
    "id": "9876543210",
    "tbs_sha256": "…",
    "dns_names": ["shop.example.co.jp", "*.shop.example.co.jp"],
    "pubkey_sha256": "…",
    "issuer": { "name": "C=US, O=Let's Encrypt, CN=R3" },
    "not_before": "2026-05-20T03:14:00Z",
    "not_after":  "2026-08-18T03:14:00Z"
  }
]

id は単調増加するので、これを保存しておけば次回は after=<前回 id> で差分だけ取れます。

認証

無料の Public API は API key 必須です(以前は鍵なしで叩けましたが現在は要登録)。SSLMate のアカウントを作って発行した key を Authorization ヘッダで渡します。

Authorization: Bearer <YOUR_API_KEY>

レート制限は IP / アカウント単位で課されます。数分〜時間単位の poll なら無料枠で十分回りますが、秒単位の連打は 429 を返されるので避けます。

curl での最小例

example.co.jp 配下の発行を取得する例:

curl -sS \
  -H "Authorization: Bearer $CERTSPOTTER_TOKEN" \
  "https://api.certspotter.com/v1/issuances?domain=example.co.jp&include_subdomains=true&expand=dns_names&expand=issuer" \
  | jq '.[] | {id, dns_names, issuer: .issuer.name, not_before}'

差分取得の場合は最後に取った id を after に渡します。

curl -sS \
  -H "Authorization: Bearer $CERTSPOTTER_TOKEN" \
  "https://api.certspotter.com/v1/issuances?domain=example.co.jp&include_subdomains=true&after=9876543210"

jq.[] が空配列ならば前回以降に新規発行はありません。

cron で日次監視 + Slack 通知

日次監視 cron の最小構成

サーバーを建てずに、GitHub Actions の scheduled workflow とリポジトリ内 state.json だけで完結する構成例を示します。

スクリプト本体(Bash + jq)

#!/usr/bin/env bash
set -euo pipefail

DOMAIN="example.co.jp"
STATE_FILE="state.json"
LAST_ID=$(jq -r '.last_id // "0"' "$STATE_FILE" 2>/dev/null || echo "0")

RES=$(curl -sS \
  -H "Authorization: Bearer $CERTSPOTTER_TOKEN" \
  "https://api.certspotter.com/v1/issuances?domain=${DOMAIN}&include_subdomains=true&after=${LAST_ID}&expand=dns_names&expand=issuer")

COUNT=$(echo "$RES" | jq 'length')
if [ "$COUNT" -gt 0 ]; then
  MSG=$(echo "$RES" | jq -r '.[] | "・\(.dns_names | join(", ")) [\(.issuer.name)]"')
  curl -sS -X POST -H 'Content-Type: application/json' \
    --data "{\"text\": \"新規証明書 ${COUNT} 件:\n${MSG}\"}" \
    "$SLACK_WEBHOOK_URL"
  NEW_LAST=$(echo "$RES" | jq -r 'max_by(.id | tonumber).id')
  jq -n --arg id "$NEW_LAST" '{last_id: $id}' > "$STATE_FILE"
fi

GitHub Actions の定期実行

name: certspotter-monitor
on:
  schedule:
    - cron: "0 0 * * *"  # 毎日 09:00 JST
  workflow_dispatch:
jobs:
  poll:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Poll CertSpotter
        env:
          CERTSPOTTER_TOKEN: ${{ secrets.CERTSPOTTER_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
        run: ./scripts/poll.sh
      - name: Commit state
        run: |
          git config user.name "actions"
          git config user.email "actions@github.com"
          git add state.json
          git diff --cached --quiet || git commit -m "chore: update state"
          git push

これで月数十円もかからず、毎朝の差分通知が回ります。

Webhook 通知(Pro プラン)

無料 Public API は pull 型ですが、Pro プランでは push 型の Webhook 通知も使えます。CertSpotter 側が新規発行を検知した瞬間に指定 URL に POST してくれるので、cron の poll 間隔より早く検知できます。

選び方の目安:

  • 監視ドメイン 1〜3 件、即時性は不要 → 無料 API + cron
  • 監視ドメイン 5 件以上、または分単位の検知が欲しい → Pro + Webhook

crt.sh と比べて API 仕様や用途がどう違うかは certspotter vs crt.sh 比較|CT log 監視の選び方、ほかの CT log 監視ツールとの全体比較は CT log 監視ツール 5 選比較|不正証明書を防ぐ を参照してください。

レート制限と運用上の注意

  • 1 ドメインの poll は 5〜15 分間隔を上限の目安に。秒単位の連打は 429
  • 401 が返ったら API key が無効か未指定。Authorization ヘッダを再確認
  • 502 / 503 は SSLMate 側の一時的な問題なのでリトライ(指数バックオフ)
  • after を使わずに毎回全件取ると配列が肥大化する。必ず id を保存
  • 通知 Webhook の URL は GitHub Actions の secret に保存。リポジトリに直書きしない

よくある質問

無料 API でサブドメインも監視できますか

できます。include_subdomains=true を付ければ *.example.co.jp 配下も対象になります。サブドメインを大量に持っている場合の効率的な棚卸し方法は CT log でサブドメインを洗い出す方法 を参照。

古い証明書も取れますか

after を未指定で叩けば、CertSpotter のインデックスに残っている範囲で過去分も返ります。ただし返却件数が多くなりタイムアウトの原因になるため、初回 import 時は期間を区切るか、Pro プランの bulk export を検討します。

API key を Cloudflare Workers の secret に置いて Worker で監視するのは

可能です。Cron Triggers と KV を組み合わせれば GitHub Actions と同じ構成を Worker 上で組めます。KV に last_id を保存するだけです。

まとめ

  • CertSpotter Public API は /v1/issuances 1 本で完結
  • 認証は Bearer token、レート制限を意識して数分〜時間単位で poll
  • after=<前回 id> の差分取得 + state.json の保存が運用の肝
  • GitHub Actions の scheduled workflow + Slack Webhook でサーバーレス監視
  • 即時性が必要なら Pro プランの Webhook に切り替え

まずは現状を把握しましょう

自社ドメインで現在発行されている SSL 証明書の一覧と、メール認証(SPF / DKIM / DMARC)の状態は、ドメイン番人の無料診断で確認できます。CT log 監視の設計から導入までサポートが必要な場合はお問い合わせからご相談ください。

次の一歩は無料診断から。