Saltar a contenido

Configurar Certificado SSL Corporativo

Esta guía muestra cómo configurar certificados SSL en entornos con un proxy de inspección SSL (SSL Inspection / MITM), cubriendo aplicaciones Java (Wizard, BotRunner, BotStudio) y Python (requests).

Contexto

Los entornos corporativos con SSL Inspection (proxy MITM) interceptan las conexiones HTTPS y reemplazan el certificado original del servidor por uno emitido por una CA interna de la empresa. Esto hace que las aplicaciones Java y Python rechacen la conexión, ya que no reconocen esa CA.

Este comportamiento suele resultar en errores de SSL al usar herramientas como el BotCity Runner, normalmente algo como PKIX path building failed o unable to find valid certification path to requested target.

Una posible solución para este escenario es registrar el certificado raíz de la CA interna en los truststores de cada tecnología.

Requisitos previos

  • Certificado raíz de la CA interna de la empresa (archivo .crt, .cer o .pem), proporcionado por el equipo de infraestructura/seguridad.

    Si necesita extraerlo, puede usar el navegador: acceda al servidor de destino desde la máquina corporativa, haga clic en el candado, exporte la cadena de certificados e identifique el certificado raíz (el que está en la parte superior de la cadena y es autofirmado).

  • Java (JDK/JRE) utilizado para ejecutar las aplicaciones.

    En este caso, es necesario saber qué Java se está utilizando para ejecutar las herramientas (Runner): si es el Java incluido en la instalación del SDK o el Java de la instalación del sistema.

  • Python con el paquete certifi instalado (pip install --upgrade certifi).

Configuración para Java

1. Identificar el cacerts de la JVM

El cacerts es el truststore predeterminado de Java. Su ubicación depende de la versión y del Java que se esté utilizando:

# cacerts en Java 9+
# $JAVA_HOME\lib\security\cacerts

# cacerts en Java 8
# $JAVA_HOME\jre\lib\security\cacerts

# Comando que puede ayudar a identificar el Java instalado
# java -version

Si el Java usado para ejecutar las herramientas es el incluido en el BotCity Studio SDK, la ruta al archivo cacerts debería ser algo como:

"<BOTCITY_SDK_PATH>\win32\java\lib\security\cacerts"

Confirme que el archivo existe:

Test-Path "<PATH_JAVA>\lib\security\cacerts"

2. Listar los certificados existentes (opcional)

keytool es una herramienta que ya viene con el JDK y se encuentra en <PATH_JAVA>\bin\keytool.exe. Es esta herramienta la que se usará en las operaciones con el certificado.

# Para facilitar las llamadas, abra una terminal en el directorio "<PATH_JAVA>\bin"
.\keytool.exe -list -keystore "<PATH_JAVA>\lib\security\cacerts" -storepass changeit

Este comando debe devolver la lista de los certificados predeterminados existentes.

3. Importar el certificado

Con el archivo del certificado de la empresa en mano, podemos usar keytool para importarlo al archivo cacerts. También es posible definir un alias para facilitar la identificación del certificado importado más adelante.

.\keytool.exe -importcert -alias ca-interna-empresa -file "C:\certs\ca-raiz-empresa.crt" -keystore "<PATH_JAVA>\lib\security\cacerts" -storepass changeit -noprompt

Nota

La contraseña predeterminada del cacerts es changeit. Use un alias descriptivo para facilitar la identificación futura. Si hay certificados intermedios, importe cada uno con un alias diferente.

4. Verificar la importación

.\keytool.exe -list -keystore "<PATH_JAVA>\lib\security\cacerts" -storepass changeit -alias ca-interna-empresa

La salida debe mostrar el alias, la fecha de creación y el tipo de certificado.

5. Reiniciar la aplicación Java

La JVM carga el truststore al iniciarse, por lo que es necesario reiniciar el proceso para que el nuevo certificado sea reconocido.

Configuración para Python (requests / certifi)

La biblioteca requests no usa el truststore del sistema operativo ni el cacerts de Java. Depende del paquete certifi, que trae su propio conjunto de CAs confiables (un archivo cacert.pem).

1. Localizar el paquete de certifi

python -c "import certifi; print(certifi.where())"

Anote la ruta devuelta (por ejemplo, C:\Users\usuario\AppData\...\certifi\cacert.pem).

2. Crear el paquete personalizado

Copie el paquete original y agregue el certificado de la CA interna al final:

# Crea el directorio de destino (si no existe)
New-Item -ItemType Directory -Path "C:\Users\<user>\Documents\Certs" -Force

# Copia el paquete original de certifi
Copy-Item -Path (python -c "import certifi; print(certifi.where())") -Destination "C:\Users\<user>\Documents\Certs\ca-bundle-empresa.pem" -Force

# Agrega el certificado raíz de la CA interna al final del paquete
Add-Content -Path "C:\Users\<user>\Documents\Certs\ca-bundle-empresa.pem" -Value ""
Get-Content -Path "C:\certs\ca-raiz-empresa.crt" | Add-Content -Path "C:\Users\<user>\Documents\Certs\ca-bundle-empresa.pem"

3. Configurar la variable de entorno

Opción A: solo para la sesión actual (prueba rápida)

$env:REQUESTS_CA_BUNDLE = "C:\Users\<user>\Documents\Certs\ca-bundle-empresa.pem"

Opción B: persistente para el usuario actual

[System.Environment]::SetEnvironmentVariable("REQUESTS_CA_BUNDLE", "C:\Users\<user>\Documents\Certs\ca-bundle-empresa.pem", "User")

Opción C: persistente para toda la máquina (requiere PowerShell como Admin)

[System.Environment]::SetEnvironmentVariable("REQUESTS_CA_BUNDLE", "C:\Users\<user>\Documents\Certs\ca-bundle-empresa.pem", "Machine")

Consejo

Si otros scripts o bibliotecas además de requests también necesitan confiar en la CA interna (por ejemplo, httpx, urllib3), configure también la variable SSL_CERT_FILE con la misma ruta, siguiendo el mismo procedimiento anterior.

4. Verificar la configuración

Abra una nueva terminal (para que se cargue la variable persistente) y pruebe:

# Confirma que la variable está definida
echo $env:REQUESTS_CA_BUNDLE

# Prueba la conexión
python -c "import requests; r = requests.get('https://developers.botcity.dev/api/v2/maestro/version'); print(r.status_code)"

5. Entornos virtuales

La variable REQUESTS_CA_BUNDLE sobrescribe el comportamiento predeterminado de requests, que sería consultar el certifi instalado en el venv activo. Con la variable definida, requests ignora certifi y usa directamente el archivo indicado, por lo que funciona para cualquier venv sin necesidad de configuración adicional por entorno.

Mantenimiento

Actualización de certifi

Cuando el paquete certifi se actualiza mediante pip, el paquete personalizado no se actualiza automáticamente (es una copia estática). Para recrearlo, basta con repetir los pasos 2 y 3 de la sección anterior.

Eliminación del certificado Java (si es necesario)

keytool -delete -keystore "<JAVA_PATH>\lib\security\cacerts" -storepass changeit -alias ca-interna-empresa

Eliminación de las variables de entorno de Python (si es necesario)

# Elimina del ámbito del usuario
[System.Environment]::SetEnvironmentVariable("REQUESTS_CA_BUNDLE", $null, "User")

# O del ámbito de la máquina (requiere Admin)
[System.Environment]::SetEnvironmentVariable("REQUESTS_CA_BUNDLE", $null, "Machine")

Solución de problemas

Java: PKIX path building failed / unable to find valid certification path

  • Verifique que JAVA_HOME apunte a la JVM correcta que usa la aplicación.
  • Confirme que el certificado importado sea el raíz (y no uno intermedio).
  • Verifique si la aplicación usa un truststore personalizado mediante -Djavax.net.ssl.trustStore. En ese caso, importe el certificado en ese truststore, no en el cacerts global.

Python: SSLCertVerifyError / CERTIFICATE_VERIFY_FAILED

  • Confirme que la variable REQUESTS_CA_BUNDLE esté definida en la terminal donde se ejecuta el script (echo $env:REQUESTS_CA_BUNDLE).
  • Verifique que el archivo .pem contenga tanto las CAs de certifi como el certificado de la CA interna.
  • Si el error persiste, pruebe con verify explícito para aislar el problema:
import requests
r = requests.get("https://su-servidor.com", verify=r"C:\certs\ca-bundle-empresa.pem")
print(r.status_code)

Resumen

Etapa Java Python
Truststore cacerts (JKS) certifi (PEM)
Herramienta keytool Copia + concatenación de PEM
Comando de importación keytool -importcert ... Copy-Item + Add-Content
Variable de entorno javax.net.ssl.trustStore (si hay truststore personalizado) REQUESTS_CA_BUNDLE o SSL_CERT_FILE
Reinicio necesario Sí (JVM) Nueva terminal

Nota

Reemplace las rutas de ejemplo (como C:\certs\...) y el alias del certificado por los valores reales del entorno del cliente.