Tips & Tricks

Claude Codeで環境変数管理のベストプラクティスを実装する

Claude Codeを活用して環境変数の安全な管理・バリデーション・型安全な読み込みを実装する方法を解説します。

環境変数管理が重要な理由

アプリケーション開発では、APIキーやデータベース接続情報などの機密情報を安全に管理する必要があります。環境変数はその基本手段ですが、型安全性やバリデーションが不足しがちです。Claude Codeを使えば、堅牢な環境変数管理の仕組みを素早く構築できます。

型安全な環境変数の読み込み

> 環境変数をzodでバリデーションして型安全に読み込むモジュールを作って。
> 必須・任意の区別と、デフォルト値の設定もできるようにして。
import { z } from 'zod';

const envSchema = z.object({
  NODE_ENV: z.enum(['development', 'staging', 'production']).default('development'),
  PORT: z.coerce.number().int().positive().default(3000),
  DATABASE_URL: z.string().url(),
  REDIS_URL: z.string().url().optional(),
  API_KEY: z.string().min(1, 'API_KEYは必須です'),
  JWT_SECRET: z.string().min(32, 'JWT_SECRETは32文字以上必要です'),
  CORS_ORIGINS: z.string().transform((s) => s.split(',')).default('http://localhost:3000'),
  LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
});

export type Env = z.infer<typeof envSchema>;

function loadEnv(): Env {
  const result = envSchema.safeParse(process.env);

  if (!result.success) {
    const formatted = result.error.format();
    console.error('環境変数のバリデーションエラー:');
    for (const [key, value] of Object.entries(formatted)) {
      if (key !== '_errors' && value && '_errors' in value) {
        console.error(`  ${key}: ${(value as any)._errors.join(', ')}`);
      }
    }
    process.exit(1);
  }

  return result.data;
}

export const env = loadEnv();

.envファイルのテンプレート管理

> .env.exampleを自動生成するスクリプトを作って。
> 実際の値は含めず、説明コメント付きで。
import fs from 'fs';
import path from 'path';

function generateEnvExample(envPath: string, outputPath: string) {
  const envContent = fs.readFileSync(envPath, 'utf-8');
  const lines = envContent.split('\n');

  const exampleLines = lines.map((line) => {
    if (line.startsWith('#') || line.trim() === '') return line;

    const [key] = line.split('=');
    const descriptions: Record<string, string> = {
      DATABASE_URL: '# データベース接続URL (例: postgresql://user:pass@localhost:5432/db)',
      API_KEY: '# APIキー (本番環境では安全に管理してください)',
      JWT_SECRET: '# JWT署名用シークレット (32文字以上)',
    };

    const comment = descriptions[key?.trim()] || '';
    return `${comment}\n${key?.trim()}=`;
  });

  fs.writeFileSync(outputPath, exampleLines.join('\n'));
}

環境ごとの設定切り替え

> 環境ごとに異なる設定を管理するConfigクラスを作って。
> development, staging, productionの3環境に対応して。
interface AppConfig {
  database: { pool: number; ssl: boolean };
  cache: { ttl: number; enabled: boolean };
  logging: { level: string; format: string };
}

const configs: Record<string, AppConfig> = {
  development: {
    database: { pool: 5, ssl: false },
    cache: { ttl: 60, enabled: false },
    logging: { level: 'debug', format: 'pretty' },
  },
  production: {
    database: { pool: 20, ssl: true },
    cache: { ttl: 3600, enabled: true },
    logging: { level: 'warn', format: 'json' },
  },
};

export function getConfig(): AppConfig {
  const nodeEnv = env.NODE_ENV;
  return configs[nodeEnv] ?? configs.development;
}

シークレットのローテーション対応

機密情報のローテーションを安全に行うため、複数バージョンのシークレットを同時に保持する仕組みも構築できます。

class SecretManager {
  private secrets: Map<string, string[]> = new Map();

  register(key: string, ...values: string[]) {
    this.secrets.set(key, values.filter(Boolean));
  }

  getCurrent(key: string): string {
    const values = this.secrets.get(key);
    if (!values || values.length === 0) {
      throw new Error(`Secret not found: ${key}`);
    }
    return values[0];
  }

  verify(key: string, token: string, verifyFn: (secret: string, token: string) => boolean): boolean {
    const values = this.secrets.get(key) ?? [];
    return values.some((secret) => verifyFn(secret, token));
  }
}

const secrets = new SecretManager();
secrets.register('JWT_SECRET', env.JWT_SECRET, process.env.JWT_SECRET_PREVIOUS ?? '');

まとめ

Claude Codeを使えば、zodによる型安全なバリデーション、環境別設定、シークレット管理まで、環境変数管理の仕組みを一貫して構築できます。セキュリティの基本として認証実装ガイドも参考にしてください。テストの自動化についてはテスト戦略の記事で詳しく解説しています。

zodの詳細はZod公式ドキュメントをご覧ください。環境変数管理のセキュリティについてはOWASP Configuration Guideも参考になります。

#Claude Code #環境変数 #セキュリティ #TypeScript #設定管理