Skip to content

feat: update readme #28

feat: update readme

feat: update readme #28

# Source: https://github.com/Josep-Andreu/segur_cloud/blob/main/build-and-push.yaml
name: Build and Push to Quay
on:
push:
branches:
- main
env:
FULL_IMAGE: quay.io/mguzman98/jboss_lab:v1.0.0
jobs:
build:
runs-on: ubuntu-latest
outputs:
full_image: quay.io/mguzman98/jboss_lab:v1.0.0
steps:
- name: 🧩 Checkout code
uses: actions/checkout@v4
- name: 🔧 Build container image
run: |
docker build -t ${{ env.FULL_IMAGE }} .
- name: 💾 Save image to tar
run: |
docker save ${{ env.FULL_IMAGE }} -o image.tar
- name: 📤 Upload image artifact
uses: actions/upload-artifact@v4
with:
name: docker-image
path: image.tar
retention-days: 1
scan:
runs-on: ubuntu-latest
needs: build
outputs:
needs_remediation: ${{ steps.check_vulns.outputs.needs_remediation }}
full_image: ${{ needs.build.outputs.full_image }}
steps:
- name: ⬇️ Download image artifact
uses: actions/download-artifact@v4
with:
name: docker-image
- name: 📦 Load image from tar
run: |
docker load -i image.tar
- name: 🔍 Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.FULL_IMAGE }}
severity: HIGH,CRITICAL
exit-code: 0
ignore-unfixed: true
# 🧾 Generate SBOM with Syft (syft-json format)
- name: 🧾 Generate SBOM (Syft)
run: |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$PWD":/work \
anchore/syft:latest "${{ env.FULL_IMAGE }}" -o syft-json > sbom.syft.json
test -s sbom.syft.json && echo "SBOM created: sbom.syft.json"
- name: 📤 Upload SBOM artifact
uses: actions/upload-artifact@v4
with:
name: sbom-syft-json
path: sbom.syft.json
if-no-files-found: error
retention-days: 14
# 🛡 Evaluate SBOM with Grype (fail build on HIGH or CRITICAL vulns)
- name: 🛡 Vulnerability scan (Grype on SBOM)
id: check_vulns
run: |
set +e
docker run --rm \
-v "$PWD":/work \
anchore/grype:latest /work/sbom.syft.json \
--fail-on high \
--only-fixed=false \
--add-cpes-if-none \
-o json > grype_report.json
# obtener salida de grype
docker run --rm \
-v "$PWD":/work \
anchore/grype:latest /work/sbom.syft.json \
--fail-on high,critical > /dev/null
GRYPE_EXIT_CODE=$?
# 3. Decisiones basadas en el código de salida
if [ $GRYPE_EXIT_CODE -ne 0 ]; then
echo "❌ VULNERABILIDADES CRÍTICAS/ALTAS ENCONTRADAS."
echo "needs_remediation=true" >> $GITHUB_OUTPUT
# --- LÓGICA DE GENERACIÓN DEL SCRIPT DE REMEDIACIÓN ---
# Aquí generamos el script que se usará en el siguiente Job
# (Se necesita el comando jq para extraer los parches del JSON. Necesitas JQ instalado en el runner.)
cat grype_report.json | jq -r '
.matches[] |
# Filtra por severidad (High/Critical) y por fix disponible
select(.vulnerability.severity == "High" or .vulnerability.severity == "Critical") |
select(.vulnerability.fix.versions | length > 0) |
{
name: .artifact.name,
fixedVersion: .vulnerability.fix.versions[0]
} |
# Genera el comando 'yum update' específico (asumiendo que estás en un sistema RPM)
"yum update " + .name + "-" + .fixedVersion + " -y"
' | sort -u > remediacion.sh
else
echo "✅ IMAGEN SEGURA. Lista para el push."
echo "needs_remediation=false" >> $GITHUB_OUTPUT
# Crea un archivo vacío si no hay nada que remediar
touch remediacion.sh
fi
- name: 📤 Subir Script de Remediación
uses: actions/upload-artifact@v4
with:
name: remediation-commands
path: remediacion.sh
retention-days: 1 # Se borra rápidamente ya que es un archivo temporal
remediate:
runs-on: ubuntu-latest
needs: scan # Depende del Job anterior
outputs:
final_remediated_tag: ${{ steps.fix_img.outputs.remediated_tag }}
if: needs.scan.outputs.needs_remediation == 'true'
env:
FULL_IMAGE: ${{ needs.scan.outputs.full_image }}
steps:
- name: ⬇️ Checkout del Código
uses: actions/checkout@v4
- name: ⬇️ Download remediation script
if: ${{ needs.scan.outputs.needs_remediation == 'true' }}
uses: actions/download-artifact@v4
with:
name: remediation-commands
- name: 🔨 Ruta Remediada (Aplicar Parche y Reconstruir)
id: fix_img
if: ${{ needs.scan.outputs.needs_remediation == 'true' }}
run: |
REMEDIATED_TAG="${{ env.FULL_IMAGE }}-remediated"
echo "Aplicando parches y reconstruyendo en ${REMEDIATED_TAG}..."
# ASUME QUE EL DOCKERFILE AHORA TIENE LA INSTRUCCIÓN:
# COPY remediacion.sh .
# RUN sh remediacion.sh && rm remediacion.sh
docker build -t $REMEDIATED_TAG .
# 💡 Paso 1: Guardar la imagen en un archivo .tar
docker save -o final_image.tar $REMEDIATED_TAG
echo "remediated_tag=$REMEDIATED_TAG" >> $GITHUB_OUTPUT
- name: 📤 Subir Imagen como Artifact
uses: actions/upload-artifact@v4
with:
name: final-docker-image
path: final_image.tar
retention-days: 1
push-sign:
runs-on: ubuntu-latest
# CRÍTICO: Depende de AMBOS jobs anteriores
needs: [scan, remediate]
# CRÍTICO: Se ejecuta si 'scan' pasó, incluso si 'remediate' fue skipped (failure() cubre skip)
if: success() || failure()
steps:
- name: ⬇️ Descargar Imagen Artifact
uses: actions/download-artifact@v4
with:
name: final-docker-image
- name: 📦 Cargar Imagen desde tar
run: |
docker load -i final_image.tar
- name: 🎯 Determinar la Imagen a Desplegar
id: determine_image
run: |
NEEDS_FIX="${{ needs.scan.outputs.needs_remediation }}"
if [ "$NEEDS_FIX" == "true" ]; then
# Si se remedió, usamos la etiqueta de salida del job 'remediate'
FINAL_TAG="${{ needs.remediate.outputs.final_remediated_tag }}"
echo "La imagen final es la remediada: $FINAL_TAG"
else
# Si NO se remedió, usamos la etiqueta original del job 'scan'
FINAL_TAG="${{ needs.scan.outputs.full_image }}"
echo "La imagen final es la original (segura): $FINAL_TAG"
fi
echo "FINAL_TAG=$FINAL_TAG" >> $GITHUB_ENV
- name: 🔑 Login to Quay.io
run: |
docker login quay.io -u "${{ secrets.QUAY_USER }}" -p "${{ secrets.QUAY_PASSWORD }}"
- name: 🚀 Push Imagen Final a Quay.io
run: |
docker push $FINAL_TAG
- name: Install cosign
run: |
curl -LO https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign-linux-amd64
sudo mv cosign-linux-amd64 /usr/local/bin/cosign
- name: Sign the image
env:
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
run: |
printf '%s' "$COSIGN_PRIVATE_KEY" > cosign.key
cosign sign --key cosign.key $FINAL_TAG
shred -u cosign.key || rm -f cosign.key