architect/_archive/2025-11-09-marketplace-old/marketplace-mvp/SECRETS.md

🔐 SECRETS - Управление паролями и ключами

Проект: Marketplace MVP (mp1)
Последнее обновление: 2025-11-08


⚠️ КРИТИЧНО: БЕЗОПАСНОСТЬ

НИКОГДА не коммитьте этот файл в git если он содержит реальные пароли!

Этот файл должен быть в .gitignore:

SECRETS.md
secrets/
*.pem
*.key
credentials.json

📑 СОДЕРЖАНИЕ

  1. Принципы работы с секретами
  2. Инвентарь секретов
  3. Переменные окружения
  4. API ключи
  5. Database credentials
  6. SSH ключи
  7. SSL сертификаты
  8. Ротация секретов
  9. Хранение секретов
  10. Emergency access

🎯 ПРИНЦИПЫ РАБОТЫ С СЕКРЕТАМИ {#принципы-работы-с-секретами}

Золотые правила

  1. НИКОГДА не коммитить секреты в git
    - ❌ В коде: api_key = "sk-abc123"
    - ✅ Через env: api_key = os.getenv("API_KEY")

  2. Разные секреты для разных окружений
    - Development: dev_api_key
    - Staging: staging_api_key
    - Production: prod_api_key

  3. Минимальные права доступа
    - Давать только то, что нужно
    - Отзывать неиспользуемые ключи

  4. Регулярная ротация
    - Пароли: раз в 90 дней
    - API ключи: раз в 180 дней
    - SSH ключи: раз в 365 дней

  5. Аудит использования
    - Логировать кто и когда использовал секрет
    - Мониторить подозрительную активность


📊 ИНВЕНТАРЬ СЕКРЕТОВ {#инвентарь-секретов}

Таблица всех секретов

Секрет Тип Окружение Где хранится Последняя ротация Следующая ротация
DATABASE_URL Password Production .env 2025-10-01 2026-01-01
SECRET_KEY Random Production .env 2025-09-01 2025-12-01
OZON_API_KEY API Key Production .env 2025-11-01 2026-05-01
OZON_CLIENT_ID API Key Production .env 2025-11-01 -
SSH_PRIVATE_KEY SSH Key Production ~/.ssh/id_rsa 2025-01-01 2026-01-01
SSL_CERT Certificate Production /etc/ssl/ 2025-06-01 2026-06-01
{ДРУГИЕ}

ШАБЛОН для добавления:

| {НАЗВАНИЕ} | {ТИП} | {ENV} | {РАСПОЛОЖЕНИЕ} | {ДАТА_СОЗДАНИЯ} | {ДАТА_РОТАЦИИ} |

🔑 ПЕРЕМЕННЫЕ ОКРУЖЕНИЯ {#переменные-окружения}

Расположение

# Production
/etc/Marketplace MVP (mp1)/.env

# Development
/path/to/project/.env  (gitignored)

Структура .env

# ========================================
# 🗄️ БАЗА ДАННЫХ
# ========================================

# PostgreSQL (Production)
DATABASE_URL=postgresql://user:STRONG_PASSWORD@localhost:5432/dbname

# ========================================
# 🔐 СЕКРЕТНЫЕ КЛЮЧИ
# ========================================

# Secret key для шифрования (64 символа, случайный)
# Генерация: openssl rand -hex 32
SECRET_KEY=abc123def456...

# JWT token secret
JWT_SECRET=xyz789uvw456...

# ========================================
# 🔌 API КЛЮЧИ
# ========================================

# Ozon API (получить в личном кабинете)
OZON_CLIENT_ID=123456
OZON_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

# Wildberries API
WB_API_KEY=your-wb-api-key

# СДЭК API (тестовые ключи - НЕ для production!)
CDEK_ACCOUNT=your-account
CDEK_SECURE_PASSWORD=your-password

# ========================================
# 📧 EMAIL (если используется)
# ========================================

SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=app-specific-password  # НЕ основной пароль!

# ========================================
# 📊 МОНИТОРИНГ
# ========================================

# Sentry DSN (error tracking)
SENTRY_DSN=https://...@sentry.io/...

# ========================================
# 🔐 ДРУГИЕ СЕКРЕТЫ
# ========================================

# {ДОБАВЬТЕ_СВОИ}

Генерация секретов

# SECRET_KEY (64 символа)
openssl rand -hex 32

# JWT_SECRET (128 символов)
openssl rand -base64 96

# Пароль (16 символов, сложный)
openssl rand -base64 16

# UUID (для токенов)
uuidgen

Права доступа

# .env должен читаться только owner
chmod 600 /etc/Marketplace MVP (mp1)/.env
chown claude-helper:claude-helper /etc/Marketplace MVP (mp1)/.env

# Проверка
ls -la /etc/Marketplace MVP (mp1)/.env
# Ожидаем: -rw------- 1 user group

🔌 API КЛЮЧИ {#api-ключи}

Ozon API

Где получить:
1. Личный кабинет Ozon Seller → Настройки → API
2. Создать ключ
3. Скопировать Client ID и API Key

Права:
- ✅ Чтение заказов (обязательно)
- ✅ Управление отгрузками (если нужно)
- ❌ Финансы (не давать если не нужно)

Хранение:

# .env
OZON_CLIENT_ID=123456
OZON_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Ротация: Раз в 6 месяцев или при компрометации

Проверка работы:

curl -X POST "https://api-seller.ozon.ru/v1/seller/info" \
  -H "Client-Id: 123456" \
  -H "Api-Key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# Ожидаем: 200 OK с данными продавца

Wildberries API

Где получить:
1. Личный кабинет WB → Профиль → Настройки → Доступ к API
2. Создать ключ
3. Скопировать токен

Хранение:

WB_API_KEY=your-wb-api-key

Ротация: Раз в 6 месяцев


СДЭК API

Где получить:
1. Тестовые (sandbox):
- Account: z9GRRu7FxmO53CQ9cFfI6qiy32wpfTkd
- Password: w24JTCv4MnAcuRTx0oHjHLDtyt3I6IBq

  1. Production:
    - Заключить договор с СДЭК
    - Получить account/password от менеджера

Хранение:

# Development (sandbox)
CDEK_ACCOUNT=z9GRRu7FxmO53CQ9cFfI6qiy32wpfTkd
CDEK_SECURE_PASSWORD=w24JTCv4MnAcuRTx0oHjHLDtyt3I6IBq
CDEK_API_URL=https://api.edu.cdek.ru/v2

# Production
CDEK_ACCOUNT=your-production-account
CDEK_SECURE_PASSWORD=your-production-password
CDEK_API_URL=https://api.cdek.ru/v2

🗄️ DATABASE CREDENTIALS {#database-credentials}

PostgreSQL

# Production
DATABASE_URL=postgresql://mp1_user:STRONG_PASSWORD_HERE@localhost:5432/mp1_prod

# Staging
DATABASE_URL=postgresql://mp1_user:DIFFERENT_PASSWORD@localhost:5432/mp1_staging

# Development (может быть SQLite)
DATABASE_URL=sqlite:///./data/dev.db

Создание пользователя БД

# PostgreSQL
sudo -u postgres psql

CREATE USER mp1_user WITH PASSWORD 'STRONG_PASSWORD';
CREATE DATABASE mp1_prod OWNER mp1_user;
GRANT ALL PRIVILEGES ON DATABASE mp1_prod TO mp1_user;

Пароли БД

Требования:
- Минимум 16 символов
- Буквы верхний/нижний регистр
- Цифры
- Специальные символы
- НЕ словарные слова

Генерация:

openssl rand -base64 20

Ротация: Раз в 90 дней (плановая), сразу при компрометации


🔑 SSH КЛЮЧИ {#ssh-ключи}

Инвентарь SSH ключей

Ключ Для чего Где Passphrase Создан Истекает
~/.ssh/id_rsa Production сервер Control Plane Да 2025-01-01 2026-01-01
~/.ssh/deploy_key GitHub deploy CI/CD Нет 2025-06-01 -
{ДРУГИЕ}

Создание SSH ключа

# С passphrase (рекомендуется для production)
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_prod

# Без passphrase (для автоматизации, CI/CD)
ssh-keygen -t ed25519 -N "" -C "deploy_key" -f ~/.ssh/deploy_key

Права доступа

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/id_*.pub

Добавление на сервер

# Скопировать публичный ключ
ssh-copy-id -i ~/.ssh/id_prod.pub user@server

# Или вручную
cat ~/.ssh/id_prod.pub | ssh user@server "cat >> ~/.ssh/authorized_keys"

Ротация SSH ключей

Когда:
- Раз в год (плановая)
- При увольнении сотрудника
- При компрометации

Процесс:

# 1. Создать новый ключ
ssh-keygen -t ed25519 -C "new_key" -f ~/.ssh/id_new

# 2. Добавить на сервер
ssh-copy-id -i ~/.ssh/id_new.pub user@server

# 3. Протестировать новый ключ
ssh -i ~/.ssh/id_new user@server

# 4. Удалить старый ключ с сервера
ssh user@server "sed -i '/OLD_KEY_FINGERPRINT/d' ~/.ssh/authorized_keys"

# 5. Удалить локально
rm ~/.ssh/id_old*

🔒 SSL СЕРТИФИКАТЫ {#ssl-сертификаты}

Let's Encrypt (бесплатные)

Расположение:

/etc/letsencrypt/live/{DOMAIN}/
├── fullchain.pem  # Сертификат + цепочка
├── privkey.pem    # Приватный ключ
└── cert.pem       # Только сертификат

Автообновление (certbot):

# Проверить сертификаты
certbot certificates

# Вручную обновить
certbot renew

# Автообновление (cron)
0 0 1 * * certbot renew --quiet && systemctl reload nginx

Проверка срока действия:

echo | openssl s_client -servername {DOMAIN} -connect {DOMAIN}:443 2>/dev/null | openssl x509 -noout -dates

# Ожидаем:
# notBefore=...
# notAfter=Mar  1 00:00:00 2026 GMT

Алерт за 30 дней до истечения:

# Скрипт проверки
#!/bin/bash
DOMAIN="{DOMAIN}"
EXPIRY=$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))

if [ $DAYS_LEFT -lt 30 ]; then
    echo "WARNING: SSL cert expires in $DAYS_LEFT days!"
    # Отправить алерт (email/telegram)
fi

🔄 РОТАЦИЯ СЕКРЕТОВ {#ротация-секретов}

График ротации

Тип секрета Период Следующая ротация
Пароли БД 90 дней {ДАТА + 90 дней}
SECRET_KEY 180 дней {ДАТА + 180 дней}
API ключи 180 дней {ДАТА + 180 дней}
SSH ключи 365 дней {ДАТА + 365 дней}
SSL сертификаты 90 дней Автообновление

Процесс ротации пароля БД

# 1. Создать новый пароль
NEW_PASSWORD=$(openssl rand -base64 20)

# 2. Изменить в PostgreSQL
sudo -u postgres psql
ALTER USER mp1_user WITH PASSWORD '$NEW_PASSWORD';

# 3. Обновить .env
sed -i "s/DATABASE_URL=.*/DATABASE_URL=postgresql:\/\/mp1_user:$NEW_PASSWORD@localhost:5432\/mp1_prod/" /etc/Marketplace MVP (mp1)/.env

# 4. Перезапустить приложение
systemctl restart Marketplace MVP (mp1)

# 5. Проверить работу
curl http://localhost:8501/health

# 6. Задокументировать
echo "$(date): Rotated DB password" >> /var/log/Marketplace MVP (mp1)/secrets-rotation.log

Процесс ротации API ключа

# 1. Создать новый ключ в личном кабинете Ozon/WB/etc

# 2. Обновить .env (старый и новый ключ одновременно)
OZON_API_KEY=new-key
OZON_API_KEY_OLD=old-key  # На случай отката

# 3. Перезапустить приложение
systemctl restart Marketplace MVP (mp1)

# 4. Протестировать 24 часа

# 5. Удалить старый ключ из .env и из личного кабинета

# 6. Задокументировать

💾 ХРАНЕНИЕ СЕКРЕТОВ {#хранение-секретов}

Уровни хранения

1. Development (локально)

# .env в проекте (gitignored)
/path/to/project/.env

2. Production (на сервере)

# Защищённый файл
/etc/Marketplace MVP (mp1)/.env
chmod 600
chown claude-helper:claude-helper

3. Vault (для больших команд)

HashiCorp Vault:

# Установка
apt install vault

# Инициализация
vault server -dev

# Сохранить секрет
vault kv put secret/Marketplace MVP (mp1)/db password="xxx"

# Получить секрет
vault kv get secret/Marketplace MVP (mp1)/db

AWS Secrets Manager:

# Создать секрет
aws secretsmanager create-secret \
  --name /Marketplace MVP (mp1)/db/password \
  --secret-string "xxx"

# Получить секрет
aws secretsmanager get-secret-value \
  --secret-id /Marketplace MVP (mp1)/db/password

4. Зашифрованное хранилище (для бэкапов)

# Зашифровать файл с секретами
gpg -c secrets.txt
# Создаст secrets.txt.gpg

# Расшифровать
gpg secrets.txt.gpg
# Спросит passphrase

🚨 EMERGENCY ACCESS {#emergency-access}

Когда нужен экстренный доступ

Break Glass процедура

Предусловие: Создать "запасной вход" заранее

# 1. Создать emergency user
sudo useradd -m -s /bin/bash emergency_admin
sudo usermod -aG sudo emergency_admin

# 2. Сгенерировать сложный пароль
EMERGENCY_PASSWORD=$(openssl rand -base64 20)

# 3. Установить пароль
echo "emergency_admin:$EMERGENCY_PASSWORD" | sudo chpasswd

# 4. Сохранить пароль в SEALED конверте
# Напечатать на бумаге, запечатать, положить в сейф

# 5. SSH ключ для emergency
ssh-keygen -t ed25519 -f ~/.ssh/emergency_key
# Публичный ключ → /home/emergency_admin/.ssh/authorized_keys
# Приватный ключ → на USB флешку в сейф

Использование:

# 1. Взять USB с emergency ключом из сейфа
# 2. Подключиться
ssh -i /path/to/emergency_key emergency_admin@server

# 3. Выполнить необходимые действия

# 4. ЛОГИРОВАТЬ всё что делали
echo "$(date): Emergency access by Admin: {ДЕЙСТВИЯ}" >> /var/log/emergency-access.log

# 5. После - ротация emergency пароля

📋 CHECKLIST БЕЗОПАСНОСТИ

Ежедневно

Еженедельно

Ежемесячно

Ежеквартально

Ежегодно


🆘 ЧТО ДЕЛАТЬ ПРИ УТЕЧКЕ

Немедленно (в течение 1 часа):

  1. Отозвать скомпрометированный секрет
    - API ключ → удалить в личном кабинете
    - Пароль БД → сменить
    - SSH ключ → удалить из authorized_keys

  2. Сгенерировать новый секрет
    - См. раздел "Ротация секретов"

  3. Проверить логи использования
    - Кто использовал секрет?
    - Были ли подозрительные действия?

  4. Уведомить команду

В течение 24 часов:

  1. Проверить нет ли других утечек
    - Просканировать git history
    - Проверить все логи

  2. Обновить документацию
    - Задокументировать инцидент
    - Обновить дату ротации

  3. Post-mortem анализ
    - Как произошла утечка?
    - Как предотвратить в будущем?


Последнее обновление: 2025-11-08
Ответственный за секреты: Admin
Emergency контакт: {ТЕЛЕФОН/EMAIL}