シークレット管理の重要性
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でリポジトリへの混入を自動検知します。定期的なローテーションで漏洩リスクを最小化してください。