Как организовать процесс обновления и патчинга базовых образов?
Уязвимости обнаруживаются постоянно — образ, безопасный сегодня, завтра может содержать критическую CVE. Регулярное обновление базовых образов и зависимостей является обязательным процессом для банковских систем и требованием стандартов безопасности (PCI DSS Requirement 6).
1. Стратегия фиксации (pin) версий:
Пример
# ПЛОХО — неизвестно, что получим при следующей сборке
FROM eclipse-temurin:21-jre
# ЛУЧШЕ — фиксация конкретной минорной версии
FROM eclipse-temurin:21.0.4_7-jre-alpine
# ЛУЧШЕЕ — pin по digest (неизменная ссылка на конкретный образ)
FROM eclipse-temurin@sha256:1a2b3c4d5e6f...
Тег (например, 21-jre) может указывать на разные образы в разное время — разработчики базового образа обновляют теги при выпуске патчей. Digest (@sha256:...) — это криптографический хеш, однозначно идентифицирующий конкретную версию образа. Pin по digest гарантирует воспроизводимость сборки, но требует дисциплины при обновлениях.
2. Автоматическое обнаружение обновлений с Renovate/Dependabot:
Renovate и Dependabot — инструменты, автоматически создающие Pull Request при появлении новых версий зависимостей. Они поддерживают Dockerfile, docker-compose, Maven, Gradle и другие экосистемы.
Пример
// renovate.json
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
"docker": {
"enabled": true,
"pinDigests": true
},
"packageRules": [
{
"matchDatasources": ["docker"],
"matchPackageNames": ["eclipse-temurin"],
"automerge": false,
"schedule": ["every weekday"],
"groupName": "base-image-updates"
}
],
"vulnerabilityAlerts": {
"enabled": true,
"labels": ["security"]
}
}
Параметр pinDigests: true автоматически добавляет digest к тегам при создании PR. Параметр automerge: false означает, что PR с обновлением базового образа требует ручного review — для банковских систем автоматический merge обновлений обычно запрещён политиками безопасности.
Пример
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "security-team"
labels:
- "docker"
- "dependencies"
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 10
3. Периодическое пересканирование развёрнутых образов:
Новые CVE появляются ежедневно. Образ, не имевший известных уязвимостей при деплое, может стать уязвимым через неделю. Поэтому необходимо регулярно пересканировать уже развёрнутые образы:
Пример
# CronJob для ежедневного сканирования всех образов в кластере
apiVersion: batch/v1
kind: CronJob
metadata:
name: image-scan
namespace: security
spec:
schedule: "0 6 * * *" # Каждый день в 6:00
jobTemplate:
spec:
template:
spec:
containers:
- name: scanner
image: aquasec/trivy:latest
command:
- /bin/sh
- -c
- |
# Получить список уникальных образов во всех namespace-ах
for image in $(kubectl get pods -A -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n' | sort -u); do
echo "Scanning: $image"
trivy image --severity CRITICAL,HIGH --exit-code 0 "$image"
done
restartPolicy: OnFailure
serviceAccountName: image-scanner-sa
4. Процесс патчинга для банковского проекта:
Пример
1. Обнаружение (автоматическое):
+-- Renovate/Dependabot создаёт PR с обновлением зависимости
+-- Trivy обнаруживает CVE при ежедневном пересканировании
+-- Подписка на security advisories (GitHub Advisory, Alpine SecDB, Spring Security)
2. Оценка (определение приоритета):
+-- CVSS >= 9.0 (Critical) -> патч в течение 24 часов
+-- CVSS 7.0-8.9 (High) -> патч в течение 7 дней
+-- CVSS 4.0-6.9 (Medium) -> патч в следующем плановом релизе
+-- CVSS < 4.0 (Low) -> в бэклог
3. Патчинг:
+-- Обновить базовый образ в Dockerfile
+-- Обновить зависимости (Maven/Gradle)
+-- Прогнать полный набор тестов (unit, integration, e2e)
+-- Сканировать новый образ на уязвимости
+-- Деплой через стандартный CI/CD пайплайн
4. Верификация:
+-- Повторное сканирование после деплоя (подтверждение устранения CVE)
+-- Мониторинг стабильности сервиса в течение контрольного периода
SLA по патчингу (24 часа для Critical, 7 дней для High) — типичное требование PCI DSS и внутренних политик безопасности банков. Каждое исключение из SLA должно быть задокументировано с обоснованием и планом устранения.
5. Пересборка образов по расписанию:
Пример
# GitHub Actions: еженедельная пересборка для актуализации базового образа
name: Weekly Rebuild
on:
schedule:
- cron: '0 2 * * 1' # Каждый понедельник в 2:00 UTC
workflow_dispatch: {} # Возможность ручного запуска
jobs:
rebuild:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build with latest base image
run: docker build --pull --no-cache -t banking-service:weekly .
- name: Scan
run: trivy image --exit-code 1 --severity CRITICAL banking-service:weekly
- name: Push if clean
run: docker push registry.bank.local/banking-service:weekly
Флаг --pull гарантирует, что Docker скачает свежую версию базового образа, а не использует локальный кэш. Флаг --no-cache отключает кэш слоёв, обеспечивая полную пересборку. В результате все пакеты ОС и зависимости будут обновлены до последних доступных версий.