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

# Lab 02 — Сканирование Docker-образа

## Цель

Собрать простой Docker-образ с устаревшей базой, просканировать **Trivy**, интерпретировать CVE, обновить базовый образ и сравнить отчёты до/после.

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

- Docker.
- Lab 01 не обязателен, но полезен контекст CI.

## Время

~40 минут.

## Шаг 1 — Структура проекта

```bash
mkdir -p ~/devsecops-labs/lab02-image/app
cd ~/devsecops-labs/lab02-image
```

`app/index.html`:

```html
<!DOCTYPE html>
<html><body><h1>DevSecOps Lab 02</h1></body></html>
```

## Шаг 2 — Dockerfile «до» (намеренно старый тег)

`Dockerfile.vulnerable`:

```dockerfile
FROM nginx:1.18-alpine
COPY app/index.html /usr/share/nginx/html/index.html
EXPOSE 80
```

```bash
docker build -f Dockerfile.vulnerable -t lab02-web:old .
```

## Шаг 3 — Скан Trivy

```bash
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image --severity HIGH,CRITICAL --format table lab02-web:old
```

Сохраните отчёт:

```bash
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image -f json -o /dev/stdout lab02-web:old \
  > report-old.json
```

Посчитайте Critical (jq опционально):

```bash
grep -c '"Severity": "CRITICAL"' report-old.json || echo "0 critical (grep approx)"
```

## Шаг 4 — Dockerfile «после»

`Dockerfile.fixed`:

```dockerfile
FROM nginx:1.26-alpine
RUN apk upgrade --no-cache
COPY app/index.html /usr/share/nginx/html/index.html
EXPOSE 80
USER nginx
```

```bash
docker build -f Dockerfile.fixed -t lab02-web:new .
trivy image --severity HIGH,CRITICAL lab02-web:new
```

Если `trivy` установлен локально — используйте его; иначе тот же docker run, что в шаге 3.

## Шаг 5 — Fail pipeline

```bash
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image --severity CRITICAL --exit-code 1 lab02-web:old
echo "Exit code: $?"
```

Ожидается **ненулевой** exit code на старом образе.

## Шаг 6 — SBOM (опционально)

```bash
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image --format spdx-json -o /dev/stdout lab02-web:new \
  > sbom-new.spdx.json
```

SBOM — список компонентов; нужен для supply chain и [audit-evidence](../09-compliance/audit-evidence.md).

## Шаг 7 — Политика `.trivyignore`

Если остаётся один принятый риск:

```
# Учебный пример — тикет SEC-LAB02-99, пересмотр 2025-12-01
CVE-2024-00000
```

Пересканируйте с `--ignorefile .trivyignore`.

## Шаг 8 — Подпись образа (концепт)

В prod используйте Cosign:

```bash
# Установка cosign отдельно; учебная команда без реального ключа
cosign sign --key cosign.key lab02-web:new
```

На курсе достаточно знать: digest + подпись = доверенный deploy.

## Таблица сравнения (заполните)

| Метрика | lab02-web:old | lab02-web:new |
|---------|---------------|---------------|
| Critical CVE | | |
| High CVE | | |
| USER root? | | |

## Критерии успеха

- [ ] Есть `report-old.json` и повторный скан `new`.
- [ ] Объяснили одну находку (пакет, CVE, fixed version).
- [ ] Проверили `--exit-code 1`.

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

1. Почему обновление `FROM` важнее, чем только `apk upgrade`?
2. Зачем `USER nginx` с точки зрения безопасности?
3. Что хранить для аудита: тег или digest?
4. Когда оправдан `.trivyignore`?

## Дальше

[Lab 03 — RBAC и NetworkPolicy](lab-03-k8s-rbac-networkpolicy.md)
