# 🔐 ПЛАН БЕЗОПАСНОСТИ API КЛЮЧЕЙ ## ТЕКУЩИЕ ПРОБЛЕМЫ БЕЗОПАСНОСТИ 1. **API ключи хранятся В ОТКРЫТОМ ВИДЕ** в БД ❌ 2. **Нет истории изменений** ключей ❌ 3. **Нет аудита доступа** к ключам ❌ 4. **Ключи видны в GraphQL ответах** ❌ ## РЕКОМЕНДУЕМАЯ АРХИТЕКТУРА ### 1. ШИФРОВАНИЕ КЛЮЧЕЙ ```typescript // services/crypto-service.ts import crypto from 'crypto' export class CryptoService { private algorithm = 'aes-256-gcm' private secretKey = process.env.ENCRYPTION_KEY // 32 байта encrypt(text: string): { encrypted: string; iv: string; tag: string } { const iv = crypto.randomBytes(16) const cipher = crypto.createCipheriv(this.algorithm, this.secretKey, iv) let encrypted = cipher.update(text, 'utf8', 'hex') encrypted += cipher.final('hex') const tag = cipher.getAuthTag() return { encrypted, iv: iv.toString('hex'), tag: tag.toString('hex'), } } decrypt(encrypted: string, iv: string, tag: string): string { const decipher = crypto.createDecipheriv(this.algorithm, this.secretKey, Buffer.from(iv, 'hex')) decipher.setAuthTag(Buffer.from(tag, 'hex')) let decrypted = decipher.update(encrypted, 'hex', 'utf8') decrypted += decipher.final('utf8') return decrypted } } ``` ### 2. ОБНОВЛЕННАЯ СХЕМА БД ```prisma model ApiKey { id String @id @default(cuid()) marketplace MarketplaceType encryptedKey String // Зашифрованный ключ encryptionIv String // Вектор инициализации encryptionTag String // Тег аутентификации keyHash String // Хеш для быстрого сравнения clientId String? isActive Boolean @default(true) lastUsedAt DateTime? expiresAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt organizationId String organization Organization @relation(fields: [organizationId], references: [id]) // Аудит createdById String createdBy User @relation("ApiKeyCreatedBy", fields: [createdById], references: [id]) lastModifiedById String? lastModifiedBy User? @relation("ApiKeyModifiedBy", fields: [lastModifiedById], references: [id]) // История изменений auditLogs ApiKeyAuditLog[] @@unique([organizationId, marketplace]) @@index([keyHash]) @@map("api_keys") } model ApiKeyAuditLog { id String @id @default(cuid()) action ApiKeyAction // CREATED, UPDATED, VALIDATED, USED, DEACTIVATED performedAt DateTime @default(now()) performedBy String user User @relation(fields: [performedBy], references: [id]) apiKeyId String apiKey ApiKey @relation(fields: [apiKeyId], references: [id]) metadata Json? // Дополнительная информация @@index([apiKeyId]) @@index([performedBy]) @@map("api_key_audit_logs") } enum ApiKeyAction { CREATED UPDATED VALIDATED USED DEACTIVATED REACTIVATED DELETED } ``` ### 3. БЕЗОПАСНЫЕ РЕЗОЛВЕРЫ ```typescript // Сохранение ключа const encrypted = cryptoService.encrypt(apiKey) await prisma.apiKey.create({ data: { organizationId: user.organization.id, marketplace, encryptedKey: encrypted.encrypted, encryptionIv: encrypted.iv, encryptionTag: encrypted.tag, keyHash: crypto.createHash('sha256').update(apiKey).digest('hex'), createdById: context.user.id, // Аудит auditLogs: { create: { action: 'CREATED', performedBy: context.user.id, metadata: { ip: context.ip, userAgent: context.userAgent }, }, }, }, }) // Использование ключа const apiKeyRecord = await prisma.apiKey.findUnique({ where: { id } }) const decryptedKey = cryptoService.decrypt( apiKeyRecord.encryptedKey, apiKeyRecord.encryptionIv, apiKeyRecord.encryptionTag, ) // Логирование использования await prisma.apiKeyAuditLog.create({ data: { action: 'USED', apiKeyId: apiKeyRecord.id, performedBy: context.user.id, metadata: { purpose: 'statistics_fetch' }, }, }) ``` ### 4. ЗАЩИТА В GRAPHQL ```typescript // Никогда не возвращать расшифрованные ключи type ApiKey { id: ID! marketplace: MarketplaceType! isActive: Boolean! lastUsedAt: DateTime createdAt: DateTime! # НЕ ВКЛЮЧАТЬ: apiKey, encryptedKey, encryptionIv, encryptionTag # Показывать только маскированную версию maskedKey: String! # "••••••••••1234" } ``` ### 5. ПЕРЕМЕННЫЕ ОКРУЖЕНИЯ ```env # .env.local ENCRYPTION_KEY=your-32-byte-base64-encoded-key-here # Генерировать: openssl rand -base64 32 ``` ## ПЛАН МИГРАЦИИ 1. **Создать CryptoService** 2. **Обновить схему БД** с новыми полями 3. **Миграция существующих ключей** (зашифровать) 4. **Обновить резолверы** для работы с шифрованием 5. **Добавить аудит** всех операций 6. **Обновить UI** для показа только маскированных ключей ## ДОПОЛНИТЕЛЬНЫЕ МЕРЫ - Ротация ключей шифрования каждые 90 дней - Автоматическое удаление неиспользуемых ключей - Уведомления об аномальной активности - Rate limiting для API операций - Двухфакторная аутентификация для изменения ключей