GitHub 認証トークンの期限切れを検知し GitHub App へ移行する

平文のトークン管理では、期限切れで自動化パイプラインが止まります。GitHub App の Installation Access Token を使って自動更新できる認証フローへ移行する手順と、期限切れの検知方法を解説します。

4分で読めます Tech
左に期限切れアイコン付きの「平文トークン」、右に GitHub App から自動ローテーションされる「Installation Access Token」を対比した認証移行図
この記事は AI が下書きを補助し、運営者が内容を確認して公開しています。

データ分析パイプラインにおける GitHub 認証の課題

データ分析業務では、Issue 管理・PR 自動化・ブログ記事生成など、GitHub REST API を活用した自動化パイプラインが重要な役割を果たします。しかし、OAuth トークンの期限切れによる自動化停止は、業務継続性の大きなリスクとなります。

この記事では、平文トークン管理から GitHub App による自動更新可能な認証フローへの移行手順と、実装時の技術的検討点を再現可能な形で解説します。

GitHub 認証トークンの期限切れが引き起こす自動化パイプラインの停止

セキュリティリスク

# 現状: 平文でのトークン保存
echo "ghp_xxxxxxxxxxxxxxxxxxxx" > secrets/gh-token
  • ローカルファイルシステムに平文で GitHub トークンを保存
  • .gitignore で除外していても、ディスク上に機密情報が残存
  • トークンのローテーションが手動依存

運用負荷

# 手動更新が必要
find /sessions/*/mnt/*/secrets/gh-token -type f -exec cat {} \;
  • トークン期限切れ時の手動更新
  • 自動化パイプラインの予期しない停止
  • 24時間365日の監視が必要

GitHub App 移行による解決策

1. GitHub App の作成

GitHub App を作成し、以下の権限を設定します:

{
  "permissions": {
    "issues": "write",
    "pull_requests": "write",
    "contents": "write",
    "metadata": "read"
  },
  "events": [
    "issues",
    "pull_request"
  ]
}

2. Installation Access Token の取得

GitHub App の Installation Access Token は1時間の有効期限で自動更新されます:

// Installation Access Token の取得
const jwt = require('jsonwebtoken');
const fetch = require('node-fetch');

async function getInstallationAccessToken(appId, privateKey, installationId) {
  // JWT の生成
  const payload = {
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + (10 * 60), // 10分
    iss: appId
  };
  
  const token = jwt.sign(payload, privateKey, { algorithm: 'RS256' });
  
  // Installation Access Token の取得
  const response = await fetch(
    `https://api.github.com/app/installations/${installationId}/access_tokens`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Accept': 'application/vnd.github.v3+json'
      }
    }
  );
  
  const data = await response.json();
  return data.token;
}

3. 自動化パイプラインへの統合

#!/bin/bash
# GitHub App トークンを使った自動化スクリプト

APP_ID="123456"
INSTALLATION_ID="987654"
PRIVATE_KEY_PATH="/secure/github-app-key.pem"

# Installation Access Token の取得
TOKEN=$(node get-installation-token.js "$APP_ID" "$INSTALLATION_ID" "$PRIVATE_KEY_PATH")

# GitHub API の実行
curl -H "Authorization: token $TOKEN" \
     -H "Accept: application/vnd.github.v3+json" \
     https://api.github.com/repos/owner/repo/issues

トークン期限切れの検知と通知

1. 期限切れ検知ロジック

async function checkTokenExpiry(token) {
  try {
    const response = await fetch('https://api.github.com/rate_limit', {
      headers: { 'Authorization': `token ${token}` }
    });
    
    if (response.status === 401) {
      throw new Error('Token expired or invalid');
    }
    
    const rateLimit = await response.json();
    return rateLimit.rate.remaining > 0;
  } catch (error) {
    console.error('Token validation failed:', error.message);
    return false;
  }
}

2. Slack 通知の実装

async function notifyTokenExpiry(slackWebhookUrl, error) {
  const message = {
    text: "GitHub API 認証エラー",
    attachments: [{
      color: "danger",
      fields: [{
        title: "エラー内容",
        value: error.message,
        short: false
      }, {
        title: "対応",
        value: "GitHub App のトークン更新またはクレデンシャル確認が必要",
        short: false
      }]
    }]
  };
  
  await fetch(slackWebhookUrl, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(message)
  });
}

実装時の技術的考慮点

サンドボックス環境での制約

# Cowork(Claude のローカルサブスクリプションに含まれる定期実行基盤)サンドボックスの制約
# - 毎回新規環境(状態引き継ぎなし)
# - FUSE マウント内のファイルは削除不可
# - 外部ネットワークアクセスは可能

秘密鍵の安全な管理

# GCP Secret Manager を使った秘密鍵管理
gcloud secrets create github-app-private-key \
  --data-file=private-key.pem

# 実行時に取得
PRIVATE_KEY=$(gcloud secrets versions access latest \
  --secret=github-app-private-key)

移行手順

1. 現行システムのバックアップ

# 既存のトークン設定をバックアップ
cp secrets/gh-token secrets/gh-token.backup

2. GitHub App の設定

  1. GitHub Settings > Developer settings > GitHub Apps
  2. “New GitHub App” を選択
  3. 必要な権限とイベントを設定
  4. 秘密鍵をダウンロード(.pem ファイル)

3. スケジュールタスクの更新

# .claude/skills/generate-blog/SKILL.md の環境セットアップ更新
sed -i 's/secrets\/gh-token/github-app-auth.js/' SKILL.md

4. 動作確認

# 新しい認証フローのテスト
node test-github-app-auth.js
gh api user --auth-token $(node get-installation-token.js)

期待される効果

セキュリティ向上

  • 平文トークンファイルの削除
  • 1時間の短い有効期限による露出リスク軽減
  • 秘密鍵の暗号化保存

運用負荷軽減

  • トークンローテーションの自動化
  • 期限切れによる自動化停止の回避
  • 24時間監視の不要化

保守性向上

  • 標準的な GitHub App パターンの採用
  • スケーラブルな認証アーキテクチャ
  • エラーハンドリングの統一化

まとめ

平文トークン管理から GitHub App への移行により、データ分析パイプラインの自動化がより安全で持続可能になります。Installation Access Token の自動更新機能を活用することで、運用負荷を大幅に軽減しながら、セキュリティレベルを向上できます。

実装時は、サンドボックス環境の制約を理解し、秘密鍵の管理方法を慎重に設計することが重要です。GCP Secret Manager や AWS Secrets Manager などのマネージドサービスとの組み合わせにより、エンタープライズレベルの認証システムを構築できます。

関連記事