En esta página, se explica cómo puedes proteger una puerta de enlace mediante varias características de seguridad:
Políticas de SSL para garantizar que la puerta de enlace use los protocolos y algoritmos seguros requeridos
Certificados para proteger el tráfico de cliente a puerta de enlace y de puerta de enlace a backends con TLS
Política de seguridad de Google Cloud Armor para proteger los servicios de los ataques de DSD
- Identity-Aware Proxy (IAP) para proporcionar una capa de autenticación y autorización antes de permitir el acceso a un servicio
Para obtener más información sobre la seguridad de las puertas de enlace, consulta Seguridad de las puertas de enlace.
Antes de comenzar
Antes de comenzar, asegúrate de haber realizado las siguientes tareas:
- Habilita la API de Google Kubernetes Engine. Habilitar la API de Google Kubernetes Engine
- Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa gcloud CLI. Si ya instalaste gcloud CLI, ejecuta
gcloud components update
para obtener la versión más reciente.
Requisitos del controlador de la puerta de enlace de GKE
- Para Standard, la versión 1.24 de GKE o una posterior.
- Para Autopilot, versión 1.26 de GKE o posterior.
- Versión 407.0.0 o posterior de Google Cloud CLI.
- La API de la puerta de enlace solo es compatible con clústeres nativos de VPC.
- Si usas las GatewayClasses internas, debes habilitar una subred de solo proxy.
- El clúster debe tener el complemento
HttpLoadBalancing
habilitado. - Si usas Istio, debes actualizarlo a una de las siguientes versiones:
- 1.15.2 o una versión posterior
- 1.14.5 o una versión posterior
- 1.13.9 o una versión posterior.
- Si usas una VPC compartida, en el proyecto host, debes asignar el rol
Compute Network User
a la cuenta de servicio de GKE para el proyecto de servicio.
Restricciones y limitaciones
Además de las restricciones y limitaciones del GKE Gateway Controller, se aplican específicamente las siguientes limitaciones a la seguridad de la puerta de enlace:
- Las configuraciones de TLS con unCertificado SSL o unAdministrador de certificados en las puertas de enlace no se admiten en la versión 1.28.4-gke.1083000 de GKE. Usa un Secret de Kubernetes como solución alternativa para esta versión de GKE.
- No puedes usar la anotación
networking.gke.io/certmap
con untls.certificateRefs
en el mismo recurso de puerta de enlace. Si haces referencia aCertificateMap
en una puerta de enlace, GKE lo considerará como un error.
- El Administrador de certificados admite certificados autoadministrados y administrados por Google. Los certificados administrados por Google son compatibles con las puertas de enlace regionales (disponibles en vista previa) y las puertas de enlace globales.
No puedes usar el mismo servicio que un backend para una puerta de enlace regional y global si haces referencia a una política de seguridad de backend de Google Cloud Armor en tu
GCPBackendPolicy
. Debes crear dos servicios y políticas independientes para este caso de uso.El controlador de Gateway no admite el recurso
ManagedCertificate
.La API de Gateway no admite la anotación
networking.gke.io/managed-certificates
.El campo
appProtocol
en la configuración del Service solo acepta letras mayúsculas para el valor del protocolo (HTTP
,HTTPS
oHTTP2
). El uso de letras minúsculas da como resultado el uso de HTTP como el protocolo con los backends.
Para obtener una lista de los campos y las capacidades de la API de puerta de enlace compatibles de los recursos de GatewayClass disponibles en GKE, consulta Capacidades de GatewayClass.
Protege una puerta de enlace mediante un Secret de Kubernetes
En este ejemplo, debes configurar una puerta de enlace mediante un Secret de Kubernetes.
Almacena un certificado en un Secret de Kubernetes
Puedes usar un certificado emitido y validado por la autoridad certificadora (CA) o crear un certificado autofirmado. En los siguientes pasos, se usa un certificado autofirmado.
Crea una clave privada:
openssl genrsa -out PRIVATE_KEY_FILE 2048
Reemplaza
PRIVATE_KEY_FILE
por el nombre de tu archivo de claves privadas, comoprivate-key.pem
. Para obtener más información, consulta Selecciona o crea una clave privada.Crea un archivo de configuración de OpenSSL:
cat <<EOF >CONFIG_FILE [req] default_bits = 2048 req_extensions = extension_requirements distinguished_name = dn_requirements prompt = no [extension_requirements] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @sans_list [dn_requirements] 0.organizationName = example commonName = store.example.com [sans_list] DNS.1 = store.example.com EOF
Reemplaza
CONFIG_FILE
con el nombre del archivo de configuración nuevo, comoconfig-file.cnf
.Crea un archivo de solicitud de firma de certificado (CSR):
openssl req -new -key PRIVATE_KEY_FILE \ -out CSR_FILE \ -config CONFIG_FILE
Reemplaza
CSR_FILE
con el nombre del archivo CSR nuevo, comocert.pem
. Para obtener más información, consulta Crea una CSR.Firma la CSR:
openssl x509 -req \ -signkey PRIVATE_KEY_FILE \ -in CSR_FILE \ -out CERTIFICATE_FILE \ -extfile CONFIG_FILE \ -extensions extension_requirements \ -days 30
Reemplaza
CERTIFICATE_FILE
por la ruta de acceso y el nombre del archivo que genera el comando, comocert-file.pem
. Para obtener más información, consulta Firma la CSR.Crea un Secret TLS de Kubernetes mediante la clave y el archivo de certificado que creaste:
kubectl create secret tls store-example-com \ --cert=CERTIFICATE_FILE \ --key=PRIVATE_KEY_FILE
GKE guarda el certificado y la clave como un recurso de Kubernetes que puedes adjuntar a tu puerta de enlace.
Crea una puerta de enlace y una HTTPRoute
Guarda el siguiente manifiesto como
external-gateway.yaml
:kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: external-http spec: gatewayClassName: gke-l7-global-external-managed listeners: - name: https protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs: - name: store-example-com
En este manifiesto, se describe una puerta de enlace con las siguientes propiedades:
gatewayClassName: gke-l7-global-external-managed
: implementa un balanceador de cargas de aplicaciones externo global.protocol: HTTPS
yport: 443
: obligatorios para habilitar TLS.tls
: hace referencia al Secret de Kubernetes creado en el paso anterior.
Aplica el manifiesto al clúster:
kubectl apply -f external-gateway.yaml
Guarda el siguiente manifiesto como
store-external-route.yaml
:kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: store-external labels: gateway: external-http spec: parentRefs: - name: external-http hostnames: - "store.example.com" rules: - backendRefs: - name: store-v1 port: 8080
En este manifiesto, se describe una HTTPRoute que coincide con el tráfico para
store.example.com
y lo envía al Servicestore-v1
.Aplica el manifiesto al clúster:
kubectl apply -f store-external-route.yaml
Verifica la puerta de enlace
Envía una solicitud a través de Internet para verificar que la puerta de enlace funcione.
Obtén la dirección IP de la puerta de enlace:
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"
El resultado es similar a este:
203.0.113.12
Este resultado es una dirección IP pública, lo que significa que cualquier cliente con acceso a Internet puede conectarse a ella.
Accede al dominio de la puerta de enlace mediante
curl
:curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert CERTIFICATE_FILE -v
Reemplaza lo siguiente:
GATEWAY_IP_ADDRESS
es la dirección IP del balanceador de cargas de puerta de enlace.CERTIFICATE_FILE
: El archivo de certificado que generaste. Debes guardar este archivo en la máquina que usas para conectarte a la puerta de enlace. Se requiere el certificado para autenticar la puerta de enlace porque esta usa un certificado autofirmado.
La opción
--resolve
resuelve el nombre de dominio a la dirección IP de la puerta de enlace, que es necesaria porque el DNS no está configurado para este dominio.El resultado es similar al siguiente:
... * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305 * ALPN, server accepted to use h2 * Server certificate: * subject: O=example; CN=store.example.com * start date: Apr 19 15:54:50 2021 GMT * expire date: Apr 19 15:54:50 2022 GMT * common name: store.example.com (matched) * issuer: O=example; CN=store.example.com * SSL certificate verify ok. ... { "cluster_name": "gw", "host_header": "store.example.com", "metadata": "store-v1", "node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal", "pod_name": "store-v1-84b47c7f58-tj5mn", "pod_name_emoji": "😍", "project_id": "agmsb-k8s", "timestamp": "2021-04-19T16:30:08" # Several lines of output omitted here. }
En esta salida, se incluye un protocolo de enlace TLS exitoso seguido de una respuesta de la aplicación. La conexión TLS finaliza en la puerta de enlace y la aplicación responde al cliente de forma segura.
Protege una puerta de enlace con Certificate Manager
En este ejemplo, se configura una puerta de enlace con el Administrador de certificados.
Crea una Certificate
Puerta de enlace global
Para crear una puerta de enlace global, debes hacer referencia a un recurso de mapa de certificados que contenga uno o más certificados. Debes crear al menos un certificado y agregarlo como entrada a tu mapa de certificados.
Para crear un certificado, primero crea una clave privada y un archivo del certificado.
Para crear un recurso
Certificate
, carga el certificado y la clave autoadministrados:gcloud certificate-manager certificates create store-example-com-cert \ --certificate-file="cert.pem" \ --private-key-file="PRIVATE_KEY_FILE"
Crea una
CertificateMap
.gcloud certificate-manager maps create store-example-com-map
Crea una
CertificateMapEntry
que asigne el certificado aCertificateMap
:gcloud certificate-manager maps entries create store-example-com-map-entry \ --map=store-example-com-map \ --hostname=store.example.com \ --certificates=store-example-com-cert
Puerta de enlace regional
Para una puerta de enlace regional, crea un Certificate
que se especificará directamente cuando se cree la puerta de enlace. A diferencia de una puerta de enlace global, no necesitas crear un CertificateMap
a la que se asignen certificados.
Crea una clave privada y archivo del certificado.
Para crear un recurso
Certificate
, sube el archivo del certificado y la clave:
gcloud certificate-manager certificates create "CERTIFICATE_NAME" \
--certificate-file="CERTIFICATE_FILE" \
--private-key-file="PRIVATE_KEY_FILE" \
--location="REGION"
Reemplaza lo siguiente:
CERTIFICATE_NAME
: el nombre del certificado, por ejemplo,store-example-com-cert
.CERTIFICATE_FILE
: el nombre del archivo del certificado, por ejemplo,cert.pem
.PRIVATE_KEY_FILE
: el nombre de tu archivo de claves privadas, comoprivate-key.pem
. Para obtener más información, consulta Selecciona o crea una clave privada.REGION
: el nombre de la región en la que configuras la puerta de enlace, por ejemplo,us-central1
.
Crea una puerta de enlace y una HTTPRoute
Puerta de enlace global
Para crear una puerta de enlace global, completa los siguientes pasos:
Guarda el siguiente manifiesto como
cert-map-gateway.yaml
:kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: external-http annotations: networking.gke.io/certmap: store-example-com-map spec: gatewayClassName: gke-l7-global-external-managed listeners: - name: https protocol: HTTPS port: 443
En este manifiesto, se describe una puerta de enlace con las siguientes propiedades:
gatewayClassName: gke-l7-global-external-managed
: implementa un balanceador de cargas de aplicaciones externo global.protocol: HTTPS
yport: 443
: obligatorios para habilitar TLS.
No hay sección TLS porque TLS se configura con el Administrador de certificados mediante la anotación
networking.gke.io/certmap
.Aplica el manifiesto al clúster:
kubectl apply -f cert-map-gateway.yaml
GKE puede tardar varios minutos en implementar la puerta de enlace.
Para crear una HTTPRoute, guarda el siguiente manifiesto como
cert-map-http-route.yaml
:apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: foo namespace: default spec: parentRefs: - name: external-http hostnames: - foo.example.com rules: - matches: - path: value: / backendRefs: - name: foo-v1 port: 8080
Aplica el manifiesto al clúster:
kubectl apply -f cert-map-http-route.yaml
Puerta de enlace regional
Cuando creas una puerta de enlace regional, puedes especificar los certificados que gestiona el Administrador de certificados y los certificados que administra Compute Engine.
Para crear una puerta de enlace externa regional, guarda el siguiente manifiesto como
external-gateway.yaml
:kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: gateway namespace: corp spec: gatewayClassName: gke-17-regional-external-managed listeners: - name: gateway-pre-shared-certmap protocol: HTTPS port: 443 tls: mode: Terminate options: networking.gke.io/cert-manager-certs: store-example-com-cert1, store-example-com-cert2 allowedRoutes: kinds: - kind: HTTPRoute namespaces: from: All
En este manifiesto, se describe una puerta de enlace con las siguientes propiedades:
gatewayClassName
:gke-l7-regional-external-managed
: implementa un balanceador de cargas de aplicaciones externo regional.protocol: HTTPS
yport: 443
: obligatorios para habilitar TLS.options
:networking.gke.io/cert-manager-certs
: los certificados que gestiona el Administrador de certificados.
Para crear una puerta de enlace interna regional, en el ejemplo anterior, cambia el valor de
gatewayClassName
agke-17-rilb
. Esto implementa un balanceador de cargas de aplicaciones interno.Aplica el manifiesto al clúster:
kubectl apply -f external-gateway.yaml
Para crear una HTTPRoute, guarda el siguiente manifiesto como
store-external-route.yaml
:apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: store-external labels: gateway: external-http spec: parentRefs: - name: external-http hostnames: - "store.example.com" rules: backendRefs: - name: store-v1 port: 8080
En este manifiesto, se describe una HTTPRoute que coincide con el tráfico para
store.example.com
y lo reenvía al Servicestore-v1
.Aplica el manifiesto al clúster:
kubectl apply -f store-external-route.yaml
Verifica la puerta de enlace
Obtén la dirección IP de la puerta de enlace:
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"
El resultado es similar a este:
203.0.113.12
Este resultado es una dirección IP pública, lo que significa que cualquier cliente con acceso a Internet puede conectarse a ella.
Actualiza un registro A o AAAA para dirigir el dominio a la dirección IP de la puerta de enlace.
Este paso solo es necesario si configuras un certificado SSL administrado por Google. Si configuras un certificado autoadministrado, puedes omitir este paso.
Después de que se actualizan los registros DNS, el balanceador de cargas puede tardar hasta 10 minutos en comenzar a usar el certificado administrado por Google.
Accede al dominio de la puerta de enlace mediante
curl
:curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert CERTIFICATE_FILE -v
Reemplaza lo siguiente:
GATEWAY_IP_ADDRESS
es la dirección IP del balanceador de cargas de puerta de enlace.CERTIFICATE_FILE
: El archivo de certificado que generaste. Debes guardar este archivo en la máquina que usas para conectarte a la puerta de enlace. Se requiere el certificado para autenticar la puerta de enlace porque esta usa un certificado autofirmado.
El resultado es similar al siguiente:
... * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305 * ALPN, server accepted to use h2 * Server certificate: * subject: O=example; CN=store.example.com * start date: Apr 19 15:54:50 2021 GMT * expire date: Apr 19 15:54:50 2022 GMT * common name: store.example.com (matched) * issuer: O=example; CN=store.example.com * SSL certificate verify ok. ... { "cluster_name": "gw", "host_header": "store.example.com", "metadata": "store-v1", "node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal", "pod_name": "store-v1-84b47c7f58-tj5mn", "pod_name_emoji": "😍", "project_id": "agmsb-k8s", "timestamp": "2021-04-19T16:30:08", "zone": "us-west1-a" }
Este resultado incluye un protocolo de enlace TLS exitoso y una respuesta de la aplicación. La TLS se finaliza correctamente en la puerta de enlace y la aplicación responde al cliente de forma segura.
Protege el tráfico del balanceador de cargas a la aplicación con TLS
Puedes encriptar el tráfico del balanceador de cargas a los Pods de backend mediante el campo ports[].appProtocol
. Los campos compatibles con appProtocol
son HTTP
, HTTPS
y HTTP2
.
En el siguiente manifiesto, se describe un Service que especifica que el balanceador de cargas debe usar tráfico HTTPS para comunicarse con los Pods de backend:
apiVersion: v1
kind: Service
metadata:
name: store-v2
spec:
selector:
app: store
version: v2
ports:
- port: 8080
targetPort: 8080
appProtocol: HTTPS
El balanceador de cargas no verifica el certificado que usan los Pods de backend. Es tu responsabilidad asegurarte de que el certificado que se usa en los Pods de backend sea válido.
Protege el cliente para el tráfico del balanceador de cargas mediante políticas de SSL
Cuando tus aplicaciones se exponen a través de una puerta de enlace externa que usa HTTPS, es importante usar los protocolos más recientes o especificar la versión mínima de SSL o TLS. Puedes proteger el tráfico del cliente al balanceador de cargas a través de las políticas de SSL.
Para obtener más información sobre las políticas de SSL que se pueden adjuntar a tu puerta de enlace y cómo crearlas, consulta Configura políticas de SSL para proteger el tráfico del cliente al balanceador de cargas.
Protege tus backends con Google Cloud Armor
Las políticas de seguridad de Google Cloud Armor te ayudan a proteger las aplicaciones con balanceo de cargas de los ataques basados en la Web. Una vez que configuraste una política de seguridad de Google Cloud Armor, puedes hacer referencia a ella en un GCPBackendPolicy
aplicado a tus servicios de Kubernetes.
Si deseas configurar las políticas de Google Cloud Armor con Gateway, consulta Configura la política de seguridad de Google Cloud Armor para proteger tus servicios de backend.
Autentica solicitudes para tus backends mediante Identity-Aware Proxy
Identity-Aware Proxy te ayuda a proteger tus backends del tráfico no deseado mediante la autenticación de los clientes que envían solicitudes a tus aplicaciones y la aplicación de la autorización de tráfico basada en roles. Después de habilitar Identity-Aware Proxy para GKE, puedes hacer referencia a tus credenciales de OAuth en una GCPBackendPolicy
aplicada a los Services de Kubernetes.
Para configurar Identity-Aware Proxy con Gateway, consulta Configura Identity-Aware Proxy.
¿Qué sigue?
- Obtén más información sobre la seguridad de la puerta de enlace.