fix(ci,ecommerce): escanear el manifiesto renderizado y endurecer readOnlyRootFilesystem del frontend
- Trivy IaC escaneaba solo el patch aislado de Kustomize (workloads/ecommerce/frontend/patches/deployment.yaml), no lo que realmente corre en el clúster. Eso generaba falsos positivos en todo lo heredado del base remoto de platform-templates (runAsNonRoot, seccompProfile) porque el patch nunca los repite. Se instala kubectl, se renderiza el kustomization completo y se escanea ese output. - readOnlyRootFilesystem pasa de false a true en el contenedor del frontend: revisando next.config.ts (optimización de imágenes) y app/api/revalidate/route.ts (revalidateTag sin cache handler custom), la imagen sí escribe a ./.next/cache en runtime. Se agregan volúmenes emptyDir para .next/cache y /tmp.
This commit is contained in:
1 parent
3147cafaff
commit
2670727cfa
2 files changed
+50
-2
No files matched your search
@@ -127,6 +127,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
APP_DIR: workloads/ecommerce
|
APP_DIR: workloads/ecommerce
|
||||||
MANIFEST_FILE: workloads/ecommerce/frontend/patches/deployment.yaml
|
MANIFEST_FILE: workloads/ecommerce/frontend/patches/deployment.yaml
|
||||||
|
KUSTOMIZE_DIR: workloads/ecommerce/frontend
|
||||||
IMAGE_NAME: gitea.cruzcloud.net/devops/ecommerce-frontend
|
IMAGE_NAME: gitea.cruzcloud.net/devops/ecommerce-frontend
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -276,6 +277,32 @@ jobs:
|
|||||||
chmod +x /tmp/trivy
|
chmod +x /tmp/trivy
|
||||||
/tmp/trivy version
|
/tmp/trivy version
|
||||||
|
|
||||||
|
- name: Instalar kubectl
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
KUBECTL_VERSION="v1.31.2"
|
||||||
|
curl -sSfL \
|
||||||
|
"https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" \
|
||||||
|
-o /tmp/kubectl
|
||||||
|
chmod +x /tmp/kubectl
|
||||||
|
/tmp/kubectl version --client
|
||||||
|
|
||||||
|
# ${MANIFEST_FILE} es solo el patch de Kustomize del Deployment, no el
|
||||||
|
# manifiesto que de verdad corre en el clúster -- escanearlo directo
|
||||||
|
# generaba falsos positivos en todo lo que hereda del base remoto de
|
||||||
|
# platform-templates (runAsNonRoot, seccompProfile), porque ese patch
|
||||||
|
# nunca repite lo que ya trae el base (visto en vivo 2026-08-24:
|
||||||
|
# comparando el patch aislado contra el output real de
|
||||||
|
# "kubectl kustomize", 2 de 5 hallazgos desaparecían). Renderizamos el
|
||||||
|
# kustomization completo (${KUSTOMIZE_DIR}, que sí trae el base vía
|
||||||
|
# git remoto) y escaneamos eso.
|
||||||
|
- name: Renderizar manifiesto Kustomize
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
/tmp/kubectl kustomize "${KUSTOMIZE_DIR}" > /tmp/frontend-rendered.yaml
|
||||||
|
|
||||||
# Escanea el manifiesto Kubernetes real del frontend (no la imagen):
|
# Escanea el manifiesto Kubernetes real del frontend (no la imagen):
|
||||||
# contenedores como root, falta de resource limits, falta de
|
# contenedores como root, falta de resource limits, falta de
|
||||||
# readiness/liveness probes, etc. Informativo por ahora — no bloquea
|
# readiness/liveness probes, etc. Informativo por ahora — no bloquea
|
||||||
@@ -287,7 +314,7 @@ jobs:
|
|||||||
/tmp/trivy config \
|
/tmp/trivy config \
|
||||||
--severity CRITICAL,HIGH,MEDIUM \
|
--severity CRITICAL,HIGH,MEDIUM \
|
||||||
--exit-code 0 \
|
--exit-code 0 \
|
||||||
"${MANIFEST_FILE}"
|
/tmp/frontend-rendered.yaml
|
||||||
|
|
||||||
# Instalado directo con pip (no como container aparte): el runner de
|
# Instalado directo con pip (no como container aparte): el runner de
|
||||||
# Gitea ejecuta cada job ya dentro de un contenedor propio que habla
|
# Gitea ejecuta cada job ya dentro de un contenedor propio que habla
|
||||||
|
|||||||
@@ -64,9 +64,20 @@ spec:
|
|||||||
# binario de node para esto, pero eso solo funciona si el
|
# binario de node para esto, pero eso solo funciona si el
|
||||||
# bounding set del contenedor lo permite -- drop: ALL del base
|
# bounding set del contenedor lo permite -- drop: ALL del base
|
||||||
# lo bloquea igual, root o no root. Mismo motivo que docs-portal.
|
# lo bloquea igual, root o no root. Mismo motivo que docs-portal.
|
||||||
|
#
|
||||||
|
# readOnlyRootFilesystem: true -- revisado en código (2026-08-24,
|
||||||
|
# aún no probado en vivo con este cambio) que esta imagen sí
|
||||||
|
# escribe a disco en runtime, no solo en build: el servidor
|
||||||
|
# standalone de Next.js cachea a ./.next/cache tanto el
|
||||||
|
# optimizador de imágenes (next.config.ts trae remotePatterns,
|
||||||
|
# sin "unoptimized: true") como el revalidateTag("medusa-products")
|
||||||
|
# de app/api/revalidate/route.ts (cache handler por default, sin
|
||||||
|
# uno custom tipo Redis). De ahí los dos volumeMounts de abajo:
|
||||||
|
# sin ellos, con root filesystem de solo lectura, ambas rutas
|
||||||
|
# fallarían al intentar escribir.
|
||||||
securityContext:
|
securityContext:
|
||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
readOnlyRootFilesystem: false
|
readOnlyRootFilesystem: true
|
||||||
capabilities:
|
capabilities:
|
||||||
drop:
|
drop:
|
||||||
- ALL
|
- ALL
|
||||||
@@ -79,3 +90,13 @@ spec:
|
|||||||
limits:
|
limits:
|
||||||
cpu: "1"
|
cpu: "1"
|
||||||
memory: 768Mi
|
memory: 768Mi
|
||||||
|
volumeMounts:
|
||||||
|
- name: next-cache
|
||||||
|
mountPath: /app/.next/cache
|
||||||
|
- name: tmp
|
||||||
|
mountPath: /tmp
|
||||||
|
volumes:
|
||||||
|
- name: next-cache
|
||||||
|
emptyDir: {}
|
||||||
|
- name: tmp
|
||||||
|
emptyDir: {}
|
||||||
Reference in new issue
Block a user