Superpipeline DevSecOps con IA
Un pipeline que predice fallos y ofrece soluciones, totalmente local y de código abierto con SAST y DAST. Primera parte.

En el mundo del desarrollo moderno, la seguridad no puede ser una idea tardía. Los equipos enfrentan el desafío constante de mantener la velocidad de desarrollo sin comprometer la seguridad de sus aplicaciones. Este artículo documenta la construcción de un pipeline DevSecOps completo que integra seguridad automatizada, análisis con IA y visibilidad centralizada.
El Desafío
Como profesional de ciberseguridad, me enfrenté a varios problemas comunes en equipos de desarrollo:
Secretos hardcodeados que terminan en producción
Vulnerabilidades en dependencias que pasan desapercibidas
Código inseguro que se detecta demasiado tarde
Falta de visibilidad sobre el estado de seguridad real
Errores de pipeline sin contexto ni soluciones claras
La pregunta era: ¿Cómo podemos hacer que la seguridad sea automática, informativa y no obstructiva La Solución: Un Pipeline DevSecOps con IA
Construí un pipeline completo que combina:
GitLab CI/CD para orquestación
4 herramientas de seguridad (Bandit, Safety, GitLeaks, Trivy)
DefectDojo para gestión de vulnerabilidades
n8n para automatización inteligente
Ollama (Mistral 7B) para análisis de errores con IA
Slack para notificaciones contextuales
Kubernetes (k3s) para deployment
Cloudflare Tunnel para exposición segura
Vamos a descargar el repositorio que tengo los archivos ahi. Primero echamos a correr nuestro docker compose, para levantar el stack.
❯ sudo git clone https://github.com/safernandez666/devsecopsia.git
Clonando en 'devsecopsia'...
remote: Enumerating objects: 29, done.
remote: Counting objects: 100% (29/29), done.
remote: Compressing objects: 100% (23/23), done.
remote: Total 29 (delta 6), reused 27 (delta 4), pack-reused 0 (from 0)
Recibiendo objetos: 100% (29/29), 16.45 KiB | 1.10 MiB/s, listo.
Resolviendo deltas: 100% (6/6), listo.
Vamos a echarlo a correr.
docker compose up
Kubernetes
Como pueden ver, tenemos k3s como nodo de Kubernetes. Se generará una carpeta llamada k3s-kubeconfig. Lo primero que haremos es configurarla para poder gestionarla mediante kubectl.
export KUBECONFIG=/Users/santiago/Proyects/devsecopsia/k3s-kubeconfig/kubeconfig.yaml

Nuestro clúster está en funcionamiento. Vamos a desplegar manualmente nuestra aplicación usando kubectl apply -f k8s/.

¡Listo! Nuestra aplicación está funcionando.

Sigamos con los demás componentes.
Gitlab
Vamos a iniciar sesión en http://localhost:8000 con el usuario: root y la contraseña: changeme123.
Outbound
Una vez dentro, configuraremos algunos elementos específicos, como el Outbound para habilitar las integraciones.

Proyecto
Ahora vamos a crear el proyecto y subir el código.

# Eliminamos .git
sudo rm -R .git
git init --initial-branch=master
git remote add origin http://localhost:8000/root/python-application.git
git add .
git commit -m "Initial commit"
git push --set-upstream origin master
Listo! Tenemos nuestro proyecto en Gitlab.

Webook
Una vez generado el proyecto vamos a crear el Webhook que hablara con N8N cada vez que hay un evento en el pipeline. Tenemos que tildar Pipeline events para la PoC vamos a deshabilitar el SSL y la ruta sera del Webhook sera http://n8n:5678/webhook/gitlab-ai.

Registrar Runner
Vamos a registrar el runner que se encargará de ejecutar nuestro proyecto. Para ello nos vamos a meter dentro del docker gitlab-runner y ejecutar algunos comandos. Previo a eso necesitamos un token. Ingresamos al docker con:
docker exec -it gitlab-runner sh
Ahí aplicamos el comando que nos da Gitlab.

Vamos a editar el config.toml de runner.
docker exec -it gitlab-runner vi /etc/gitlab-runner/config.toml
Deberia quedar asi:
concurrent = 1
check_interval = 0
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "docker-desktop"
url = "http://localhost:8000"
id = 1
token = "glrt-GWHqJu72JQo3xR1-1okEwW86MQp0OjEKdToxCw.01.1215lwx2d"
token_obtained_at = 2025-11-14T21:15:44Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
[runners.cache]
MaxUploadedArchiveSize = 0
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "alpine-latest"
privileged = false
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
shm_size = 0
network_mode = "host"
network_mtu = 0
Listo, solo queda reiniciarlo con un docker restart gitlab-runner. Tenemos el runner en linea y listo para funcionar.

Más adelante, deberás agregar la variable de Defect Dojo y la configuración de Kubernetes. Aquí tienes una imagen de ejemplo.

Defect Dojo
Vamos a reunir todos nuestros hallazgos en esta plataforma. Una vez que esté en funcionamiento, la configuraremos para que esté operativa y podamos extraer la API Key que necesitamos para nuestro CI en Gitlab.
# Inicializar la base de datos de DefectDojo
docker exec -it defectdojo-uwsgi ./manage.py migrate
# Crear el superusuario (admin/admin123)
docker exec -it defectdojo-uwsgi ./manage.py createsuperuser --noinput --username admin --email admin@defectdojo.local
# Cambiar la password del admin
docker exec -it defectdojo-uwsgi python manage.py shell << EOF
from django.contrib.auth import get_user_model
User = get_user_model()
user = User.objects.get(username='admin')
user.set_password('admin123')
user.save()
EOF
# Reiniciar los servicios
docker restart defectdojo-uwsgi defectdojo-nginx
Generamos la API Key una vez que hicimos el Sign In.

La copiamos y luego la agregamos como variable en CI/CD bajo el nombre de DEFECTDOJO_API_KEY.
N8N
Importamos el proyecto y rellenamos lo que nos falta. Por un lado es el Token del Bot de Slack, en internet vas a encontrar como sacarlo, y por el otro un PRIVATE-TOKEN.


Pipeline
Vamos a correr el pipeline. Hacemos un cambio y hacemos el push.

Slack nos avisa, que tenemos que hacer. Le damos play al deploy-k3s. Listo, ya esta corriendo nuestro deployment.

Vemos como se despliega.

El mensaje de Slack donde se ejecuto el pipeline numero #96.

Ya estamos productivos.

Generación de Errores
Ahora que el pipeline está listo, es momento de probar qué sucede si encuentra algo. Para esto, voy a crear un archivo con contraseñas para que gitleaks lo detecte y lo pase a Ollama para el análisis.
# Crear un archivo con un secreto
cat > app/config.py << 'EOF'
# Configuración de la aplicación
import os
# NUNCA hagas esto en producción
AWS_ACCESS_KEY = "AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
DATABASE_PASSWORD = "super_secret_password_123"
# Configuración de la base de datos
DB_CONFIG = {
"host": "localhost",
"port": 5432,
"username": "admin",
"password": "admin123456", # Contraseña hardcodeada
"database": "production_db"
}
EOF
Hacemos el commit.
# Commit
git add app/config.py
git commit -m "Change with Leaks"
git push
Aquí vemos el error y el análisis de Ollama. Si todo funciona correctamente, el Job de Bandit y GitLeaks encontrará problemas, lo que hará que el Security Gate falle.

Esto activará el Webhook a N8N para que Ollama lo analice y nos notifique por Slack. Recibimos el mensaje con el análisis realizado por la LLM. Es genial para saber dónde están los errores.

Mientras tanto en Defect Dojo, tenemos una manera de visualizar los hallazgos.

Espero que hayan disfrutado del proceso y puedan implementar IA en sus entornos. Seguiremos explorando esto, añadiendo OWASP ZAP y algunas otras cosas para interactuar con Slack.



