# Базы данных: что нужно SecOps

← [Раздел](README.md) · [Главная](../README.md)

## Цель

Понять **типы баз данных**, базовый SQL, риски (injection, backups, доступы) — без проектирования схем как DBA.

## Предварительно

- [HTTP, API, JSON](http-api-json-prostymi-slovami.md)

## Время

**3–4 часа**

---

## Зачем SecOps знать про БД

| Инцидент / audit | Нужно понимать |
|------------------|----------------|
| SQL Injection | Как запросы строятся |
| Утечка PII | Где лежат таблицы guests, users |
| Ransomware | Есть ли backups, RPO/RTO |
| Overprivileged DB user | App подключается как `admin` |
| Encryption at rest | Диск vs column-level |

---

## Типы хранилищ

| Тип | Модель | Примеры | Типичное use |
|-----|--------|---------|--------------|
| **Реляционная (SQL)** | Таблицы, строки, связи | PostgreSQL, MySQL | Заказы, пользователи |
| **Key-Value** | Ключ → значение | Redis, DynamoDB | Сессии, кэш |
| **Document** | JSON-документы | MongoDB | Гибкие схемы |
| **Object storage** | Файлы по ключу | S3, MinIO | Фото, бэкапы |

**Аналогия SQL:** Excel с несколькими связанными таблицами и строгими столбцами.

---

## Базовый SQL (чтение)

```sql
-- Выбрать 5 гостей
SELECT id, name, email FROM guests LIMIT 5;

-- Фильтр
SELECT * FROM guests WHERE rsvp_status = 'confirmed';

-- Связь двух таблиц (JOIN)
SELECT g.name, e.title
FROM guests g
JOIN events e ON g.event_id = e.id;

-- Подсчёт
SELECT rsvp_status, COUNT(*) FROM guests GROUP BY rsvp_status;
```

**INSERT / UPDATE / DELETE** меняют данные — в prod только с правами и audit.

---

## SQL Injection — главный риск

**Плохо** (код склеивает строку):

```python
query = "SELECT * FROM users WHERE login = '" + user_input + "'"
```

Если `user_input` = `' OR '1'='1` — возможен обход login.

**Хорошо:** parameterized queries (prepared statements):

```python
cursor.execute("SELECT * FROM users WHERE login = ?", (user_input,))
```

SAST и WAF ищут **паттерны склеивания** SQL.

---

## Учётные записи и least privilege

| Плохо | Хорошо |
|-------|--------|
| App uses `postgres` superuser | Отдельный user `app_wedding_ro` |
| Один пароль на все env | Разные creds dev/staging/prod |
| Пароль в коде | Secret manager / env injection |

**Миграции** (Flyway, Liquibase) — отдельный user с DDL-правами, не runtime app.

---

## Backups и восстановление

| Термин | Значение |
|--------|----------|
| **Backup** | Копия данных на момент времени |
| **RPO** | Сколько данных можно **потерять** (1 ч, 24 ч) |
| **RTO** | За сколько **поднять** систему после сбоя |
| **PITR** | Point-in-time recovery |

**SecOps checklist:**

- [ ] Backups **encrypted**
- [ ] Restore **тестируется** (не «надеемся»)
- [ ] Доступ к backup storage **ограничен**
- [ ] Нет публичных S3 bucket с dump БД

---

## Шифрование данных

| Уровень | Что защищает |
|---------|--------------|
| TLS in transit | Трафик app ↔ DB |
| Disk encryption | Украденный диск |
| Column / app-level | Даже DBA не видит plaintext (PII) |

**Tokenization** — в БД хранится token, PAN карты — у платёжного провайдера.

---

## Логирование и PII

Логи приложения часто **случайно** пишут email, token, SQL.

```
❌ LOG.info("User login: " + email + " token: " + jwt)
✅ LOG.info("User login success", userId=42)
```

GDPR / 152-ФЗ — минимизация PII в логах и retention policy.

---

## Практика (lab)

1. Поднимите **Docker PostgreSQL** (только локально).
2. Создайте таблицу `guests (id, name, rsvp_status)`.
3. INSERT 3 строки, SELECT с WHERE.
4. Создайте user `app_readonly` с GRANT SELECT only.

Не используйте production dumps.

---

## Самопроверка

1. Чем Redis отличается от PostgreSQL?
2. Что такое SQL injection одной фразой?
3. Зачем отдельный DB user для приложения?
4. Чем RPO отличается от RTO?

---

## Дальше

→ [Языки и стек — обзор](yazyki-i-stek-obzor.md)
