
## この記事でわかること

- DKIM 鍵を 3 ヶ月ごとに自動ローテーションする運用設計
- cron / GitHub Actions / ESP API の 3 パターンの比較
- グレース期間（旧鍵残存期間）の決め方と監視ポイント

DKIM 鍵ローテは「年 1 回以上」が一般的ですが、機密度の高いメールを扱う企業では **3 ヶ月ごとの更新** を採用するケースが増えています。手動運用では繁忙期や担当者交代で取りこぼし、結果として鍵が数年単位で放置されることも珍しくありません。

本記事では手動手順の[DKIM 鍵ローテーションの手順](/blog/dkim-key-rotation)を前提に、その先の「自動化」を整理します。鍵長の議論は[DKIM 鍵の 2048bit 化](/blog/dkim-key-2048-upgrade)を併読してください。

## なぜ「3 ヶ月」「自動化」なのか

- **暗号攻撃の機会を最小化**：秘密鍵漏洩時の被害ウィンドウが短い
- **運用ルーチン化**：四半期定例に組み込みやすく、引き継ぎでも忘れにくい
- **監査整合**：四半期決算や監査タイミングと変更履歴を揃えられる
- **リプレイ被害時の応急処置の高速化**：[DKIM リプレイ攻撃](/blog/dkim-replay-attack)で正規署名が再送され続ける事象が発生したとき、自動化済みなら数十分で鍵を切り替えられる

3 ヶ月ごとの作業を手動で続けると年 4 回の手順実行が必要で、DNS 反映漏れ・旧鍵削除タイミングミス・パーミッション設定漏れ等のヒューマンエラーが累積します。「人が忘れずに」ではなく「仕組みで自動的に」回す設計が必要です。

## 自動ローテのタイムライン

3 ヶ月ローテの基本タイムラインは次のとおりです。

![DKIM 鍵 3 ヶ月自動ローテーションのタイムライン](/blog/dkim-rotation-automation/timeline.svg)

ポイントは **新旧鍵を 1〜2 週間共存させるグレース期間** です。転送・キャッシュされた古いメールの検証成功率を維持するため、新鍵切替直後に旧鍵を即削除しないのが鉄則です。セレクタ名は `s2026q1`〜`s2026q4` のように四半期を埋め込むと生成時期が一目でわかります。命名思想は[DKIM セレクタとは](/blog/dkim-selector-explained)を参照。

## 実装パターン 3 種の比較

中小企業で現実的に採用される実装パターンは次の 3 つに大別されます。

![DKIM 自動ローテーションの実装パターン](/blog/dkim-rotation-automation/automation-patterns.svg)

### パターン 1: cron + opendkim（自前サーバー）

Postfix + OpenDKIM 運用の典型構成。シェルスクリプトで次の処理を組みます。

1. `openssl genrsa -out new.key 2048` で新鍵生成
2. DNS API（Cloudflare / Route 53 等）で TXT レコード追加
3. `opendkim-genkey` の KeyTable / SigningTable 更新
4. `systemctl reload opendkim`
5. 14 日後に別 cron で旧鍵 DNS レコード削除

cron の設定例:

```
0 3 1 1,4,7,10 * /usr/local/bin/dkim-rotate.sh
```

四半期初日の午前 3 時に実行。柔軟性は最大ですが、認証情報管理・パーミッション・ログ設計まで含めて運用コストはかかります。

### パターン 2: GitHub Actions（中小企業の主力案）

Actions の cron で自動実行する構成。中小企業に最も推奨できるパターンです。

```yaml
name: dkim-rotate
on:
  schedule:
    - cron: '0 3 1 1,4,7,10 *'
  workflow_dispatch:

jobs:
  rotate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Generate new key
        run: ./scripts/generate-dkim-key.sh
      - name: Update DNS via Cloudflare API
        env:
          CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
        run: ./scripts/update-dns.sh
      - name: Notify Slack
        run: ./scripts/notify.sh
```

メリットは、実行ログが GitHub に永続保存され監査で参照可能・Secrets で API キーを安全に管理・`workflow_dispatch` で手動再実行可・PR レビュー経由の変更履歴が残る、の 4 点です。

秘密鍵自体はリポジトリに保存せず、Cloudflare Secrets や AWS Secrets Manager 等に書き込み、送信側がそこから読み出す構成が安全です。

### パターン 3: ESP API 連携

主要 ESP の DKIM 自動ローテ対応状況です。

- **SendGrid**: API で DKIM 設定再生成可。Webhook と組み合わせて完全自動化できる
- **Mailgun**: API で再生成可。鍵長 `2048` 指定可能
- **Microsoft 365**: PowerShell `Rotate-DkimSigningConfig -KeySize 2048` で実行可。Azure Automation Runbook で定期実行
- **Google Workspace**: 管理コンソールからの **手動再生成のみ**。API 自動化は限定的
- **Resend**: 2026 年時点で API 自動化は未対応

ESP API パターンでは DNS 側 TXT 更新が別途必要なケースが多く、ESP Webhook → DNS API 呼び出しの連携も合わせて組みます。

### グレース期間の設計

- **最低 7 日間**：DNS TTL × 受信側キャッシュ反映時間で十分な余裕
- **推奨 14 日間**：転送メール・遅延配信・モバイルキャリアの遅延を吸収
- **大規模配信時 21〜30 日間**：月次レポート系の再検証に対応

グレース期間中の DNS は次のように 2 つ並びます。

```
s2026q1._domainkey.example.co.jp.  TXT  "v=DKIM1; k=rsa; p=AAA..."  (旧鍵)
s2026q2._domainkey.example.co.jp.  TXT  "v=DKIM1; k=rsa; p=BBB..."  (新鍵)
```

送信側は新セレクタでのみ署名し、旧セレクタは検証用に DNS だけ残します。

## 監視と段階的な導入ステップ

自動化後も完全放置は危険です。次の監視を併設します。

1. **DKIM 検証の合成監視**：SaaS や自前リレーに定期送信し DKIM=pass を確認
2. **DMARC レポート監視**：aggregate report で DKIM 失敗率の急増を検知
3. **DNS 差分通知**：変更を Slack 通知し想定外更新を即時把握

DKIM 検証の基本は[DKIM 設定の確認方法](/blog/dkim-verification)を参照してください。

導入は段階運用が安全です。まず半年ローテを手動で 1 周して手順をドキュメント化し、次に GitHub Actions で半年ローテを自動化、安定したら 3 ヶ月ローテに移行、最後に合成監視と Slack 通知を追加する流れです。

## 自社の状況を確認してみませんか

設定状況がわからない方は、無料の[ドメイン診断](/diagnose)で現状をチェックできます。
DMARC・SPF・DKIM・SSL の状態が数十秒でレポートされます。
判断に迷う場合は[お問い合わせ](/contact)からご相談ください。専門家がわかりやすくサポートいたします。
