Problema

En muchas organizaciones la inspección de tráfico TLS forma parte de la estrategia de seguridad perimetral. Cuando se habilita, el dispositivo de inspección actúa como un MITM (Man‑In‑The‑Middle) y presenta un certificado firmado por una autoridad interna. Los desarrolladores, sin embargo, suelen ejecutar herramientas que confían en almacenes de certificados propios: pip, mvn, go, aws cli, sentry-cli, entre otros. Cada vez que la cadena de confianza no incluye la CA interna, la herramienta aborta con errores de validación. El síntoma típico es una cascada de fallos al descargar dependencias o al interactuar con APIs externas, obligando a los equipos a desactivar la inspección o a parchear manualmente cada cliente. En entornos con equipos pequeños que planean escalar, este proceso se vuelve insostenible.

Causa

  1. Almacenes de certificados aislados
    La mayoría de los runtimes y gestores de paquetes utilizan su propio almacén (por ejemplo, certifi en Python, cacerts.jar en Java). Añadir la CA interna al llavero del sistema operativo no los afecta.

  2. Validación estricta de hostname
    Herramientas como pip o aws cli verifican que el certificado coincida exactamente con el hostname del repositorio. Cuando la inspección genera un certificado con un CN genérico o con SAN que no incluye sub‑dominios dinámicos, la validación falla.

  3. Rotación frecuente de dominios de dependencias
    Los gestores de paquetes consultan múltiples dominios (pypi.org, maven central, npm registry, etc.). Mantener una lista blanca estática se vuelve inviable.

  4. Configuraciones de proxy inconsistentes
    Algunas herramientas respetan la variable HTTPS_PROXY, otras no, y otras requieren un archivo de configuración propio. La falta de un punto único de configuración genera desalineación.

  5. Política de revocación de certificados
    Si la CA interna emite certificados con CRL o OCSP y la herramienta no los verifica, el tráfico puede quedar sin inspección aunque el certificado sea aceptado, creando brechas de seguridad inesperadas.

Solución

Una estrategia robusta combina tres pilares:

1. Proxy interno de dependencias

Implementar un artifact proxy (por ejemplo, Nexus, Artifactory o un simple nginx con caché) que sirva como punto único de salida para todos los gestores de paquetes. El proxy se coloca detrás del dispositivo de inspección, por lo que sólo necesita confiar en la CA interna una vez. Los clientes configuran su herramienta para apuntar al proxy mediante variables de entorno o archivos de configuración estándar.

Ventajas:

  • Reducción drástica del número de dominios externos que atraviesan la inspección.
  • Cache local que acelera builds y reduce ancho de banda.
  • Control centralizado de certificados; basta con actualizar la CA del proxy.

2. Bundles de CA gestionados automáticamente

Crear un script de bootstrap que descargue la CA interna y la inserte en los almacenes de certificados más comunes. El script se ejecuta al iniciar la máquina de desarrollo (por ejemplo, como parte de brew install, apt-get, o en el Dockerfile). Un ejemplo sencillo para Python, Java y Go:

#!/usr/bin/env bash
CA_PEM="/usr/local/share/ca-internal/ca.pem"

# Python (certifi)
python - <<PY
import certifi, shutil, os
dest = certifi.where()
shutil.copyfile("$CA_PEM", dest)
PY

# Java (cacerts)
keytool -importcert -trustcacerts -noprompt -alias internal-ca -file "$CA_PEM" -keystore "$JAVA_HOME/lib/security/cacerts" -storepass changeit

# Go (default root store)
sudo cp "$CA_PEM" /usr/local/share/ca-certificates/internal-ca.crt
sudo update-ca-certificates

Este enfoque elimina la necesidad de variables por herramienta y garantiza que cualquier nuevo contenedor o VM tenga la CA disponible desde el arranque.

3. Política de TLS decryption selectiva

En lugar de desactivar la inspección a nivel global, definir reglas de bypass basadas en grupos de IP o en puertos usados exclusivamente por los proxies internos. La mayoría de los appliances SASE permiten crear políticas de “no decryption” para rangos de IP internos. Así, el tráfico entre los desarrolladores y el artifact proxy circula sin ser interceptado, mientras que el resto del tráfico sigue bajo inspección.

Cuándo aplicar esta solución

  • Síntomas: fallos de validación de certificado en múltiples herramientas, necesidad de desactivar la inspección para builds, alta carga de solicitudes a dominios externos.
  • Entornos: equipos de desarrollo que consumen paquetes de varios lenguajes, CI/CD que ejecuta builds en contenedores o VMs efímeras.
  • No aplica: cuando la organización ya utiliza un proxy de artefactos y la inspección está configurada para excluirlo; o cuando la política de seguridad prohíbe cualquier bypass de TLS.

Código

#!/usr/bin/env bash
# bootstrap-ca.sh – instala la CA interna en los almacenes más usados

set -euo pipefail

CA_URL="https://internal-ca.company.local/ca.pem"
CA_PEM="/tmp/ca-internal.pem"

curl -sSf "$CA_URL" -o "$CA_PEM"

# Python (certifi)
python - <<PY
import certifi, shutil, os, sys
dest = certifi.where()
shutil.copyfile(sys.argv[1], dest)
PY "$CA_PEM"

# Java (cacerts)
if [[ -n "${JAVA_HOME:-}" ]]; then
  keytool -importcert -trustcacerts -noprompt -alias internal-ca \
    -file "$CA_PEM" -keystore "$JAVA_HOME/lib/security/cacerts" -storepass changeit
fi

# Go (system store)
sudo cp "$CA_PEM" /usr/local/share/ca-certificates/internal-ca.crt
sudo update-ca-certificates

Verificación

  1. Python: python -c "import ssl, urllib.request; urllib.request.urlopen('https://pypi.org')" debe completarse sin SSLError.
  2. Java: mvn dependency:resolve debe descargar artefactos sin advertencias de certificado.
  3. AWS CLI: aws s3 ls debe listar buckets sin error de SSL.
  4. Proxy: curl -I https://artifacts.company.local debe devolver 200 OK y el certificado debe mostrar la CA interna al inspeccionarlo con openssl s_client -connect.

Si cualquiera de los pasos falla, revisar los logs del appliance SASE para confirmar que la regla de bypass está activa y que el bundle contiene la CA correcta.

Notas adicionales

  • Mantener la CA interna en un repositorio de configuración (GitOps) permite versionar cambios y desplegar el script de bootstrap mediante Ansible, Chef o Terraform.
  • Algunos lenguajes (Rust, .NET) usan el almacén del SO; en esos casos basta con añadir la CA al llavero del sistema (macOS Keychain, Windows Cert Store, Linux /etc/ssl/certs).
  • Evitar certificados con CN genérico; usar SAN que incluya todos los sub‑dominios que el proxy pueda servir para que la validación de hostname nunca falle.
  • Si la organización requiere inspección completa, considerar TLS termination en el proxy interno y reenviar tráfico ya desencriptado al appliance; aunque implica mayor superficie de ataque, permite mantener la inspección sin romper clientes.