Envoy Gateway TLS y Seguridad: Configura HTTPS y Deja de Exponer tu API sin Protección
Hacer funcionar HTTP es solo el calentamiento. A menos que tu servicio viva en la Edad de Piedra, producción casi con certeza necesita HTTPS. Este post cubre los fundamentos de TLS para Envoy Gateway para que tus APIs dejen de correr en texto claro.
Cómo Funciona TLS en Gateway
El enfoque más común: terminar TLS en el listener del Gateway.
Esto significa:
- El cliente se conecta vía HTTPS
- El Gateway gestiona el handshake y el certificado
- El tráfico se reenvía a tu Service sin cifrar internamente
Un listener HTTPS básico luce así:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg
spec:
gatewayClassName: eg
listeners:
- name: http
protocol: HTTP
port: 80
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- kind: Secret
group: ""
name: example-certDos cosas importan aquí:
protocol: HTTPStls.mode: Terminate
Esto significa: TLS termina aquí, y el Gateway se encarga del certificado.
HTTPS + HTTPRoute vs TLSRoute: Cuál es la Diferencia
Esto es importante, porque mucha gente ve TLSRoute y enseguida pregunta:
"¿No es suficiente con un listener HTTPS? ¿Para qué necesitamos un TLSRoute separado?"
La diferencia está en si el Gateway termina TLS o no:
| Escenario | Combinación Habitual | Descripción |
|---|---|---|
| El Gateway termina TLS y luego aplica reglas HTTP | listener HTTPS + HTTPRoute |
El escenario más común para sitios web y APIs |
| El Gateway no descifra — enruta tráfico cifrado basándose solo en SNI | listener TLS + TLSRoute |
Escenario de TLS passthrough |
En otras palabras:
- Si quieres inspeccionar
path,header,methoden el Gateway, primero necesitas terminar TLS y luego usarHTTPRoute - Si quieres preservar el cifrado de extremo a extremo y no descifrar en el Gateway,
TLSRoutees el camino correcto
Ningún enfoque es "más avanzado" — lo importante es saber qué quieres: "terminar TLS y hacer routing L7," o "mantener el cifrado intacto y hacer routing basado en SNI."
Preparar el Secret del Certificado
Para entornos de prueba, un certificado autofirmado funciona bien. Los ejemplos oficiales usan exactamente esto:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 \
-subj '/O=example Inc./CN=example.com' \
-keyout example.com.key \
-out example.com.crt
openssl req -out www.example.com.csr -newkey rsa:2048 -nodes \
-keyout www.example.com.key \
-subj "/CN=www.example.com/O=example organization"
openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key \
-set_serial 0 -in www.example.com.csr -out www.example.com.crtGuarda el certificado y la clave como un Secret de Kubernetes:
kubectl create secret tls example-cert \
--key=www.example.com.key \
--cert=www.example.com.crtEl Gateway puede entonces referenciar este Secret mediante certificateRefs.
⚠️ Los certificados autofirmados son solo para pruebas. En producción, usa cert-manager o tu flujo de gestión de certificados existente. No lleves la configuración del demo directamente a producción — es como sobrevivir a base de fideos instantáneos: está bien de vez en cuando, pero no es sostenible a largo plazo.
Agregar un Listener HTTPS a un Gateway Existente
Si ya tienes un Gateway eg del post anterior, puedes parchearlo directamente:
kubectl patch gateway eg --type=json --patch '
- op: add
path: /spec/listeners/-
value:
name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- kind: Secret
group: ""
name: example-cert
'Verifica el estado:
kubectl get gateway/eg -o yamlSi el listener se ve saludable, prueba HTTPS:
curl -v -HHost:www.example.com \
--resolve "www.example.com:443:${GATEWAY_HOST}" \
--cacert example.com.crt \
https://www.example.com/getEste comando es excelente para validación local, especialmente cuando el DNS todavía no está configurado.
Un Gateway, Múltiples Dominios HTTPS
Si tienes múltiples dominios, agrega múltiples listeners HTTPS al mismo Gateway.
Por ejemplo, para agregar foo.example.com:
listeners:
- name: https-main
protocol: HTTPS
port: 443
hostname: www.example.com
tls:
mode: Terminate
certificateRefs:
- name: example-cert
- name: https-foo
protocol: HTTPS
port: 443
hostname: foo.example.com
tls:
mode: Terminate
certificateRefs:
- name: foo-certNo olvides actualizar el HTTPRoute correspondiente con el hostname correcto — de lo contrario, el listener puede estar escuchando, pero la ruta no sabe a dónde enviar el tráfico.
Modelo Mental para TLSRoute
Para TLS passthrough, piensa en TLSRoute así:
💡 El
apiVersionparaTLSRoutepuede variar dependiendo de qué versión de los CRDs de Gateway API tengas instalada. El ejemplo a continuación es solo para ilustración conceptual — verifica la versión instalada en tu clúster antes de aplicarlo.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg-tls
spec:
gatewayClassName: eg
listeners:
- name: tls
protocol: TLS
port: 443
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: passthrough-route
spec:
parentRefs:
- name: eg-tls
hostnames:
- "db.example.com"
rules:
- backendRefs:
- name: db-service
port: 5432Casos de uso comunes para este patrón:
- Routing basado únicamente en el hostname SNI
- Preservar el cifrado hasta el backend
- Sin análisis de path o headers HTTP en el Gateway
Así que la mayor diferencia entre TLSRoute y HTTPRoute no es solo el nombre — operan en capas de tráfico completamente distintas.
Referencias de Certificados Entre Namespaces
La documentación oficial destaca una capacidad útil:
Un Gateway puede referenciar Secrets de certificados de otros namespaces — pero requiere un ReferenceGrant.
Por ejemplo, si el equipo de plataforma almacena los certificados de forma centralizada en envoy-gateway-system, pero el Gateway de la aplicación está en default, no puedes simplemente referenciar entre namespaces sin autorización explícita.
Ejemplo:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-default-to-read-cert
namespace: envoy-gateway-system
spec:
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: default
to:
- group: ""
kind: SecretEsto significa:
- Un
Gatewayen el namespacedefault - Está autorizado a referenciar recursos
Secretenenvoy-gateway-system
Sin un ReferenceGrant, esta referencia entre namespaces se trata como inválida. Es un mecanismo de protección — no Gateway API siendo innecesariamente estricta.
Resumen en Una Línea
TLS en Envoy Gateway no es tan misterioso como suena: prepara el Secret del certificado, configura el listener HTTPS, confirma que tu ruta y hostname coincidan — y básicamente eso es todo.
💡 El error más común de los principiantes no es que TLS sea difícil — es que tres cosas no están alineadas:
hostname,certificateRefsy los hostnames deHTTPRoute. Si cualquiera de ellas está mal, el tráfico empieza a comportarse de forma extraña.
Siguiente Paso
Ahora que has cubierto instalación, conceptos, routing y TLS, el siguiente post consolida todo esto en un conjunto de prácticas que tienen menos probabilidad de explotar en producción: 👉 Buenas Prácticas