Configura la seguridad del servicio con Envoy y las APIs de balanceo de cargas (heredado)

Usa las instrucciones de esta guía para configurar la autenticación y la autorización para los servicios implementados con Cloud Service Mesh y proxies de Envoy mediante las APIs de balanceo de cargas. Si usas las APIs de enrutamiento de servicios, lee Configura la seguridad de los servicios con Envoy.

Para obtener información completa, consulta Seguridad del servicio de Cloud Service Mesh con las APIs de balanceo de cargas.

Este documento se aplica a las configuraciones que usan las APIs de balanceo de cargas. Este es un documento heredado.

Requisitos

Antes de configurar la seguridad de servicios para Cloud Service Mesh con Envoy, asegúrate de que cumpla con los siguientes requisitos previos:

Prepárate para la configuración

En las siguientes secciones, se describen las tareas que debes completar antes de configurar el servicio de seguridad de Cloud Service Mesh. Las tareas son las siguientes:

  • Actualiza Google Cloud CLI
  • Configurar variables
  • Habilita las APIs necesarias para que Cloud Service Mesh funcione con Certificate Authority Service

Actualiza la herramienta de línea de comandos de gcloud

Para actualizar Google Cloud CLI, ejecuta lo siguiente en tu máquina local:

gcloud components update

Configura variables

Configura las siguientes variables para que puedas copiar y pegar el código con valores coherentes a medida que trabajas con el ejemplo de este documento. Usa los siguientes valores:

  • PROJECT_ID: Sustituye el ID de tu proyecto.
  • CLUSTER_NAME: Sustituye el nombre del clúster que deseas usar, por ejemplo, secure-td-cluster.
  • ZONE: Sustituye la zona en la que se encuentra el clúster.
  • GKE_CLUSTER_URL: Sustituye https://container.googleapis.com/v1/projects/PROJECT_ID/locations/ZONE/clusters/CLUSTER_NAME
  • WORKLOAD_POOL: Sustituye PROJECT_ID.svc.id.goog
  • K8S_NAMESPACE: Sustituye default.
  • DEMO_CLIENT_KSA: Sustituye el nombre de tu cuenta de servicio de cliente de Kubernetes.
  • DEMO_SERVER_KSA: Sustituye el nombre de la cuenta de servicio de Kubernetes de tu servidor.
  • PROJNUM: Sustituye el número de proyecto que puedes determinar desde la consola de Google Cloud o mediante este comando:

    gcloud projects describe PROJECT_ID --format="value(projectNumber)"
    
  • SA_GKE: Sustituye service-PROJNUM@container-engine-robot.iam.gserviceaccount.com

  • CLUSTER_VERSION: Sustituye la versión más reciente disponible. Puedes encontrarla en las notas de la versión del canal rápido. La versión mínima requerida es 1.21.4-gke.1801. Esta es la versión del clúster de GKE que se usará en este ejemplo.

Establece los valores aquí:

# Substitute your project ID
PROJECT_ID=PROJECT_ID

# GKE cluster name and zone for this example.
CLUSTER_NAME=CLUSTER_NAME
ZONE=ZONE

# GKE cluster URL derived from the above
GKE_CLUSTER_URL="https://container.googleapis.com/v1/projects/PROJECT_ID/locations/ZONE/clusters/CLUSTER_NAME"

# Workload pool to be used with the GKE cluster
WORKLOAD_POOL="PROJECT_ID.svc.id.goog"

# Kubernetes namespace to run client and server demo.
K8S_NAMESPACE=K8S_NAMESPACE
DEMO_CLIENT_KSA=DEMO_CLIENT_KSA
DEMO_SERVER_KSA=DEMO_SERVER_KSA

# Compute other values
# Project number for your project
PROJNUM=PROJNUM

CLUSTER_VERSION=CLUSTER_VERSION
SA_GKE=service-PROJNUM@container-engine-robot.iam.gserviceaccount.com

Habilitación de las API

Usa el comando gcloud services enable para habilitar todas las APIs que necesitas a fin de configurar la seguridad de Cloud Service Mesh con Certificate Authority Service.

gcloud services enable \
   container.googleapis.com \
   cloudresourcemanager.googleapis.com \
   compute.googleapis.com \
   trafficdirector.googleapis.com \
   networkservices.googleapis.com \
   networksecurity.googleapis.com \
   privateca.googleapis.com \
   gkehub.googleapis.com

Crea o actualiza un clúster de GKE

La seguridad del servicio de Cloud Service Mesh depende de la integración del servicio de AC con GKE. El clúster de GKE debe cumplir con los siguientes requisitos además de los requisitos para la configuración:

  • Usa una versión de clúster mínima de 1.21.4-gke.1801. Si necesitas funciones que se encuentran en una versión posterior, puedes obtenerla del canal de versiones rápido.
  • El clúster de GKE debe estar habilitado y configurado con certificados de malla de trabajo, como se describe en Crea autoridades certificadoras para emitir certificados.
  1. Crea un clúster nuevo que use la federación de identidades para cargas de trabajo para GKE. Si actualizas un clúster existente, avanza al siguiente paso. El valor que proporciones para --tags debe coincidir con el nombre que se pasó a la marca --target-tags del comando firewall-rules create en la sección Configura Cloud Service Mesh con componentes de Cloud Load Balancing.

    # Create a GKE cluster with GKE managed mesh certificates.
    gcloud container clusters create CLUSTER_NAME \
      --release-channel=rapid \
      --scopes=cloud-platform \
      --image-type=cos_containerd \
      --machine-type=e2-standard-2 \
      --zone=ZONE \
      --workload-pool=PROJECT_ID.svc.id.goog \
      --enable-mesh-certificates \
      --cluster-version=CLUSTER_VERSION \
      --enable-ip-alias \
      --tags=allow-health-checks \
      --workload-metadata=GKE_METADATA
    

    La creación del clúster puede tomar varios minutos en completarse.

  2. Si usas un clúster existente, activa la federación de identidades para cargas de trabajo para GKE y los certificados de malla de GKE. Asegúrate de que el clúster se haya creado con la marca --enable-ip-alias, que no se puede usar con el comando update.

    gcloud container clusters update CLUSTER_NAME \
      --enable-mesh-certificates
    
  3. Ejecuta el siguiente comando a fin de cambiar al clúster nuevo como el clúster predeterminado para los comandos de kubectl:

    gcloud container clusters get-credentials CLUSTER_NAME \
      --zone ZONE
    

Implementa en un entorno de varios clústeres

Si realizas la implementación en un entorno de varios clústeres, sigue el procedimiento general que se describe en esta sección. En estas instrucciones, se supone que los Pods de cliente se ejecutan en un clúster y los Pods del servidor se ejecutan en el otro.

  1. Crea o actualiza los clústeres mediante las instrucciones de la sección anterior.

  2. Captura los rangos de direcciones IP del Pod para cada clúster mediante el siguiente comando:

    gcloud compute firewall-rules list \
      --filter="name~gke-{CLUSTER_NAME}-[0-9a-z]*-all" \
      --format="value(sourceRanges)"
    

    Por ejemplo, para los clústeres llamados cluster-a y cluster-b, los comandos muestran resultados como los siguientes:

    cluster-a, pod CIDR: 10.4.0.0/14, node network tag: gke-cluster-a-9cd18751-node
    cluster-b, pod CIDR: 10.8.0.0/14, node network tag: gke-cluster-b-acd14479-node
    
  3. Crea reglas de firewall de VPC que permitan que los clústeres se comuniquen entre sí. Por ejemplo, el siguiente comando crea una regla de firewall que permite que las direcciones IP del Pod cluster-a se comuniquen con los nodos cluster-b:

    gcloud compute firewall-rules create per-cluster-a-pods \
      --allow="tcp,udp,icmp,esp,ah,sctp" \
      --target-tags="gke-cluster-b-acd14479-node"
    

    El siguiente comando crea una regla de firewall que permite que las direcciones IP del pod cluster-b se comuniquen con los nodos cluster-a:

    gcloud compute firewall-rules create per-cluster-b-pods \
      --allow="tcp,udp,icmp,esp,ah,sctp" \
      --target-tags="gke-cluster-a-9cd18751-node"
    

Registra clústeres con una flota

Registra el clúster que creaste o actualizaste en Crea un clúster de GKE con una flota. El registro del clúster facilita la configuración de clústeres en varios proyectos.

Ten en cuenta que estos pasos pueden demorar hasta diez minutos en completarse.

  1. Registra tu clúster en la flota:

    gcloud container fleet memberships register CLUSTER_NAME \
      --gke-cluster=ZONE/CLUSTER_NAME \
      --enable-workload-identity --install-connect-agent \
      --manifest-output-file=MANIFEST-FILE_NAME
    

    de la siguiente manera:

    • CLUSTER_NAME: Es el nombre del clúster.
    • ZONE: La zona del clúster.
    • MANIFEST-FILE_NAME: Es la ruta de acceso en la que estos comandos generan el manifiesto para el registro.

    Cuando el proceso de registro se realice de forma correcta, verás un mensaje como el siguiente:

    Finished registering the cluster CLUSTER_NAME with the fleet.
  2. Aplica el archivo de manifiesto generado a tu clúster:

    kubectl apply -f MANIFEST-FILE_NAME
    

    Cuando el proceso de la aplicación se realice de forma correcta, verás mensajes como los siguientes:

    namespace/gke-connect created
    serviceaccount/connect-agent-sa created
    podsecuritypolicy.policy/gkeconnect-psp created
    role.rbac.authorization.k8s.io/gkeconnect-psp:role created
    rolebinding.rbac.authorization.k8s.io/gkeconnect-psp:rolebinding created
    role.rbac.authorization.k8s.io/agent-updater created
    rolebinding.rbac.authorization.k8s.io/agent-updater created
    role.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    clusterrole.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-feature-authorizer-20210416-01-00 created
    rolebinding.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    role.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    rolebinding.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    secret/http-proxy created
    deployment.apps/gke-connect-agent-20210416-01-00 created
    service/gke-connect-monitoring created
    secret/creds-gcp create
    
  3. Obtén el recurso de la membresía del clúster:

    kubectl get memberships membership -o yaml
    

    El resultado debe incluir el grupo de Workload Identity que asigna la flota, en el que PROJECT_ID es el ID de tu proyecto:

    workload_identity_pool: PROJECT_ID.svc.id.goog
    

    Esto significa que el clúster se registró correctamente.

Crea autoridades certificadoras para emitir certificados

Para emitir certificados a tus pods, crea un grupo de servicios de CA y las siguientes autoridades certificadoras (CA):

  • CA raíz. Esta es la raíz de confianza de todos los certificados de malla emitidos. Puedes usar una CA raíz existente si tienes una. Crea la CA raíz en el nivel enterprise, que está destinado a la emisión de certificados de larga duración y bajo volumen.
  • CA subordinada. Esta CA emite certificados para cargas de trabajo. Crea la CA subordinada en la región en la que se implementa el clúster. Crea la CA subordinada en el nivel devops, que está destinado a la emisión de certificados de corta duración y gran volumen.

Crear una CA subordinada es opcional, pero te recomendamos crear una en lugar de usar tu CA raíz para emitir certificados de malla de GKE. Si decides usar la CA raíz para emitir certificados de malla, asegúrate de que se mantenga el modo de emisión basado en configuración predeterminado.

La CA subordinada puede estar en una región diferente de tu clúster, pero recomendamos crearla en la misma región que tu clúster para optimizar el rendimiento. Sin embargo, puedes crear las CA subordinadas y raíz en regiones diferentes sin ningún impacto en el rendimiento o la disponibilidad.

Estas regiones son compatibles con el servicio de CA:

Nombre de la región Descripción de la región
asia-east1 Taiwán
asia-east2 Hong Kong
asia-northeast1 Tokio
asia-northeast2 Osaka
asia-northeast3 Seúl
asia-south1 Bombay
asia-south2 Delhi
asia-southeast1 Singapur
asia-southeast2 Yakarta
australia-southeast1 Sídney
australia-southeast2 Melbourne
europe-central2 Varsovia
europe-north1 Finlandia
europe-southwest1 Madrid
europe-west1 Bélgica
europe-west2 Londres
europe-west3 Fráncfort
europe-west4 Países Bajos
europe-west6 Zúrich
europe-west8 Milán
europe-west9 París
europe-west10 Berlín
europe-west12 Turín
me-central1 Doha
me-central2 Dammam
me-west1 Tel Aviv
northamerica-northeast1 Montreal
northamerica-northeast2 Toronto
southamerica-east1 São Paulo
southamerica-west1 Santiago
us-central1 Iowa
us-east1 Carolina del Sur
us-east4 Virginia del Norte
us-east5 Columbus
us-south1 Dallas
us-west1 Oregón
us-west2 Los Ángeles
us-west3 Salt Lake City
us-west4 Las Vegas

La lista de ubicaciones compatibles también se puede verificar ejecutando el siguiente comando:

gcloud privateca locations list
  1. Otorga la roles/privateca.caManager de IAM a las personas que crean un grupo de CA y una CA. Ten en cuenta que, para MEMBER, el formato correcto es user:userid@example.com. Si esa persona es el usuario actual, puedes obtener el ID del usuario actual con el comando de shell $(gcloud auth list --filter=status:ACTIVE --format="value(account)").

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.caManager
    
  2. Otorga el rol role/privateca.admin en el servicio de AC a las personas que necesiten modificar las políticas de IAM. En este caso, MEMBER es una persona que necesita este acceso, en particular, cualquier persona que realice los siguientes pasos que otorgan los roles privateca.auditor y privateca.certificateManager:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.admin
    
  3. Crea el grupo de servicios de CA raíz.

    gcloud privateca pools create ROOT_CA_POOL_NAME \
      --location ROOT_CA_POOL_LOCATION \
      --tier enterprise
    
  4. Crea una CA raíz.

    gcloud privateca roots create ROOT_CA_NAME --pool ROOT_CA_POOL_NAME \
      --subject "CN=ROOT_CA_NAME, O=ROOT_CA_ORGANIZATION" \
      --key-algorithm="ec-p256-sha256" \
      --max-chain-length=1 \
      --location ROOT_CA_POOL_LOCATION
    

    En esta configuración de demostración, usa los siguientes valores para las variables:

    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_NAME=pkcs2-ca
    • ROOT_CA_POOL_LOCATION=us-east1
    • ROOT_CA_ORGANIZATION="TestCorpLLC"
  5. Crea el grupo subordinado y la CA subordinada. Asegúrate de que el modo de emisión basado en la configuración predeterminado permanezca permitido.

    gcloud privateca pools create SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --tier devops
    
    gcloud privateca subordinates create SUBORDINATE_CA_NAME \
      --pool SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --issuer-pool ROOT_CA_POOL_NAME \
      --issuer-location ROOT_CA_POOL_LOCATION \
      --subject "CN=SUBORDINATE_CA_NAME, O=SUBORDINATE_CA_ORGANIZATION" \
      --key-algorithm "ec-p256-sha256" \
      --use-preset-profile subordinate_mtls_pathlen_0
    

    En esta configuración de demostración, usa los siguientes valores para las variables:

    • SUBORDINATE_CA_POOL_NAME="td-ca-pool"
    • SUBORDINATE_CA_POOL_LOCATION=us-east1
    • SUBORDINATE_CA_NAME="td-ca"
    • SUBORDINATE_CA_ORGANIZATION="TestCorpLLC"
    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_POOL_LOCATION=us-east1
  6. Otorga la función privateca.auditor de IAM al grupo de CA raíz para permitir el acceso desde la cuenta de servicio de GKE:

    gcloud privateca pools add-iam-policy-binding ROOT_CA_POOL_NAME \
     --location ROOT_CA_POOL_LOCATION \
     --role roles/privateca.auditor \
     --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  7. Otorga la función privateca.certificateManager de IAM para que el grupo CA subordinado permita el acceso desde la cuenta de servicio de GKE:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --role roles/privateca.certificateManager \
      --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  8. Guarda la siguiente configuración de YAML WorkloadCertificateConfig para indicarle a tu clúster cómo emitir certificados de malla:

    apiVersion: security.cloud.google.com/v1
    kind: WorkloadCertificateConfig
    metadata:
      name: default
    spec:
      # Required. The CA service that issues your certificates.
      certificateAuthorityConfig:
        certificateAuthorityServiceConfig:
          endpointURI: ISSUING_CA_POOL_URI
    
      # Required. The key algorithm to use. Choice of RSA or ECDSA.
      #
      # To maximize compatibility with various TLS stacks, your workloads
      # should use keys of the same family as your root and subordinate CAs.
      #
      # To use RSA, specify configuration such as:
      #   keyAlgorithm:
      #     rsa:
      #       modulusSize: 4096
      #
      # Currently, the only supported ECDSA curves are "P256" and "P384", and the only
      # supported RSA modulus sizes are 2048, 3072 and 4096.
      keyAlgorithm:
        rsa:
          modulusSize: 4096
    
      # Optional. Validity duration of issued certificates, in seconds.
      #
      # Defaults to 86400 (1 day) if not specified.
      validityDurationSeconds: 86400
    
      # Optional. Try to start rotating the certificate once this
      # percentage of validityDurationSeconds is remaining.
      #
      # Defaults to 50 if not specified.
      rotationWindowPercentage: 50
    
    

    Reemplaza lo siguiente:

    • El ID del proyecto del proyecto en el que se ejecuta tu clúster.
      PROJECT_ID
    • El URI completamente calificado de la CA que emite los certificados de malla (ISSUING_CA_POOL_URI). Puede ser tu CA subordinada (recomendada) o la CA raíz. El formato es:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
  9. Guarda la siguiente configuración de YAML TrustConfig para indicarle a tu clúster cómo confiar en los certificados emitidos:

    apiVersion: security.cloud.google.com/v1
    kind: TrustConfig
    metadata:
      name: default
    spec:
      # You must include a trustStores entry for the trust domain that
      # your cluster is enrolled in.
      trustStores:
      - trustDomain: PROJECT_ID.svc.id.goog
        # Trust identities in this trustDomain if they appear in a certificate
        # that chains up to this root CA.
        trustAnchors:
        - certificateAuthorityServiceURI: ROOT_CA_POOL_URI
    

    Reemplaza lo siguiente:

    • El ID del proyecto del proyecto en el que se ejecuta tu clúster.
      PROJECT_ID
    • El URI completamente calificado del grupo de CA raíz (ROOT_CA_POOL_URI). El formato es:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
  10. Aplica las configuraciones a tu clúster.

    kubectl apply -f WorkloadCertificateConfig.yaml
    kubectl apply -f TrustConfig.yaml
    

Configura la administración de identidades y accesos

A fin de crear los recursos necesarios para la configuración, debes tener la función compute.NetworkAdmin. Esta función contiene todos los permisos necesarios para crear, actualizar, borrar, enumerar y usar (es decir, hacer referencia a esto en otros recursos) los recursos necesarios. Si eres propietario o editor de tu proyecto, automáticamente tienes esta función.

Ten en cuenta que networksecurity.googleapis.com.clientTlsPolicies.use y networksecurity.googleapis.com.serverTlsPolicies.use no se aplican cuando haces referencia a estos recursos en el servicio de backend y a los recursos de proxy HTTPS de destino.

Si esto se aplica en el futuro y usas la función compute.NetworkAdmin, no notarás ningún problema cuando se aplique esta verificación.

Si usas funciones personalizadas y esta verificación se aplica en el futuro, debes asegurarte de incluir el permiso .use correspondiente. De lo contrario, en el futuro, es posible que tu función personalizada no tenga los permisos necesarios para hacer referencia a clientTlsPolicy o serverTlsPolicy desde el servicio de backend o el proxy HTTPS de destino, respectivamente.

Las siguientes instrucciones permiten que la cuenta de servicio predeterminada acceda a la API de seguridad de Service Mesh de Cloud y cree las cuentas de servicio de Kubernetes.

  1. Configura IAM para permitir que la cuenta de servicio predeterminada acceda a la API de seguridad de Cloud Service Mesh.

    GSA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \
       --filter='displayName:Compute Engine default service account')
    
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member serviceAccount:${GSA_EMAIL} \
      --role roles/trafficdirector.client
    
  2. Configura cuentas de servicio de Kubernetes. En las implementaciones de cliente y servidor de las siguientes secciones, se usan los nombres de K del servidor de Kubernetes y las cuentas de servicio del cliente.

    kubectl create serviceaccount --namespace K8S_NAMESPACE DEMO_SERVER_KSA
    kubectl create serviceaccount --namespace K8S_NAMESPACE DEMO_CLIENT_KSA
    
  3. Para permitir que las cuentas de servicio de Kubernetes actúen en nombre de la cuenta de servicio predeterminada de Compute Engine, crea una vinculación de políticas de IAM entre las dos. Esta vinculación permite que la cuenta de servicio de Kubernetes actúe como la cuenta de servicio de Compute Engine predeterminada.

    gcloud iam service-accounts add-iam-policy-binding  \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/DEMO_SERVER_KSA]" ${GSA_EMAIL}
    
    gcloud iam service-accounts add-iam-policy-binding  \
      --role roles/iam.workloadIdentityUser  \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/DEMO_CLIENT_KSA]" ${GSA_EMAIL}
    
  4. Anota las cuentas de servicio de Kubernetes para asociarlas con la cuenta de servicio predeterminada de Compute Engine.

    kubectl annotate --namespace K8S_NAMESPACE \
      serviceaccount DEMO_SERVER_KSA \
      iam.gke.io/gcp-service-account=${GSA_EMAIL}
    
    kubectl annotate --namespace K8S_NAMESPACE \
      serviceaccount DEMO_CLIENT_KSA \
      iam.gke.io/gcp-service-account=${GSA_EMAIL}
    

Configura Cloud Service Mesh

Usa las siguientes instrucciones para instalar el inyector de sidecar, configurar un servicio de prueba y completar otras tareas de implementación.

Instala el inyector de sidecar de Envoy en el clúster

Usa las instrucciones de las dos secciones siguientes de la configuración de Cloud Service Mesh para pods de GKE con inserción automática de Envoy para implementar y habilitar la inserción de sidecar de Envoy en tu clúster:

Asegúrate de completar ambos conjuntos de instrucciones antes de configurar un servicio de prueba.

Configura un servicio de prueba

Después de instalar el inyector de sidecar de Envoy, usa estas instrucciones a fin de configurar un servicio de prueba para la implementación.

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/service_sample.yaml | sed -e s/DEMO_SERVER_KSA_PLACEHOLDER/DEMO_SERVER_KSA/g > service_sample.yaml

kubectl apply -f service_sample.yaml

El archivo service_sample.yaml contiene el podspec para tu aplicación de servidor de demostración. Hay algunas anotaciones específicas de la seguridad de Cloud Service Mesh.

Metadatos del proxy de Cloud Service Mesh

El podspec especifica la anotación proxyMetadata:

spec:
...
      annotations:
        cloud.google.com/proxyMetadata: '{"app": "payments"}'
...

Cuando se inicializa el Pod, el proxy de sidecar detecta esta anotación y la transmite a Cloud Service Mesh. Luego, Cloud Service Mesh puede usar esta información para devolver la configuración filtrada:

  • Más adelante en esta guía, ten en cuenta que la política de extremos especifica un comparador de extremos.
  • El comparador de extremos especifica que solo los clientes que presentan una etiqueta con el nombre app y el valor payments reciben la configuración filtrada.

Usa claves y certificados de malla firmados por el servicio de CA

El podspec especifica la anotación enableManagedCerts:

spec:
...
      annotations:
        ...
        cloud.google.com/enableManagedCerts: "true"
...

Cuando se inicializa el Pod, los certificados y claves firmados por el Servicio de AC se activan de forma automática en el sistema de archivos del proxy de sidecar local.

Configura el puerto de interceptación de tráfico entrante

El podspec especifica la anotación includeInboundPorts:

spec:
...
      annotations:
        ...
        cloud.google.com/includeInboundPorts: "8000"
...

Este es el puerto en el que tu aplicación de servidor escucha las conexiones. Cuando se inicializa el Pod, el proxy de sidecar detecta esta anotación y la transmite a Cloud Service Mesh. Luego, Cloud Service Mesh puede usar esta información para enviar una configuración filtrada que intercepte todo el tráfico entrante a este puerto y que pueda aplicar políticas de seguridad en él.

El puerto de verificación de estado debe ser diferente del puerto de la aplicación. De lo contrario, se aplicarán las mismas políticas de seguridad a las conexiones entrantes al puerto de verificación de estado, lo que puede ocasionar el rechazo de las conexiones, lo que dará como resultado que el servidor se marque incorrectamente como en mal estado.

Configura servicios de GKE con NEG

Los servicios de GKE deben exponerse a través de grupos de extremos de red (NEG) para que puedas configurarlos como backends de un servicio de backend de Cloud Service Mesh. El paquete service_sample.yaml que se proporciona con esta guía de configuración usa el nombre de NEG service-test-neg en la siguiente anotación:

...
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "service-test-neg"}}}'
spec:
  ports:
  - port: 80
    name: service-test
    protocol: TCP
    targetPort: 8000

No es necesario que cambies el archivo service_sample.yaml.

Guarda el nombre del NEG

Guarda el nombre del NEG en la variable NEG_NAME:

NEG_NAME="service-test-neg"

Implementa una aplicación cliente en GKE

Ejecuta el siguiente comando para iniciar un cliente de demostración con un proxy de Envoy como un sidecar, que necesitas a fin de demostrar las funciones de seguridad.

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/client_sample.yaml | sed -e s/DEMO_CLIENT_KSA_PLACEHOLDER/DEMO_CLIENT_KSA/g > client_sample.yaml

kubectl apply -f client_sample.yaml

El podspec del cliente solo incluye la anotación enableManagedCerts. Esto es necesario a fin de activar los volúmenes necesarios para las claves y los certificados de malla administrados de GKE que firma la instancia del servicio de CA.

Configura los recursos de Google Cloud de Cloud Service Mesh

Sigue los pasos en Configura Cloud Service Mesh con componentes de Cloud Load Balancing. Asegúrate de verificar que el tráfico del cliente de muestra se enrute al servicio de muestra.

La configuración de Cloud Service Mesh está completa y ahora puedes configurar las políticas de autenticación y autorización.

Configura la seguridad de servicio a servicio

Usa las instrucciones de las siguientes secciones para configurar la seguridad entre servicios.

Habilita mTLS en la malla

Para configurar mTLS en la malla, debes proteger el tráfico saliente al servicio de backend y el tráfico entrante al extremo.

Formato de las referencias de políticas

Ten en cuenta el siguiente formato obligatorio para hacer referencia a la TLS del servidor, la TLS del cliente y las políticas de autorización:

projects/PROJECT_ID/locations/global/[serverTlsPolicies|clientTlsPolicies|authorizationPolicies]/[server-tls-policy|client-mtls-policy|authz-policy]

Por ejemplo:

projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
projects/PROJECT_ID/locations/global/authorizationPolicies/authz-policy

Protege el tráfico saliente al servicio de backend

Para proteger el tráfico saliente, primero debes crear una política de TLS de cliente que haga lo siguiente:

  • Usa google_cloud_private_spiffe como el complemento de clientCertificate, que programa Envoy para usar certificados de malla administrados por GKE como la identidad del cliente.
  • Usa google_cloud_private_spiffe como complemento para serverValidationCa, que programa Envoy a fin de usar certificados de malla administrados por GKE a fin de validar el servidor.

Luego, adjunta la política de TLS del cliente al servicio de backend. Esto realiza las siguientes acciones:

  • Aplica la política de autenticación de la política TLS del cliente a las conexiones salientes a los extremos del servicio de backend.
  • SAN (nombres alternativos del asunto) indica al cliente que confirme la identidad exacta del servidor al que se está conectando.
  1. Crea la política de TLS del cliente en un archivo client-mtls-policy.yaml:

    name: "client-mtls-policy"
    clientCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. Importa la política de TLS del cliente:

    gcloud network-security client-tls-policies import client-mtls-policy \
        --source=client-mtls-policy.yaml --location=global
    
  3. Vincula la política de TLS del cliente al servicio de backend. Esto aplica la autenticación mTLS en todas las solicitudes salientes del cliente a este servicio de backend.

    gcloud compute backend-services export td-gke-service \
        --global --destination=demo-backend-service.yaml
    

    Agrega las siguientes líneas a demo-backend-service.yaml:

    securitySettings:
      clientTlsPolicy: projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
      subjectAltNames:
        - "spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA"
    
  4. Importa los valores:

    gcloud compute backend-services import td-gke-service \
        --global --source=demo-backend-service.yaml
    
  5. También puedes ejecutar el siguiente comando para comprobar si la solicitud falla. Esto es un error esperado, porque el cliente espera certificados del extremo, pero el extremo no está programado con una política de seguridad.

    # Get the name of the Podrunning Busybox.
    BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')
    
    # Command to execute that tests connectivity to the service service-test.
    TEST_CMD="wget -q -O - service-test; echo"
    
    # Execute the test command on the pod.
    kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"
    

    Verás un resultado como este:

    wget: server returned error: HTTP/1.1 503 Service Unavailable
    

Protege el tráfico entrante al extremo

Para proteger el tráfico entrante, primero debes crear una política de TLS del servidor que haga lo siguiente:

  • Usa google_cloud_private_spiffe como el complemento para serverCertificate, que programa Envoy para usar certificados de malla administrados por GKE como la identidad del servidor.
  • Usa google_cloud_private_spiffe como el complemento para clientValidationCa, que programa Envoy a fin de usar certificados de malla administrados por GKE a fin de validar el cliente.
  1. Guarda los valores de la política de TLS del servidor en un archivo llamado server-mtls-policy.yaml.

    name: "server-mtls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    mtlsPolicy:
      clientValidationCa:
      - certificateProviderInstance:
          pluginInstance: google_cloud_private_spiffe
    
  2. Crea la política de TLS del servidor:

    gcloud network-security server-tls-policies import server-mtls-policy \
        --source=server-mtls-policy.yaml --location=global
    
  3. Crea un archivo llamado ep_mtls.yaml que contenga el comparador de extremos y conecta la política de TLS del servidor.

    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: MATCH_ALL
        metadataLabels:
        - labelName: app
          labelValue: payments
    name: "ep"
    serverTlsPolicy: projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy
    type: SIDECAR_PROXY
    
  4. Importa el comparador de extremos.

    gcloud network-services endpoint-policies import ep \
        --source=ep_mtls.yaml --location=global
    

Valida la configuración

Ejecuta el siguiente comando curl. Si la solicitud finaliza de forma correcta, verás x-forwarded-client-cert en el resultado. El encabezado se imprime solo cuando la conexión es mTLS.

# Get the name of the Podrunning Busybox.
BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')

# Command to execute that tests connectivity to the service service-test.
TEST_CMD="wget -q -O - service-test; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

Verás un resultado como el siguiente:

GET /get HTTP/1.1
Host: service-test
content-length: 0
x-envoy-internal: true
accept: */*
x-forwarded-for: 10.48.0.6
x-envoy-expected-rq-timeout-ms: 15000
user-agent: curl/7.35.0
x-forwarded-proto: http
x-request-id: redacted
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA

Ten en cuenta que el encabezado x-forwarded-client-cert lo inserta Envoy desde el servidor y que contiene su propia identidad (servidor) y la identidad del cliente de origen. Debido a que vemos las identidades del cliente y del servidor, esto es una señal de una conexión mTLS.

Configura el acceso a nivel de servicio con una política de autorización

Con estas instrucciones, se crea una política de autorización que permite las solicitudes que se envían mediante la cuenta DEMO_CLIENT_KSA en la que el nombre de host es service-test, el puerto es 8000 y el método HTTP es GET. Antes de crear políticas de autorización, lee la precaución en Restringir el acceso con autorización.

  1. Para crear una política de autorización, crea un archivo llamado authz-policy.yaml.

    action: ALLOW
    name: authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
      destinations:
      - hosts:
        - service-test
        ports:
        - 8000
        methods:
        - GET
    
  2. Importa la política:

    gcloud network-security authorization-policies import authz-policy \
      --source=authz-policy.yaml \
      --location=global
    
  3. Actualiza la política de extremos para hacer referencia a la política de autorización nueva. Para ello, agrega lo siguiente al archivo ep_mtls.yaml:

    authorizationPolicy: projects/PROJECT_ID/locations/global/authorizationPolicies/authz-policy
    

    La política de extremos ahora especifica que mTLS y la política de autorización deben aplicarse a las solicitudes entrantes a los pods cuyos proxies de sidecar de Envoy presentan la etiqueta app:payments.

  4. Importa la política:

    gcloud network-services endpoint-policies import ep \
        --source=ep_mtls.yaml --location=global
    

Valida la configuración

Ejecuta los siguientes comandos para validar la configuración:

# Get the name of the Podrunning Busybox.
BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')

# Command to execute that tests connectivity to the service service-test.
# This is a valid request and will be allowed.
TEST_CMD="wget -q -O - service-test; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

El resultado esperado es similar al siguiente:

GET /get HTTP/1.1
Host: service-test
content-length: 0
x-envoy-internal: true
accept: */*
x-forwarded-for: redacted
x-envoy-expected-rq-timeout-ms: 15000
user-agent: curl/7.35.0
x-forwarded-proto: http
x-request-id: redacted
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA

Ejecuta los siguientes comandos para probar si la política de autorización rechaza correctamente las solicitudes no válidas:

# Failure case
# Command to execute that tests connectivity to the service service-test.
# This is an invalid request and server will reject because the server
# authorization policy only allows GET requests.
TEST_CMD="wget -q -O - service-test --post-data='' ; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

El resultado esperado es similar al siguiente:

<RBAC: access denied HTTP/1.1 403 Forbidden>

Configura la seguridad de la puerta de enlace de entrada

En esta sección, se asume que completaste la sección de seguridad entre servicios, incluida la configuración de tu clúster de GKE con el inyector automático de sidecar, la creación de una autoridad certificadora y la creación de una política de extremos.

En esta sección, implementarás un proxy de Envoy como una puerta de enlace de entrada que finaliza las conexiones TLS y autoriza solicitudes de los clientes internos de un clúster.

Finalización de TLS en una puerta de enlace de entrada (haz clic para agrandar)
Finalización de TLS en una puerta de enlace de entrada (haz clic para agrandar)

A fin de configurar una puerta de enlace de entrada para finalizar TLS, haz lo siguiente:

  1. Implementa un servicio de Kubernetes al que se pueda acceder mediante una dirección IP interna del clúster
    1. La implementación consiste en un proxy de Envoy independiente que se expone como un servicio de Kubernetes y se conecta a Cloud Service Mesh.
  2. Crea una política de TLS de servidor para finalizar TLS.
  3. Crea una política de autorización para autorizar solicitudes entrantes.

Implementa un servicio de puerta de enlace de entrada en GKE

Ejecuta el siguiente comando para implementar el servicio de puerta de enlace de entrada en GKE:

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/gateway_sample_xdsv3.yaml | sed -e s/PROJECT_NUMBER_PLACEHOLDER/PROJNUM/g | sed -e s/NETWORK_PLACEHOLDER/default/g | sed -e s/DEMO_CLIENT_KSA_PLACEHOLDER/DEMO_CLIENT_KSA/g > gateway_sample.yaml

kubectl apply -f gateway_sample.yaml

El archivo gateway_sample.yaml es la especificación de la puerta de enlace de entrada. Las siguientes secciones describen algunas adiciones a la especificación.

Inhabilita la inserción de archivos adicionales de Cloud Service Mesh

La especificación gateway_sample.yaml implementa un proxy de Envoy como el único contenedor. En los pasos anteriores, Envoy se insertó como un sidecar a un contenedor de aplicación. Si deseas evitar que varias Envoy manejen las solicitudes, puedes inhabilitar la inserción de sidecar para este servicio de Kubernetes mediante la siguiente declaración:

sidecar.istio.io/inject: "false"

Activa el volumen correcto

La especificación gateway_sample.yaml activa el volumen gke-workload-certificates. Este volumen también se usa en la implementación de sidecar, pero el inyector de sidecar lo agrega de forma automática cuando detecta la anotación cloud.google.com/enableManagedCerts: "true". El volumen gke-workload-certificates contiene los certificados y las claves de SPIFFE administrados por GKE que firma la instancia del servicio de CA que configuraste.

Configura la dirección IP interna del clúster

Configura la puerta de enlace de entrada con un servicio de tipo ClusterInternal. Esto crea un nombre de host DNS que se resuelve de forma interna para mesh-gateway. Cuando un cliente envía una solicitud a mesh-gateway:443, Kubernetes enruta la solicitud de inmediato al puerto 8080 de la implementación de Envoy de la puerta de enlace de entrada.

Habilita TLS en una puerta de enlace de entrada

Usa estas instrucciones para habilitar TLS en una puerta de enlace de entrada.

  1. Crea un recurso de política de TLS de servidor para finalizar las conexiones TLS, con los valores en un archivo llamado server-tls-policy.yaml:

    description: tls server policy
    name: server-tls-policy
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. Importa la política de TLS del servidor:

    gcloud network-security server-tls-policies import server-tls-policy \
        --source=server-tls-policy.yaml --location=global
    
  3. Crea un mapa de URL nuevo que enrute todas las solicitudes al servicio de backend td-gke-service. La puerta de enlace de entrada controla las solicitudes entrantes y las envía a los pods que pertenecen al servicio de backend td-gke-service.

    gcloud compute url-maps create td-gke-ig-url-map \
       --default-service=td-gke-service
    
  4. Crea un nuevo proxy HTTPS de destino en el archivo td-gke-https-proxy.yaml y adjunta la política de TLS del servidor y el mapa de URL creados antes. Esto configura la puerta de enlace de entrada del proxy de Envoy para finalizar el tráfico TLS entrante.

    kind: compute#targetHttpsProxy
    name: td-gke-https-proxy
    proxyBind: true
    urlMap: https://www.googleapis.com/compute/beta/projects/PROJECT_ID/global/urlMaps/td-gke-ig-url-map
    serverTlsPolicy: projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
    
  5. Importa la política:

    gcloud compute target-https-proxies import td-gke-https-proxy \
       --global --source=td-gke-https-proxy.yaml
    
  6. Crea una regla de reenvío nueva y adjunta el proxy HTTPS de destino. De este modo, se configura el proxy de Envoy para que escuche en el puerto 8080 y aplique las políticas de enrutamiento y seguridad definidas en td-gke-https-proxy.

    gcloud compute forwarding-rules create td-gke-gateway-forwarding-rule --global \
      --load-balancing-scheme=INTERNAL_SELF_MANAGED --address=0.0.0.0 \
      --target-https-proxy=td-gke-https-proxy --ports 8080 \
      --network default
    
  7. De manera opcional, actualiza la política de autorización en los backends para permitir solicitudes cuando se cumplan todas las siguientes condiciones:

    • Solicitudes enviadas por DEMO_CLIENT_KSA. (La implementación de la puerta de enlace de entrada usa la cuenta de servicio DEMO_CLIENT_KSA).
    • Solicitudes con el host mesh-gateway o service-test
    • Puerto 8000

    No es necesario que ejecutes estos comandos, a menos que hayas configurado una política de autorización para tus backends. Si no hay una política de autorización en el extremo o no contiene la coincidencia principal o de host en la política de autorización, la solicitud se permite sin este paso. Agrega estos valores a authz-policy.yaml.

    action: ALLOW
    name: authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
      destinations:
      - hosts:
        - service-test
        - mesh-gateway
        ports:
        - 8000
        methods:
        - GET
    
  8. Importa la política:

    gcloud network-security authorization-policies import authz-policy \
      --source=authz-policy.yaml \
      --location=global
    

Valida la implementación de la puerta de enlace de entrada

Usa un contenedor nuevo llamado debug para enviar solicitudes a la puerta de enlace de entrada a fin de validar la implementación.

En la siguiente especificación, la anotación "sidecar.istio.io/inject":"false" evita que el inyector de sidecar de Cloud Service Mesh inserte de forma automática un proxy de sidecar. No hay ningún sidecar para ayudar al contenedor debug en el enrutamiento de solicitudes. El contenedor debe conectarse a la puerta de enlace de entrada para el enrutamiento.

La especificación incluye la marca --no-check-certificate, que ignora la validación del certificado del servidor. El contenedor debug no tiene los certificados de validación de la autoridad certificadora que se necesitan en los certificados válidos firmados por el servicio de CA que usa la puerta de enlace de entrada para finalizar TLS.

En un entorno de producción, te recomendamos descargar el certificado de validación del servicio de CA y activarlo o instalarlo en tu cliente. Después de instalar el certificado de validación, quita la opción --no-check-certificate del comando wget.

Ejecuta el siguiente comando:

kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway; echo"

Verás un resultado similar a este:

GET / HTTP/1.1
Host: 10.68.7.132
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
x-envoy-expected-rq-timeout-ms: 15000
x-envoy-internal: true
x-request-id: 5ae429e7-0e18-4bd9-bb79-4e4149cf8fef
x-forwarded-for: 10.64.0.53
x-forwarded-proto: https
content-length: 0
user-agent: Wget

Ejecuta el siguiente comando de prueba negativa:

# Negative test
# Expect this to fail because gateway expects TLS.
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - http://mesh-gateway:443/headers; echo"

Verás un resultado similar al siguiente:

wget: error getting response: Connection reset by peer

Ejecuta el siguiente comando de prueba negativa:

# Negative test.
# AuthorizationPolicy applied on the endpoints expect a GET request. Otherwise
# the request is denied authorization.
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway --post-data=''; echo"

Verás un resultado similar al siguiente:

HTTP/1.1 403 Forbidden
wget: server returned error: HTTP/1.1 403 Forbidden

Configura una política de autorización para la puerta de enlace de entrada

La política de autorización que configuras aquí permite que la puerta de enlace de entrada permita las solicitudes a la malla cuando se cumplan todas las condiciones siguientes:

  • Host: mesh-gateway
  • Puerto 8080
  • ruta de acceso: *
  • Método HTTP GET
  1. Crea una política de autorización en el archivo authz-gateway-policy.yaml:

    action: ALLOW
    name: authz-gateway-policy
    rules:
    - destinations:
      - hosts:
        - mesh-gateway
        ports:
        - 8080
        methods:
        - GET
    
  2. Importa los valores en el archivo:

    gcloud network-security authorization-policies import authz-gateway-policy \
       --source=authz-gateway-policy.yaml  --location=global
    
  3. Para editar el archivo td-gke-https-proxy.yaml, agrega lo siguiente:

    authorizationPolicy: projects/PROJECT_ID/locations/global/authorizationPolicies/authz-gateway-policy
    
  4. Vuelve a importar el archivo td-gke-https-proxy.yaml:

    gcloud compute target-https-proxies import td-gke-https-proxy \
       --global --source=td-gke-https-proxy.yaml
    

Valida la implementación

Ejecuta el siguiente comando para validar tu implementación.

# On your localhost.
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway; echo"

Verás un resultado similar al siguiente:

GET / HTTP/1.1
Host: 35.196.50.2
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
x-envoy-expected-rq-timeout-ms: 15000
user-agent: curl/7.72.0
x-forwarded-proto: https
content-length: 0
x-envoy-internal: true
x-request-id: 98bec135-6df8-4082-8edc-b2c23609295a
accept: */*
x-forwarded-for: 10.142.0.7

Ejecuta el siguiente comando de prueba negativa:

# Negative test. Expect failure because only POST method is allowed by \
# authz-gateway-policy
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway/ --post-data=''; echo"

Verás un resultado similar al siguiente:

wget: server returned error: HTTP/1.1 403 Forbidden

Borra la implementación

También puedes ejecutar estos comandos para borrar la implementación que creaste con esta guía.

Para borrar el clúster, ejecuta este comando:

gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet

Para borrar los recursos que creaste, ejecuta estos comandos:

gcloud compute forwarding-rules delete td-gke-forwarding-rule --global --quiet
gcloud compute forwarding-rules delete td-gke-gateway-forwarding-rule --global \
    --quiet
gcloud compute target-http-proxies delete td-gke-proxy  --quiet
gcloud compute target-https-proxies delete td-gke-https-proxy  --quiet
gcloud compute url-maps delete td-gke-url-map  --quiet
gcloud compute url-maps delete td-gke-ig-url-map  --quiet
gcloud compute backend-services delete td-gke-service --global --quiet
cloud compute network-endpoint-groups delete service-test-neg --zone ZONE --quiet
gcloud compute firewall-rules delete fw-allow-health-checks --quiet
gcloud compute health-checks delete td-gke-health-check --quiet
gcloud network-services endpoint-policies delete ep \
    --location=global --quiet
gcloud network-security authorization-policies delete authz-gateway-policy \
   --location=global --quiet
gcloud network-security authorization-policies delete authz-policy \
    --location=global --quiet
gcloud network-security client-tls-policies delete client-mtls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-tls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-mtls-policy \
    --location=global --quiet

Limitaciones

La seguridad del servicio de Cloud Service Mesh solo es compatible con GKE. No puedes implementar la seguridad del servicio con Compute Engine.

Soluciona problemas

Esta sección contiene información sobre cómo solucionar los problemas que encuentras durante la configuración del servicio de seguridad.

Fallas de conexión

Si la conexión falla con un error upstream connect o disconnect/reset before headers, examina los registros de Envoy, en los que puedes ver uno de los siguientes mensajes de registro:

gRPC config stream closed: 5, Requested entity was not found

gRPC config stream closed: 2, no credential token is found

Si ves estos errores en el registro de Envoy, es probable que el token de la cuenta de servicio esté activado de forma incorrecta o que use un audience diferente, o ambos.

Para obtener más información, consulta Mensajes de error en los registros de Envoy indican un problema de configuración.

No se crearon los Pods

Para solucionar este problema, consulta Soluciona problemas de implementaciones automáticas de pods de GKE.

Envoy no se autentica con Cloud Service Mesh

Cuando Envoy (envoy-proxy) se conecta a Cloud Service Mesh para recuperar la configuración de xDS, usa Workload Identity Federation para GKE y la cuenta de servicio predeterminada de la VM de Compute Engine (a menos que se haya modificado el arranque). Si la autenticación falla, Envoy no entra en el estado de listo.

No se puede crear un clúster con --workload-identity-certificate-authority flag

Si ves este error, asegúrate de que estás ejecutando la versión más reciente de Google Cloud CLI:

gcloud components update

Los pods permanecen en un estado pendiente

Si los Pods permanecen en estado pendiente durante el proceso de configuración, aumenta los recursos de CPU y memoria para los pods en tu especificación de implementación.

No se pudo crear el clúster con la marca --enable-mesh-certificates

Asegúrate de ejecutar la versión más reciente de la CLI de gcloud:

gcloud components update

Ten en cuenta que la marca --enable-mesh-certificates solo funciona con gcloud beta.

Los pods no se inician

Es posible que los pods que usan certificados de malla de GKE no se inicien si falla el aprovisionamiento de certificados. Esto puede suceder en situaciones como las siguientes:

  • WorkloadCertificateConfig o TrustConfig no están bien configurados o no se encuentran.
  • No se aprueban las CSR.

Para verificar si el aprovisionamiento de certificados falla, revisa los eventos del pod.

  1. Verifica el estado del Pod:

    kubectl get pod -n POD_NAMESPACE POD_NAME
    

    Reemplaza lo siguiente:

    • POD_NAMESPACE: es el espacio de nombres del Pod.
    • POD_NAME: es el nombre del Pod.
  2. Revisa los eventos recientes de tu pod:

    kubectl describe pod -n POD_NAMESPACE POD_NAME
    
  3. Si falla el aprovisionamiento de certificados, verás un evento con Type=Warning, Reason=FailedMount, From=kubelet y un campo Message que comienza con MountVolume.SetUp failed for volume "gke-workload-certificates". El campo Message contiene información para solucionar problemas.

    Events:
      Type     Reason       Age                From       Message
      ----     ------       ----               ----       -------
      Warning  FailedMount  13s (x7 over 46s)  kubelet    MountVolume.SetUp failed for volume "gke-workload-certificates" : rpc error: code = Internal desc = unable to mount volume: store.CreateVolume, err: unable to create volume "csi-4d540ed59ef937fbb41a9bf5380a5a534edb3eedf037fe64be36bab0abf45c9c": caPEM is nil (check active WorkloadCertificateConfig)
    
  4. Consulta los siguientes pasos de solución de problemas si el motivo por el que tus pods no se inician es porque hay objetos mal configurados o CSR rechazadas.

La configuración de WorkloadCertificateConfig o TrustConfig es incorrecta

Asegúrate de haber creado los objetos WorkloadCertificateConfig y TrustConfig de forma correcta. Puedes diagnosticar una configuración incorrecta en cualquiera de estos objetos mediante kubectl.

  1. Recupera el estado actual.

    Para WorkloadCertificateConfig:

    kubectl get WorkloadCertificateConfig default -o yaml
    

    Para TrustConfig:

    kubectl get TrustConfig default -o yaml
    
  2. Inspecciona el resultado del estado. Un objeto válido tendrá una condición con type: Ready y status: "True".

    status:
      conditions:
      - lastTransitionTime: "2021-03-04T22:24:11Z"
        message: WorkloadCertificateConfig is ready
        observedGeneration: 1
        reason: ConfigReady
        status: "True"
        type: Ready
    

    En el caso de los objetos no válidos, aparece status: "False" en su lugar. Los campos reason y message contienen detalles adicionales sobre la solución de problemas.

Las CSR no están aprobadas.

Si algo sale mal durante el proceso de aprobación de la CSR, puedes verificar los detalles del error en las condiciones de type: Approved y type: Issued de la CSR.

  1. Enumera las CSR relevantes mediante kubectl:

    kubectl get csr \
      --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
    
  2. Elige una CSR que tenga el estado Approved y no Issued, o que no tenga el estado Approved.

  3. Obtén detalles de la CSR seleccionada con kubectl:

    kubectl get csr CSR_NAME -o yaml
    

    Reemplaza CSR_NAME por el nombre de la CSR que elegiste.

Una CSR válida tiene una condición con type: Approved y status: "True", y un certificado válido en el campo status.certificate:

status:
  certificate: <base64-encoded data>
  conditions:
  - lastTransitionTime: "2021-03-04T21:58:46Z"
    lastUpdateTime: "2021-03-04T21:58:46Z"
    message: Approved CSR because it is a valid SPIFFE SVID for the correct identity.
    reason: AutoApproved
    status: "True"
    type: Approved

La información de solución de problemas para CSR no válidas aparece en los campos message y reason.

Las aplicaciones no pueden usar las credenciales de mTLS emitidas

  1. Verifica que el certificado no haya vencido:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  2. Comprueba que tu aplicación admita el tipo de clave que usaste.

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
    
  3. Comprueba que la CA emisora use la misma familia de claves que la clave del certificado.

    1. Obtén el estado de la instancia del servicio de CA (vista previa):

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      Reemplaza lo siguiente:

      • ISSUING_CA_TYPE: el tipo de CA de la emisión, que debe ser subordinates o roots.
      • ISSUING_CA_NAME: el nombre de la CA emisora.
      • ISSUING_CA_LOCATION: la región de la CA emisora.
    2. Comprueba que el keySpec.algorithm en el resultado sea el mismo algoritmo de clave que definiste en el manifiesto de YAML WorkloadCertificateConfig. El resultado se verá así:

      config:
        ...
        subjectConfig:
          commonName: td-sub-ca
          subject:
            organization: TestOrgLLC
          subjectAltName: {}
      createTime: '2021-05-04T05:37:58.329293525Z'
      issuingOptions:
        includeCaCertUrl: true
      keySpec:
        algorithm: RSA_PKCS1_2048_SHA256
       ...
      

Los certificados se rechazan

  1. Verifica que la aplicación par use el mismo paquete de confianza para verificar el certificado.
  2. Verifica que el certificado no haya vencido:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  3. Verifica que el código de cliente, si no usas la API de recarga de credenciales de gRPC para Go, actualice las credenciales del sistema de archivos de forma periódica.

  4. Verifica que las cargas de trabajo estén en el mismo dominio de confianza que la CA. Los certificados de malla de GKE admiten la comunicación entre cargas de trabajo en un solo dominio de confianza.