7abff8f73f
Три прямых фикса по /cso security audit на v2.45.2: ## Finding #1 (HIGH): Backend containers run as root ordinis-app / ordinis-read-api / ordinis-projection-writer Dockerfile'ы запускали JVM от root (eclipse-temurin:21-jre default'но не задаёт USER). Compromise через Spring CVE / Jackson deserialization → root-в-контейнере = escalation surface на ноду через любой pod misconfig. Добавлено: `RUN groupadd -r -g 10001 app && useradd -r -u 10001 -g app -s /sbin/nologin app` + `USER app`. UID 10001 — outside system (0-999) и distribution reserved (1000-9999). `--chown=app:app` на COPY чтобы JVM могла прочитать jar. ordinis-migrations (USER liquibase) и docs (nginx default) уже non-root. ## Finding #2 (HIGH): .env / .env.local not in .gitignore `.gitignore` блокировал *.pem, *.key, .gstack/, .claude/ — но не .env. Развработчик с realный dotenv для local dev мог случайно `git add .` и закоммитить creds. Сейчас нет committed .env (verified) но защита нулевая. Добавлено: `.env`, `.env.local`, `.env.*.local`, `*.env` + whitelist `!.env.example`, `!.env.template`, `!.env.sample` для шаблонов. Существующий tracked `ordinis-admin-ui/.env.example` остался tracked (verified `git ls-files | grep .env.example`). ## Finding #3 (MEDIUM): Spring Actuator permitAll() — defense-in-depth gap SecurityConfig had `requestMatchers("/actuator/**").permitAll()` → любой pod в кластере мог `curl ordinis-app:8080/actuator/env` и получить ORDINIS_KEYCLOAK_ADMIN_CLIENT_SECRET, DB creds и пр. VERIFIED: nginx ingress на проде НЕ проксирует /actuator/* (SPA fallback отдаёт index.html), так что не exposed на интернет. Но pod-to-pod в кластере = открыто. Defense in two layers: 1. SecurityConfig: split actuator routes — /actuator/health/**, /actuator/info, /actuator/prometheus → permitAll /actuator/** → denyAll Probes/Prometheus scrape работают, остальное блок. 2. application.yml для всех трёх Spring apps: narrowed default exposure to "health,info,prometheus". Поддерживается env override MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE для staging diagnostic (включить env/configprops/loggers только когда нужно дебажить autoconfig). ## Тесты - mvn package — все 15 модулей SUCCESS - ordinis-rest-api + ordinis-auth tests — SUCCESS ## Manual verify post-deploy После пророллится v2.45.3: - staging+prod liveness/readiness probes должны остаться зелёными (/actuator/health/{liveness,readiness} в permitAll list). - Prometheus scrape /actuator/prometheus → 200. - ssh pod && curl localhost:8080/actuator/env → должен вернуть 401/403 (или 404 если endpoint вообще выключен через exposure). ## Откат Если probes сломаются (маловероятно — health endpoints whitelisted) — revert этого MR. Image rollback к v2.45.2 через helm.
44 lines
2.4 KiB
Docker
44 lines
2.4 KiB
Docker
# Multi-stage build для ordinis-app.
|
||
#
|
||
# COPY . ./ + root .dockerignore: один rule вместо explicit per-module
|
||
# list. Когда добавляется новый Maven module в parent pom.xml — Docker
|
||
# build автоматически его подхватит, без правки этого файла. Lesson из
|
||
# Phase A (notifications module): explicit COPY list пропускал новый
|
||
# module → `mvn -am package` падал на parent pom validation.
|
||
#
|
||
# .dockerignore исключает frontend (admin-ui), bench, docs, target/, .git/,
|
||
# IDE metadata — backend image остаётся компактным.
|
||
FROM repo.nstart.cloud/library/maven:3.9.9-eclipse-temurin-21 AS build
|
||
# Git info из CI environment (`.gitlab-ci.yml` `--build-arg`) — нужен для
|
||
# Spring Boot build-info goal через ordinis-app/pom.xml. Внутри Docker
|
||
# context .git/ исключён (.dockerignore), поэтому git-commit-id-maven-plugin
|
||
# не может прочитать локально. Defaults в pom.xml gracefully fallback'ят
|
||
# если ARG'и не переданы (local docker build без ENV).
|
||
ARG GIT_COMMIT=unknown
|
||
ARG GIT_BRANCH=unknown
|
||
# GIT_TAG defaults to "none" (не пусто): Maven property substitution трактует
|
||
# empty value как null → Spring Boot build-info goal валится с
|
||
# "Additional property 'tag' is illegal as its value is null".
|
||
ARG GIT_TAG=none
|
||
ARG GIT_TIME=unknown
|
||
WORKDIR /build
|
||
COPY . ./
|
||
RUN mvn -B -pl ordinis-app -am package -DskipTests \
|
||
-Dgit.commit.id.abbrev="$GIT_COMMIT" \
|
||
-Dgit.branch="$GIT_BRANCH" \
|
||
-Dgit.tags="$GIT_TAG" \
|
||
-Dgit.commit.time="$GIT_TIME"
|
||
|
||
FROM repo.nstart.cloud/library/eclipse-temurin:21-jre
|
||
# Non-root user — security hardening (CSO report 2026-05-27 finding #1).
|
||
# Eclipse-temurin runtime image не задаёт USER by default → JVM от root.
|
||
# Compromise через Spring Boot CVE / Jackson deserialization без USER
|
||
# становится root-в-контейнере → escalation surface на ноду. UID 10001
|
||
# не конфликтует с system users (0-999) и distribution-reserved (1000-9999).
|
||
RUN groupadd -r -g 10001 app && useradd -r -u 10001 -g app -s /sbin/nologin app
|
||
WORKDIR /app
|
||
COPY --from=build --chown=app:app /build/ordinis-app/target/*.jar /app/app.jar
|
||
USER app
|
||
EXPOSE 8080
|
||
ENTRYPOINT ["java", "-XX:+UseZGC", "-XX:MaxRAMPercentage=75", "-jar", "/app/app.jar"]
|