IT-Admin.tech

Asegurar los runners de CI/CD: aislamiento de credenciales, limpieza segura del workspace y protección de la cadena de compilación

Architekturdiagramm einer CI/CD-Pipeline mit Ephemeral-VM-Runnern, OIDC-Tokenflow, HSM-basiertem Signierdienst und...
Diagramm zeigt Trennung: Ephemeral Runner, internes Mirror, Artefakt-Repository und HSM/Signierdienst — so minimieren Sie Blast Radius bei kompromittierten Builds.

Asegurar los runners de CI/CD no es un truco de seguridad, sino una tarea operativa sostenible: los runners obtienen código fuente, generan artefactos y con frecuencia tienen acceso a credenciales, cachés y la red interna. Para administradores y operadores es crucial reducir la superficie de ataque de forma medible y disponer de rutas claras de verificación y reversión. Esta guía proporciona medidas concretas, pasos de comprobación y troubleshooting para el aislamiento de credenciales, una limpieza robusta del workspace y la protección de la cadena de build.

Por qué los runners son un vector de ataque crítico

Los runners son entornos de ejecución para jobs de CI/CD (builds, tests, packaging). Un runner comprometido puede:

  • Exfiltrar secretos (tokens, claves SSH, credenciales de cloud).
  • Alterar artefactos o firmarlos de forma manipulada.
  • Realizar cache-poisoning y así afectar builds posteriores.
  • Permitir pivoting hacia la red interna.

Distinción importante: trusted-Builds (p. ej. ramas protegidas o releases) frente a untrusted-Builds (forks, PRs externas, contribuciones públicas). Para los untrusted-Builds debe asumirse operativamente que el job es potencialmente malicioso.

Principios básicos: privilegios mínimos, aislamiento, trazabilidad

Endurezca la operación en torno a tres objetivos medibles:

  • Objetivo de aislamiento: Ningún job debe poder ver el estado de otro job.
  • Objetivo de credenciales: Los jobs reciben únicamente las credenciales mínimas necesarias, preferiblemente de corta duración.
  • Objetivo de integridad: La procedencia y la inmutabilidad de dependencias y artefactos deben ser trazables.

Estos objetivos se pueden operacionalizar, probar y auditar.

Aislamiento de credenciales: implementación, motivos y trampas típicas

Aislamiento de credenciales significa: nada de tokens estáticos de uso general. Segmenten identidades según la fase de la pipeline (build, package, release, deploy) y el contexto. Utilicen tokens efímeros (TTL en minutos/horas) vía OIDC, STS (Security Token Service) o leases de HashiCorp Vault. Las credenciales de corta duración limitan el blast radius en caso de compromiso y facilitan el revocado.

Opciones técnicas y su uso

OIDC (OpenID Connect) es un protocolo para emitir tokens efímeros; conecta sistemas de CI con Cloud-IAM o Vault sin secretos permanentes. KMS/HSM (Key Management Service / Hardware Security Module) almacena claves privadas fuera de los runners normales. Vault ofrece secretos dinámicos (p. ej. credenciales de bases de datos con leases). Cada opción exige requisitos operativos: OIDC precisa claims de token fiables; Vault requiere alta disponibilidad y políticas de acceso adecuadas.

Ejemplo: Vault-Policy para Package-Push

Hcl
# Vault policy (HCL) - erlaubt Token zum Schreiben in ein internes Artefakt-Repo
path "secret/data/ci/artifacts/*" {
  capabilities = ["create", "update", "read"]
}

Por qué funciona: Vault emite tokens con duración limitada, y la policy restringe los paths. Cuándo falla: cuando los runners persisten el token de Vault (p. ej. en caché) o las policies están definidas demasiado amplias.

Firmado limitado por políticas mediante un servicio de firma

Las claves privadas de firma no deben residir en runners normales. Un servicio de firma (un servicio interno que firma mediante KMS/HSM) recibe hashes de artefactos, verifica políticas (p. ej. que el build provenga de una rama protegida) y después realiza la firma. La operación de firma requiere logs de auditoría separados y una autenticación estricta.

Asegurar los runners de CI/CD: aislamiento a nivel de infraestructura

Seleccione el aislamiento en función del riesgo y la rentabilidad:

  • Host-Runner: Rápido, pero solo para trabajos plenamente confiables.
  • Container-Runner: Buen rendimiento, pero solo con rootless y políticas de montaje estrictas.
  • Ephemeral VM/Instance-Runner: Aislamiento máximo; por trabajo una VM nueva o un snapshot. Costes más altos, seguridad máxima.

Los Ephemeral-Runner son especialmente recomendables para builds no confiables: tras finalizar, la instancia se destruye para evitar persistencia.

Ejemplo: Kubernetes-Runner como Job efímero

Yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: runner-job-{{ .RunID }}
spec:
  template:
    spec:
      securityContext:
        runAsUser: 1000
        runAsGroup: 1000
        fsGroup: 1000
      containers:
      - name: builder
        image: registry.internal/runner-image:stable
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
      RESTartPolicy: Never
  backoffLimit: 0

Por qué ayuda: Kubernetes permite Namespaces, NetworkPolicies y contextos de seguridad de Pods para RESTringir. Atención: configuraciones erróneas de RBAC o de volúmenes pueden socavar el aislamiento.

Limpieza segura del workspace: robusta y resistente a manipulaciones

Una limpieza defectuosa permite persistencia. Los problemas surgen por handles abiertos, sistemas de archivos montados, trucos con symlinks y ACLs RESTrictivas. Una limpieza robusta implementa varias capas de protección: workspaces dedicados, normalización de ownership, –one-file-system al borrar y comprobaciones con registro de auditoría.

Linux: Limpieza ampliada incluyendo verificación de handles

Shell
#!/usr/bin/env bash
set -euo pipefail
JOB_DIR="$1"
RUNNER_UID=1001
RUNNER_GID=1001

# 1) Prozesse beenden, die in JOB_DIR arbeiten
fuser -k -TERM -m "$JOB_DIR" || true
sleep 1
fuser -k -KILL -m "$JOB_DIR" || true

# 2) Ownership und Rechte normalisieren
chown -R "${RUNNER_UID}:${RUNNER_GID}" "$JOB_DIR" 2>/dev/null || true
chmod -R u+rwX,go-rwx "$JOB_DIR" 2>/dev/null || true

# 3) Prüfen auf Mountpoints im Jobdir
mountpoints=$(findmnt -n -o TARGET --target "$JOB_DIR" || true)
if [ -n "$mountpoints" ]; then
  echo "Found mounts: $mountpoints" >&2
  # Option: detach mounts safely or warn and abort
fi

# 4) Löschen sicher durchführen
rm -rf --one-file-system "$JOB_DIR"

Por qué fuser es necesario: los handles de archivos abiertos impiden la eliminación; los procesos deben terminarse correctamente. El script puede fallar si un job ha iniciado procesos del sistema que el script no puede terminar—por eso el registro y los niveles de advertencia son importantes.

Windows: Handles, plan de reinicio e interacción con antivirus

En Windows son habituales los locks por servicios y AV. Complemente la limpieza con comprobaciones de handles (Sysinternals Handle/Process Explorer), reintentos y una ruta de reinicio planificada si la eliminación no es posible. Los simples reintentos no siempre bastan ante locks persistentes — documente una ruta de rollback.

Seguridad de la cadena de compilación: orígenes de paquetes, cachés y firma

Proteja la cadena de compilación mediante la separación de orígenes de paquetes, proxies con listas de permitidos, cachés controlados y políticas de artefactos inmutables.

Espejos internos y RESTricción de egress

Además de listas de permitidos para endpoints de paquetes, los runner deberían tener solo egress definido: VCS, mirror, repositorio de artefactos, KMS/servicio de firmado. Las ACLs de egress reducen las posibilidades de exfiltración/conexiones a infraestructura de Command-and-Control. Pruebe los cambios primero en modo monitor (solo registro) antes de bloquear.

Endurecimiento del repositorio de artefactos

Establezca Write-Policies (non-overwrite), políticas de retención y los flags require-signed-artifact cuando su repositorio lo soporte. Los audit-logs deben mostrar quién y cuándo publicó un artefacto. Regla de ejemplo: „Los releases solo pueden publicarse tras la firma por el servicio de firmado“.

Estrategias de caché contra el envenenamiento

Separe las cachés por zonas de confianza y por proyecto. Evite cachés compartidos con permisos de escritura para jobs no confiables. Utilice invalidación por TTL y hashes de caché registrados para detectar el envenenamiento.

Endurecimiento de red y host: medidas concretas

Trate los Runner como componentes de infraestructura crítica:

  • segmentos de red dedicados o VLANs
  • ACLs de egress definidas
  • firewall del host y proceso de parcheo
  • monitorización y registros centralizados

Ejemplo: regla iptables simple para egress (VM-Runner)

Shell
# Erlaube nur DNS, HTTP(S) zu mirror.example und signing.example
iptables -A OUTPUT -m owner --uid-owner runner -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d mirror.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d signing.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -j DROP

Por qué ayuda: incluso si un job intenta establecer comunicación maliciosa, el egress queda limitado. Atención: DNS-over-HTTPS y otros caminos de evasión pueden eludir esto — probar y monitorizar.

Pruebas, auditoría y validación

Valide las medidas mediante pruebas automatizadas y auditorías:

  • Jobs de auditoría periódicos que intenten realizar acciones no permitidas desde un Runner (¡solo en una red de prueba aislada!).
  • Auditorías post-job: comprobar restos en el workspace, descriptores abiertos y procesos activos.
  • Análisis de logs: buscar exfiltración de tokens o conexiones de egress inusuales.

Ejemplo de script de prueba: Post-Cleanup-Validation

Shell
#!/usr/bin/env bash
# Prüft, ob ein Job-Verzeichnis nach Cleanup noch existiert
JOB_DIR="$1"
if [ -e "$JOB_DIR" ]; then
  echo "CLEANUP FAILED: $JOB_DIR still exists" >&2
  ls -la "$JOB_DIR" >&2
  exit 2
fi
# Prüfe auf aktive Prozesse des Runner-User
if pgrep -u runner >/dev/null; then
  echo "ACTIVE PROCESSES FOUND" >&2
  ps -u runner -o pid,cmd
  exit 3
fi
exit 0

Errores típicos y resolución de problemas

1) Secretos accidentalmente en el registro de compilación

Causa: prints de depuración o falta de enmascaramiento. Medidas: activar el enmascaramiento de logs en CI, no exponer variables sensibles en texto plano. Automatice la comprobación de logs en busca de patrones (API-Keys, Bearer-Tokens) con un job scanner.

2) Contenedores privilegiados mal utilizados

Causa: contenedores privilegiados o montaje del socket de Docker. Medida: builds rootless, no montar sockets del host, uso de BuildKit/daemon remoto. Prueba: job intenta iniciar contenedores en el host (solo en entorno de pruebas!).

3) Claves de firma en Runner

Causa: practicidad en lugar de seguridad — los equipos almacenan claves localmente. Medida: centralizar los servicios de firma, mantener las claves solo en HSM/KMS. En caso de compromiso: rotación inmediata e invalide todas las claves potencialmente comprometidas.

Estrategia de rollback y emergencia

Introduzca los cambios de forma gradual:

  1. Modo monitor: solo registro, sin bloqueo.
  2. Cierre gradual de áreas de egress/política.
  3. Operación en paralelo de pools de Runner antiguos y nuevos; conmutación mediante feature-flag/ruta.
  4. Tokens break-glass para emergencias, de corta vida y con auditoría.

Importante: documente los pasos de reversión y pruébelos regularmente en una ejecución de prueba aislada.

Lista de verificación práctica: implementación en 90–180 minutos

  • Inventariar los tokens activos y verificar permisos para cada fase del pipeline.
  • Migrar trabajos no confiables a pools de runners separados o a VM efímeras.
  • Ampliar los scripts de limpieza: process-kill, chown, chmod, –one-file-system, validación posterior.
  • Auditar el proceso de firma y planificar el movimiento de claves a HSM/KMS.
  • Crear ACLs de egreso en modo de monitorización y observar el tráfico.
  • Trabajo de auditoría: intentar ejecutar desde el runner acciones no autorizadas (de forma aislada).

Conclusión

Asegurar los runners de CI/CD significa combinar practicidad con seguridad medible. Priorice la separación de credenciales por fase del pipeline (con tokens de corta duración), la limpieza garantizada del espacio de trabajo (o runners efímeros) y la firma mediante un servicio de firma o HSM/KMS. Complemente esto con RESTricciones de egreso, monitorización y pruebas de auditoría periódicas. Con una introducción por etapas, fases en modo de monitorización y rutas de retroceso probadas, la seguridad se mantiene manejable y operativamente segura.

FAQ

¿Cuál es el error más grave al asegurar los runners de CI/CD?

El error más frecuente es un token permanente y ampliamente autorizado para todas las fases del pipeline. Un trabajo comprometido obtiene así demasiado poder. Es preferible la separación por fase (Build, Package, Release, Deploy) y tokens de corta duración y ligados al contexto.

¿Es suficiente un contenedor como aislamiento para builds no confiables?

Un contenedor solo es suficiente si los privilegios, los mounts y la red están estrictamente RESTringidos. Son especialmente peligrosos los contenedores privilegiados o la exposición del socket de Docker. Para builds no confiables, las VM efímeras o los jobs de Kubernetes fuertemente aislados son más robustos.

¿Cómo me aseguro de que la limpieza del espacio de trabajo realmente funcione?

Use espacios de trabajo dedicados por trabajo, normalice la propiedad y los permisos antes de eliminar y borre con –one-file-system. En Windows detenga los manejadores de proceso del usuario del trabajo y opere con reintentos. Auditorías automatizadas posteriores al trabajo verifican si quedan RESTos.

¿Por qué no debe residir la clave privada de firma en el runner?

Si la clave está en runners estándar, un trabajo comprometido puede firmar artefactos manipulados. Es mejor la firma mediante HSM/KMS o un servicio de firma separado que solo firme en contextos concretos y con políticas verificadas.

¿Cómo gestiono la pérdida de rendimiento por un aislamiento más estricto?

Separe las cachés por zonas de confianza y por proyectos, utilice mirrors internos e imágenes de runners con inicio en caliente (snapshots). Así mantiene el rendimiento sin asumir riesgos de cache poisoning.

¿Qué comprobaciones debe incluir un trabajo de auditoría para runners?

Los trabajos de auditoría deben intentar establecer conexiones de egreso no autorizadas, obtener acceso de escritura a otros espacios de trabajo, probar acceso a APIs de firma sin claims válidos y verificar que el post-limpieza no deje archivos ni procesos. Ejecute estas pruebas solo en entornos aislados.

Asegurar los runners de CI/CD: operación, monitorización e integración

Las medidas técnicas solo son tan buenas como su operación. Planifique el monitoreo, las métricas y las integraciones ya al introducir el endurecimiento de Runner, para que la seguridad sea repetible y medible.

Métricas y alertas importantes:

  • Cleanup-Failure-Rate: proporción de Jobs en los que la Post-Job‑Validation falló. Defina un umbral y active una alarma antes de que los déficits de limpieza conduzcan a persistencia.
  • Vault-Lease‑Errors y OIDC-Token‑Failures: señalan problemas con credenciales de corta duración o claims defectuosos.
  • Conexiones de egress inusuales por Runner-Pool: aumentos repentinos indican exfiltración o intentos de elusión.
  • Solicitudes de firma por hora y errores de firmado: las desviaciones pueden indicar pipelines comprometidas o fallos de política.

Notas de integración:

  • IAM/IdP: Integre el CI como cliente OAuth/OIDC en proveedores de identidad existentes (p. ej. AD, Okta). Así, la auditoría y el ciclo de vida de usuarios permanecen controlables de forma central.
  • Backends de secretos: utilice Vault/KMS de forma dinámica; automatice la renovación de leases y la rotación. Documente las rotaciones de emergencia y pruebe la ruta de revocación de claves.
  • Repositorio de artefactos: complemente las políticas de firmado con atestaciones (metadatos de compilación, SBOM). Eso hace que el origen sea verificable y facilita los análisis de incidentes.

Runbook y prácticas de contingencia:

  • Cree un runbook breve: pasos para aislar un Runner‑Pool, rotación de claves, interruptor de desactivación para el servicio de firmado y rollback a runners en warm‑standby.
  • Realice pruebas de caos periódicas en una zona de pruebas (Cleanup-Fail, Egress-Block) y evalúe los procesos operativos frente a SLAs concretos.

Conclusión: la operación y la integración no son pensamientos secundarios. Buenas métricas, rotación automatizada y runbooks coordinados hacen que la seguridad CI/CD sea robusta y manejable en el día a día.

Para este tema también son importantes la Supply-Chain-Security y la protección de la cadena de compilación. El artículo sitúa estos aspectos de forma comprensible y muestra en qué hay que centrarse en la operación diaria.