サイトのAPI図鑑B版
掲載情報が正確でない可能性があります。
セキュリティ・コンプライアンス

APIキー・シークレットの安全な管理方法【HashiCorp Vault・AWS Secrets Manager】

APIキー・データベースパスワード・OAuthシークレットの安全な管理方法をAWS Secrets Manager・HashiCorp Vault・環境変数の適切な使用・シークレットのローテーション手法を解説します。

#シークレット管理#AWS Secrets Manager#HashiCorp Vault#セキュリティ

シークレット管理の重要性

APIキー・データベースパスワード・JWTシークレット・OAuthクライアントシークレットは、不適切な管理によりセキュリティインシデントの原因になります。コードへのハードコード・Gitへの誤コミット・不適切な権限設定などのリスクをシークレット管理ツールで解消しましょう。

NGリストとリスク

  • コードへのハードコード(最悪)
  • .envファイルのGit管理(誤コミットリスク)
  • 共有スプレッドシートでの管理
  • Slackでの共有

AWS Secrets Managerの使い方

// シークレットの保存
aws secretsmanager create-secret   --name prod/myapp/database   --secret-string '{"username":"admin","password":"S3cureP@ss"}'

// アプリからシークレットを取得(Node.js)
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';

const secretsClient = new SecretsManagerClient({ region: 'ap-northeast-1' });

const getSecret = async (secretName) => {
  const command = new GetSecretValueCommand({ SecretId: secretName });
  const response = await secretsClient.send(command);
  return JSON.parse(response.SecretString);
};

// 起動時にシークレットを一度だけ取得してキャッシュ
const secrets = await getSecret('prod/myapp/database');
const dbPool = createDbPool({
  host: process.env.DB_HOST,
  user: secrets.username,
  password: secrets.password
});

HashiCorp Vaultの基本的な使い方

# Vaultへのシークレット保存
vault kv put secret/myapp/api-keys   openai_key=sk-xxxx   stripe_key=sk_live_xxxx   sendgrid_key=SG.xxxxx

# Vaultからシークレットを取得(Node.js)
import Vault from 'node-vault';

const vault = Vault({
  endpoint: process.env.VAULT_ADDR,
  token: process.env.VAULT_TOKEN
});

const { data } = await vault.read('secret/data/myapp/api-keys');
const { openai_key, stripe_key } = data.data;

GitHub Actionsでのシークレット管理

# GitHub Secretsを使ってCI/CDでシークレットを安全に使用
jobs:
  deploy:
    steps:
      - name: APIキーを環境変数に設定
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        run: npm run deploy

シークレットのスキャン(GitLeaks)

# GitLeaksでリポジトリ内のシークレットをスキャン
docker run -v $(pwd):/path   ghcr.io/gitleaks/gitleaks:latest   detect --source=/path --report-format=json

# pre-commitフックでコミット前にスキャン
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

シークレットローテーションの自動化

// AWS Secrets ManagerでAPIキーを自動ローテーション
// Lambdaローテーション関数
exports.handler = async (event) => {
  const { SecretId, ClientRequestToken, Step } = event;
  
  switch (Step) {
    case 'createSecret':
      const newApiKey = await generateNewApiKey();
      await secretsManager.putSecretValue({
        SecretId,
        ClientRequestToken,
        SecretString: JSON.stringify({ apiKey: newApiKey }),
        VersionStages: ['AWSPENDING']
      }).promise();
      break;
    
    case 'finishSecret':
      await secretsManager.updateSecretVersionStage({
        SecretId,
        VersionStage: 'AWSCURRENT',
        MoveToVersionId: ClientRequestToken
      }).promise();
      break;
  }
};

まとめ

シークレット管理のベストプラクティスは「コードには秘密情報を書かない」です。AWS Secrets ManagerやHashiCorp Vaultを使ってシークレットを安全に管理し、GitLeaksでリポジトリへの混入を自動検知します。定期的なローテーションで漏洩リスクを最小化してください。

よくある質問

Q.環境変数でシークレットを管理するとなぜ安全でないのですか?

環境変数自体は暗号化されておらず、プロセス一覧からアクセスされる可能性があります。コンテナ化環境ではコンテナの検査コマンドで見える場合があります。.envファイルをGitにコミットするミスも頻繁に発生します。AWS Secrets ManagerやVaultを使えば暗号化・アクセス制御・監査ログが標準で備わります。

Q.シークレットのローテーション(更新)はなぜ定期的に行うべきですか?

定期的なシークレットのローテーションにより、漏洩した場合の影響期間を限定できます。AWS Secrets ManagerはLambdaを使ったシークレットの自動ローテーションをサポートしており、DBパスワードなどの自動更新が可能です。

Q.GitにAPIキーを誤ってコミットした場合はどうすればよいですか?

すぐにAPIキーを無効化・再発行することが最優先です。Gitの履歴からは`git filter-branch`またはBFG Repo Cleanerで削除できますが、いったんリモートにプッシュされた場合はすでに他者に見られた可能性があるため、キーの無効化が最重要です。

関連記事