Automatiza la administración de certificados TLS para la puerta de enlace de entrada de Cloud Service Mesh mediante Certificate Authority Service

En este instructivo, se muestra a los operadores de plataforma cómo usar el emisor de Certificate Authority Service (servicio de AC) para la herramienta cert-manager para automatizar la administración del certificado TLS para la puerta de enlace de entrada de Cloud Service Mesh. Los certificados permiten que la puerta de enlace de entrada finalice HTTPS y otro tráfico de TLS y mTLS que se origina en los clientes de la nube privada virtual (VPC), pero fuera de la malla de servicios. En el instructivo, se supone que estás familiarizado con los certificados de Kubernetes y TLS.

Introducción

Cloud Service Mesh aprovisiona certificados TLS para cada carga de trabajo en la malla de servicios. Estos certificados permiten la comunicación encriptada y TLS autenticada de forma mutua (mTLS) entre las cargas de trabajo en la malla de servicios. Una de las CA admitidas emite y firma los certificados.

Sin embargo, Cloud Service Mesh no aprovisiona de forma automática los certificados a la puerta de enlace de entrada para el tráfico que ingresa a la malla de servicios. Una solución común es usar la herramienta de código abierto cert-manager para automatizar la administración de los certificados de la puerta de enlace de entrada.

La herramienta cert-manager solicita certificados de una entidad emisora, que representa una autoridad certificadora (CA). Certificate Authority Service es un servicio de Google Cloud que te permite crear tu propia AC privada. La herramienta cert-manager puede solicitar certificados del servicio de CA mediante la entidad emisora externa para el servicio de CA de código abierto.

Una CA privada puede emitir certificados TLS que autentican y encriptan el tráfico dentro de una red interna. Las puertas de enlace de entrada de Cloud Service Mesh suelen configurarse para permitir el tráfico entrante de los clientes que se encuentran dentro de la VPC, pero fuera de la malla de servicios. En el tráfico de red interno, puedes usar una CA privada en el servicio de CA a fin de emitir certificados para la puerta de enlace de entrada.

En este instructivo, se muestra cómo configurar la herramienta cert-manager y el emisor del servicio de CA para automatizar el aprovisionamiento y la renovación de los certificados TLS para la puerta de enlace de entrada. La herramienta cert-manager aprovisiona certificados como recursos de Secret de Kubernetes de tipo TLS. Cuando la herramienta cert-manager renueva un certificado, actualiza el recurso secreto con un certificado nuevo. La puerta de enlace de entrada ejecuta el proxy de Envoy y admite el servicio de descubrimiento de secretos (SDS) de Envoy. El SDS permite que la puerta de enlace de entrada comience a usar un certificado nuevo sin necesidad de que un administrador reinicie o vuelva a cargar el proceso.

Los proxies de sidecar que forman parte de la malla pueden obtener certificados TLS de la autoridad certificadora de CA o de Cloud Service Mesh. En este instructivo, usarás el servicio de CA para los certificados de puerta de enlace de entrada y proxy. Esto te permite usar una CA raíz para todos los certificados TLS.

En el siguiente diagrama, se muestran los recursos que aprovisionarás en este instructivo. Aprovisionas un balanceador de cargas de red de transferencia interno para la puerta de enlace de entrada. El balanceador de cargas de red de transferencia interno no es un proxy, por lo que no finaliza las conexiones TCP ni realiza protocolos de enlace TLS. En su lugar, enruta las conexiones a los Pods de la implementación istio-ingressgateway.

El Secret hello-example-com-credential contiene un certificado y una clave privada. La puerta de enlace hello configura los Pods de la implementación istio-ingressgateway a fin de usar este certificado y una clave privada para realizar protocolos de enlace TLS para las solicitudes con el nombre de host hello.example.com.

Administración de mtls con servicio de CA

Los pods de la implementación google-cas-issuer en el espacio de nombres cert-manager solicitan certificados de la CA que creas en el servicio de CA. Crea una vinculación de política de administración de identidades y accesos que permita que los Pods ca-service-isser actúen en nombre de una cuenta de servicio de Google mediante Workload Identity Federation for GKE. Puedes otorgar a esta cuenta de servicio de Google el permiso para solicitar certificados de tu CA en el servicio de CA mediante la creación de una vinculación de política de IAM en tu grupo de CA.

Objetivos

Costos

En este instructivo, se usan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Cuando finalices este instructivo, podrás borrar los recursos creados para evitar que se te siga facturando. Para obtener más información, consulta Cómo realizar una limpieza.

Antes de comenzar

  1. En la consola de Google Cloud, ve a la página de selección de proyecto y, luego, selecciona o crea un proyecto.

  2. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  3. En la consola de Google Cloud ve a Cloud Shell.

    En la parte inferior de la consola de Google Cloud, se abre una sesión de Cloud Shell que muestra una ventana emergente con una línea de comandos. Usa Cloud Shell para ejecutar todos los comandos de este instructivo.

  4. Configura el proyecto de la consola de Google Cloud que deseas usar para este instructivo:

    gcloud config set core/project PROJECT_ID
    

    Reemplaza PROJECT_ID por el ID del proyecto de tu proyecto de Cloud.

    En el diálogo Autorizar Cloud Shell, haz clic en Autorizar. Si haces clic en Autorizar, permites que los comandos gcloud que ejecutas en Cloud Shell usen tus credenciales de usuario para autenticarse en las API de Google.

  5. Habilita Resource Manager, GKE, GKE Hub, la autoridad certificadora de Cloud Service Mesh y las APIs del servicio de AC:

    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        container.googleapis.com \
        gkehub.googleapis.com \
        meshca.googleapis.com \
        privateca.googleapis.com
    

Configura el servicio de CA

En esta sección, crearás una CA raíz y dos CA subordinadas en un servicio de CA. Una CA subordinada emite certificados a la puerta de enlace de entrada y la otra CA subordina emite certificados a los proxies de sidecar en la malla.

A fin de hacerlo más simple, en este instructivo, usas el mismo proyecto para el clúster de GKE y las CA subordinadas y de raíz. En tu propio entorno, puedes usar un proyecto diferente para el clúster de GKE y las CA.

  1. En Cloud Shell, crea un grupo de CA para usar con la CA raíz:

    gcloud privateca pools create ROOT_CA_POOL \
        --location CA_LOCATION \
        --tier enterprise
    
    • ROOT_CA_POOL es el nombre del grupo de CA. Por ejemplo, root-ca-pool-tutorial
    • CA_LOCATION es la ubicación del grupo de CA. Por ejemplo, us-central1.

    Puedes enumerar las ubicaciones del Servicio de CA disponibles mediante este comando: gcloud privateca locations list

  2. Crea y habilita una CA raíz:

    gcloud privateca roots create ROOT_CA \
        --auto-enable \
        --key-algorithm ec-p384-sha384 \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --subject "CN=Example Root CA, O=Example Organization" \
        --use-preset-profile root_unconstrained
    
    • ROOT_CA es el nombre que deseas usar para la CA raíz. Por ejemplo, root-ca-tutorial
  3. Crea un grupo de CA para usar con la CA subordinada que emite certificados a la puerta de enlace de entrada:

    gcloud privateca pools create SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --tier devops
    
    • SUBORDINATE_CA_POOL_GATEWAYS es el nombre del grupo de CA. Por ejemplo, subordinate-ca-mtls-pool-gateways-tutorial
  4. Crea y habilita la CA subordinada que emite certificados a la puerta de enlace de entrada:

    gcloud privateca subordinates create SUBORDINATE_CA_GATEWAYS \
        --auto-enable \
        --issuer-location CA_LOCATION \
        --issuer-pool ROOT_CA_POOL \
        --key-algorithm ec-p256-sha256 \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_GATEWAYS \
        --subject "CN=Example Gateway mTLS CA, O=Example Organization" \
        --use-preset-profile subordinate_mtls_pathlen_0
    
    • SUBORDINATE_CA_GATEWAYS es el nombre que deseas usar para la CA subordinada. Por ejemplo, subordinate-ca-mtls-gateways-tutorial
    • La marca --use-preset-profile configura la CA subordinada para usar el perfil de certificado Subordinada mTLS. Este perfil permite que la CA subordinada emita certificados TLS de cliente y de servidor para mTLS.

    Si deseas que la puerta de enlace de entrada use una TLS simple en lugar de mTLS, la CA subordinada solo necesita emitir certificados TLS del servidor. En este caso, puedes usar el perfil de certificado TLS subordinado (subordinate_server_tls_pathlen_0).

  5. Crea una política de emisión de certificado:

    cat << EOF > policy.yaml
    baselineValues:
      keyUsage:
        baseKeyUsage:
          digitalSignature: true
          keyEncipherment: true
        extendedKeyUsage:
          serverAuth: true
          clientAuth: true
      caOptions:
        isCa: false
    identityConstraints:
      allowSubjectPassthrough: false
      allowSubjectAltNamesPassthrough: true
      celExpression:
        expression: subject_alt_names.all(san, san.type == URI && san.value.startsWith("spiffe://PROJECT_ID.svc.id.goog/ns/") )
    EOF
    

    Esta política de emisión restringe las CA a fin de que solo emitan certificados para cargas de trabajo en la malla.

  6. Crea un grupo de CA para usarlo con la CA subordinada que emite certificados a los proxies de sidecar en la malla. Aplica la política de emisión al grupo de CA:

    gcloud privateca pools create SUBORDINATE_CA_POOL_SIDECARS \
     --issuance-policy policy.yaml \
     --location CA_LOCATION \
     --tier devops
    
    • SUBORDINATE_CA_POOL_SIDECARS es el nombre del grupo de CA. Por ejemplo, subordinate-ca-mtls-pool-sidecars-tutorial
  7. Crea y habilita la CA subordinada que emite certificados a los proxies de sidecar en la malla:

    gcloud privateca subordinates create SUBORDINATE_CA_SIDECARS \
        --auto-enable \
        --issuer-location CA_LOCATION \
        --issuer-pool ROOT_CA_POOL \
        --key-algorithm ec-p256-sha256 \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_SIDECARS \
        --subject "CN=Example Sidecar mTLS CA, O=Example Organization" \
        --use-preset-profile subordinate_mtls_pathlen_0
    
    • SUBORDINATE_CA_GATEWAYS es el nombre que deseas usar para la CA subordinada. Por ejemplo, subordinate-ca-mtls-sidecars-tutorial

Cree un clúster de Google Kubernetes Engine

  1. En Cloud Shell, crea un clúster de GKE:

    gcloud container clusters create CLUSTER_NAME \
        --enable-ip-alias \
        --num-nodes 4 \
        --release-channel regular \
        --scopes cloud-platform \
        --workload-pool PROJECT_ID.svc.id.goog \
        --zone ZONE
    

    Reemplaza CLUSTER_NAME por la zona que deseas usar para el clúster. Por ejemplo, asm-ingress-cert-manager-ca-service

    Reemplaza ZONE por la zona que deseas usar para el clúster. Por ejemplo, us-central1-f

    Ten en cuenta lo siguiente sobre el comando:

    • La marca --release-channel selecciona el canal de versiones de GKE para el clúster.
    • Cloud Service Mesh y la entidad emisora del servicio de AC para la herramienta cert-manager requieren que establezcas el permiso cloud-platform en los nodos del clúster.
    • El argumento --workload-pool habilita la federación de identidades para cargas de trabajo para GKE, que permite que la cuenta de servicio de Kubernetes del emisor del servicio de AC actúe en nombre de una cuenta de servicio de Google. Esta suplantación significa que los Pods de la entidad emisora de la CA pueden acceder a la API sin que se descargue un archivo de claves para la cuenta de servicio de Google.
  2. Otorga permisos de administrador de clúster a tu cuenta de usuario:

    kubectl create clusterrolebinding cluster-admin-binding \
        --clusterrole cluster-admin \
        --user $(gcloud config get-value core/account)
    

    Necesitas los permisos que proporciona el ClusterRole cluster-admin de Kubernetes para crear las reglas de control de acceso basado en funciones (RBAC) para Cloud Service Mesh y para instalar la herramienta cert-manager.

Instala el plano de control de Anthos Service Mesh

En este instructivo, instalarás Cloud Service Mesh administrado para un clúster de GKE en Google Cloud, con todos los recursos en un proyecto. En tu propio entorno, puedes aplicar la solución que se describe en este documento mediante Cloud Service Mesh administrado o un plano de control en el clúster.

Cloud Service Mesh proporciona una variedad de opciones de instalación para diferentes situaciones. Después de completar este instructivo, te recomendamos que revises las guías de instalación para seleccionar la opción que mejor se adapte a tu entorno.

  1. En Cloud Shell, descarga la herramienta de instalación asmcli:

    curl --location --output asmcli https://storage.googleapis.com/csm-artifacts/asm/asmcli_1.15
    
    chmod +x asmcli
    

    Usa asmcli para instalar el plano de control de Cloud Service Mesh.

  2. Instala el plano de control de Cloud Service Mesh:

    ./asmcli install \
        --ca gcp_cas \
        --ca_pool projects/PROJECT_ID/locations/CA_LOCATION/caPools/SUBORDINATE_CA_POOL_SIDECARS \
        --cluster_location ZONE \
        --cluster_name CLUSTER_NAME \
        --enable_all \
        --enable_registration \
        --fleet_id PROJECT_ID \
        --managed \
        --output_dir asm-files \
        --project_id PROJECT_ID \
        --verbose
    

    La instalación tarda varios minutos. Cuando se complete la instalación, verás el siguiente resultado:

    asmcli: Successfully installed ASM.
    

Instala la puerta de enlace de entrada

  1. En Cloud Shell, crea un espacio de nombres de Kubernetes para la puerta de enlace de entrada:

    kubectl create namespace GATEWAY_NAMESPACE
    
    • GATEWAY_NAMESPACE es el nombre del espacio de nombres que deseas usar para la puerta de enlace de entrada. Por ejemplo, istio-ingress
  2. Reserva una dirección IP interna estática para usar en el balanceador de cargas de red de transferencia interno de la puerta de enlace de entrada:

    LOAD_BALANCER_IP=$(gcloud compute addresses create \
        asm-ingress-gateway-ilb \
        --region REGION \
        --subnet default \
        --format 'value(address)')
    
    • Reemplaza REGION por la región que contiene las zonas que usan los nodos del clúster de GKE. Por ejemplo, si tu clúster usa la zona us-central1-f, reemplaza REGION por us-central1.

    Mediante este comando, se reserva una dirección IP de la subred predeterminada en la región que especificas.

  3. Crea un manifiesto del operador para la puerta de enlace de entrada:

    cat << EOF > ingressgateway-operator.yaml
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      name: ingressgateway-operator
      annotations:
        config.kubernetes.io/local-config: "true"
    spec:
      profile: empty
      revision: asm-managed
      components:
        ingressGateways:
        - name: istio-ingressgateway
          namespace: GATEWAY_NAMESPACE
          enabled: true
          k8s:
            overlays:
            - apiVersion: apps/v1
              kind: Deployment
              name: istio-ingressgateway
              patches:
              - path: spec.template.metadata.annotations
                value:
                  inject.istio.io/templates: gateway
              - path: spec.template.metadata.labels.sidecar\.istio\.io/inject
                value: "true"
              - path: spec.template.spec.containers[name:istio-proxy]
                value:
                  name: istio-proxy
                  image: auto
            service:
              loadBalancerIP: $LOAD_BALANCER_IP
            serviceAnnotations:
              networking.gke.io/load-balancer-type: Internal
              networking.gke.io/internal-load-balancer-allow-global-access: "true"
    EOF
    

    Ten en cuenta lo siguiente sobre el manifiesto del operador:

  4. Crea el manifiesto de instalación de la puerta de enlace de entrada con el manifiesto del operador y la herramienta istioctl que descargó la secuencia de comandos asmcli cuando instalaste el plano de control:

    ./asm-files/istioctl manifest generate \
        --filename ingressgateway-operator.yaml \
        --output ingressgateway
    
  5. Instala la puerta de enlace de entrada:

    kubectl apply --recursive --filename ingressgateway/
    

Instala la herramienta cert-manager

  1. En Cloud Shell, descarga y aplica el manifiesto de instalación de la herramienta cert-manager:

    CERT_MANAGER_VERSION=v1.5.4
    
    curl --location --output cert-manager.yaml "https://github.com/jetstack/cert-manager/releases/download/${CERT_MANAGER_VERSION}/cert-manager.yaml"
    
    kubectl apply --filename cert-manager.yaml
    

    La instalación de la herramienta cert-manager tarda aproximadamente un minuto en completarse.

Instala el controlador de la entidad emisora del servicio de CA

El controlador de la entidad emisora del Servicio de AC permite que la herramienta cert-manager solicite certificados mediante el servicio de AC. El controlador usa el mecanismo de extensión de la entidad emisora externa de la herramienta de cert-manager.

  1. En Cloud Shell, crea una cuenta de servicio de Google:

    gcloud iam service-accounts create CAS_ISSUER_GSA \
        --display-name "CA Service issuer for cert-manager"
    
    • CAS_ISSUER_GSA es el nombre de la cuenta de servicio de Google. Por ejemplo, cert-manager-ca-service-issuer

    El controlador de la entidad emisora de Certificate Authority Service usa esta cuenta de servicio de Google para autenticarse en las API de Certificate Authority Service.

  2. Crea una vinculación de políticas de administración de identidades y accesos que permita que la cuenta de servicio de controlador de Certificate Authority Service solicite los certificados del grupo de CA que contenga la CA subordinada:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    
  3. Descarga el manifiesto de instalación del controlador de la entidad emisora de Certificate Authority Service:

    CAS_ISSUER_VERSION=v0.5.3
    
    curl --location --output ca-service-issuer.yaml "https://github.com/jetstack/google-cas-issuer/releases/download/${CAS_ISSUER_VERSION}/google-cas-issuer-${CAS_ISSUER_VERSION}.yaml"
    
  4. Crea una vinculación de política de IAM para permitir que la cuenta de servicio de Kubernetes ksa-google-cas-issuer en el espacio de nombres cert-manager actúe en nombre de la cuenta de servicio de Google (GSA) mediante la federación de identidades para cargas de trabajo para GKE:

    gcloud iam service-accounts add-iam-policy-binding \
     CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[cert-manager/ksa-google-cas-issuer]" \
        --role roles/iam.workloadIdentityUser
    

    Los Pods del controlador de la entidad emisora de servicios de CA usan la cuenta de servicio de Kubernetes ksa-google-cas-issuer.

  5. Instala el controlador de entidad emisora del servicio de CA en tu clúster de GKE:

    kubectl apply --filename ca-service-issuer.yaml
    
  6. Agrega la anotación iam.gke.io/gcp-service-account de Workload Identity Federation for GKE a la cuenta de servicio de Kubernetes que usan los Pods del controlador de la entidad emisora del servicio de AC:

    kubectl annotate serviceaccount ksa-google-cas-issuer --namespace cert-manager \
       "iam.gke.io/gcp-service-account=CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com"
    

    Esta anotación informa a GKE que la cuenta de servicio de Kubernetes puede actuar en nombre de una cuenta de servicio de Google para acceder a las API de Google.

Crea una entidad emisora de certificados

  1. En Cloud Shell, crea y aplica un manifiesto de GoogleCASIssuer:

    cat << EOF > gateway-cas-issuer.yaml
    apiVersion: cas-issuer.jetstack.io/v1beta1
    kind: GoogleCASIssuer
    metadata:
      name: gateway-cas-issuer
      namespace: GATEWAY_NAMESPACE
    spec:
      caPoolId: SUBORDINATE_CA_POOL_GATEWAYS
      location: CA_LOCATION
      project: PROJECT_ID
    EOF
    
    kubectl apply --filename gateway-cas-issuer.yaml
    

    La entidad emisora permite que la herramienta cert-manager aprovisione los certificados del grupo de CA subordinado en tu espacio de nombres de la puerta de enlace de entrada.

Implementar una aplicación de muestra

En esta sección, debes verificar que la herramienta cert-manager pueda usar la entidad emisora del servicio de CA para obtener certificados del servicio de CA. Para verificar, debes implementar una aplicación de muestra con configuración de enrutamiento de solicitudes y un certificado para la puerta de enlace de entrada.

  1. En Cloud Shell, crea un espacio de nombres para los recursos de la aplicación de ejemplo:

    cat << EOF > sample-app-namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: APP_NAMESPACE
      annotations:
        mesh.cloud.google.com/proxy: '{"managed":"true"}'
      labels:
        istio.io/rev: asm-managed
    EOF
    
    kubectl apply --filename sample-app-namespace.yaml
    
    • APP_NAMESPACE es el nombre del espacio de nombres para la aplicación de ejemplo. Por ejemplo, sample-app

    La anotación mesh.cloud.google.com/proxy habilita el plano de datos administrado para el espacio de nombres.

    La etiqueta istio.io/rev: asm-managed selecciona el canal de versiones regular para el plano de datos administrado en el espacio de nombres de la aplicación de muestra. Cambia el valor de esta etiqueta si usas los canales de versiones rápidos o estables.

  2. Crea un recurso de implementación para la aplicación de ejemplo:

    cat << EOF > deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello
      namespace: APP_NAMESPACE
      labels:
        app: hello
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: hello
      template:
        metadata:
          labels:
            app: hello
        spec:
          containers:
          - image: gcr.io/google-samples/hello-app:1.0
            name: hello-app
            ports:
            - containerPort: 8080
    EOF
    
    kubectl apply --filename deployment.yaml
    
  3. Crea un recurso de Service para la aplicación de ejemplo:

    cat << EOF > service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: SERVICE_NAME
      namespace: APP_NAMESPACE
    spec:
      ports:
      - name: http-hello
        port: 8080
      selector:
        app: hello
      type: ClusterIP
    EOF
    
    kubectl apply --filename service.yaml
    
    • SERVICE_NAME es el nombre del servicio. Por ejemplo, hello.
  4. Crea un recurso de certificado para el nombre de dominio hello.example.com con la entidad emisora del certificado:

    cat << EOF > certificate.yaml
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: hello-example-com-certificate
      namespace: GATEWAY_NAMESPACE
    spec:
      secretName: hello-example-com-credential
      commonName: hello.example.com
      dnsNames:
      - hello.example.com
      duration: 24h
      renewBefore: 8h
      issuerRef:
        group: cas-issuer.jetstack.io
        kind: GoogleCASIssuer
        name: gateway-cas-issuer
    EOF
    
    kubectl apply --filename certificate.yaml
    

    El espacio de nombres del certificado debe coincidir con el espacio de nombres de la puerta de enlace de entrada. Por lo general, solo los administradores de la plataforma pueden cambiar los recursos en este espacio de nombres, ya que los cambios pueden afectar a toda la malla de servicios. La herramienta cert-manager crea el recurso secreto para el certificado TLS en el mismo espacio de nombres. Esto significa que los administradores de la aplicación no necesitan tener acceso al espacio de nombres de la puerta de enlace de entrada.

    Puedes agregar nombres de host adicionales en la lista dnsNames del certificado. Estos nombres de host se incluyen en el certificado como Nombres alternativos de sujeto (SAN).

  5. Crea un recurso Gateway para la aplicación de ejemplo:

    cat << EOF > gateway.yaml
    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: GATEWAY_NAME
      namespace: GATEWAY_NAMESPACE
    spec:
      selector:
        istio: ingressgateway
      servers:
      - hosts:
        - APP_NAMESPACE/hello.example.com
        port:
          name: https-hello
          number: 443
          protocol: HTTPS
        tls:
          credentialName: hello-example-com-credential
          mode: MUTUAL
    EOF
    
    kubectl apply --filename gateway.yaml
    
    • GATEWAY_NAME es el nombre de la puerta de enlace. Por ejemplo, hello
    • El campo credentialName en la puerta de enlace coincide con el campo secretName en el certificado. La herramienta cert-manager crea un secreto de Kubernetes con el certificado TLS del servicio de CA. Este certificado permite que la puerta de enlace de entrada finalice el tráfico de TLS destinado a hello.example.com.

    El manifiesto de Gateway especifica TLS (mTLS) MUTUAL. Si deseas configurar la puerta de enlace para TLS normal, establece el modo TLS de la puerta de enlace en SIMPLE.

  6. Crea un recurso VirtualService para la aplicación de ejemplo:

    cat << EOF > virtual-service.yaml
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: hello
      namespace: APP_NAMESPACE
    spec:
      hosts:
      - hello.example.com
      gateways:
      - GATEWAY_NAMESPACE/GATEWAY_NAME
      http:
      - route:
        - destination:
            host: SERVICE_NAME
            port:
              number: 8080
    EOF
    
    kubectl apply --filename virtual-service.yaml
    

    El objeto Gateway y VirtualService usan diferentes espacios de nombres. En este patrón común, se restringen los cambios al enrutamiento basado en el host en Gateway a los administradores de la plataforma que tienen permisos para cambiar recursos en el espacio de nombres de la puerta de enlace de entrada.

    Los administradores de aplicaciones con permisos para editar el VirtualService en el espacio de nombres de la aplicación de ejemplo pueden cambiar el enrutamiento por otros campos de solicitud, como la ruta de URL, sin coordinar con los administradores de la plataforma.

Si deseas explorar otras opciones de configuración, lee la documentación de la API para los recursos de Certificate, Gateway y VirtualService.

Puedes aplicar políticas de autenticación y autorización al tráfico que ingresa a la malla de servicios a través de la puerta de enlace de entrada. Para ello, lee la documentación de las APIs de PeerAuthentication y AuthorizationPolicy de Istio.

Verifica la solución

En esta sección, verificarás que puedas enviar solicitudes HTTPS mediante mTLS a la aplicación de ejemplo desde fuera de la malla de servicios. Para verificar, creas una instancia de VM de Compute Engine, solicitas un certificado TLS de cliente desde el Servicio de CA y usas este certificado a fin de autenticar la solicitud en la aplicación de ejemplo.

Necesitas acceso SSH a la instancia de VM. La red predeterminada incluye una regla de firewall que permite el acceso SSH. Si no tienes acceso SSH, sigue la documentación de reglas de firewall para crear una regla de firewall que permita conexiones TCP entrantes en el puerto 22.

  1. En Cloud Shell, crea una cuenta de servicio de Google:

    gcloud iam service-accounts create CLIENT_VM_GSA \
        --display-name "CA Service tutorial VM instance service account"
    
    • CLIENT_VM_GSA es el nombre de la cuenta de servicio de Google. Por ejemplo, cas-tutorial-client

    Debes asignar esta cuenta de servicio de Google a la instancia de VM de Compute Engine.

  2. Otorga el rol Solicitante del certificado de servicio de CA en las puertas de enlace subordinadas del grupo de CA a la cuenta de servicio de Google:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    

    Este rol proporciona permisos para solicitar certificados del grupo de CA.

  3. Crea una instancia de VM de Compute Engine en la misma VPC que el clúster de GKE:

    gcloud compute instances create cas-tutorial-client \
        --scopes cloud-platform \
        --service-account CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --zone ZONE
    

    La instancia de VM requiere el permiso cloud-platform para acceder a la API del servicio de CA.

  4. Guarda la dirección IP del balanceador de cargas de red de transferencia interno de la puerta de enlace de entrada en un archivo:

    kubectl get services istio-ingressgateway \
       --namespace GATEWAY_NAMESPACE \
       --output jsonpath='{.status.loadBalancer.ingress[0].ip}' > ilb-ip.txt
    
  5. Guarda el certificado de clave pública de la CA raíz en un archivo:

    gcloud privateca roots describe ROOT_CA \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --format 'value(pemCaCertificates)' > root-ca-cert.pem
    
  6. Copia el certificado de AC raíz y el archivo que contiene la dirección IP del balanceador de cargas de red de transferencia interna de la puerta de enlace de entrada en la instancia de VM:

    gcloud compute scp root-ca-cert.pem ilb-ip.txt cas-tutorial-client:~ \
       --zone ZONE
    
  7. Conéctate a la instancia de VM mediante SSH:

    gcloud compute ssh cas-tutorial-client --zone ZONE
    

    Ejecuta el resto de los comandos en esta sección desde la sesión de SSH.

  8. Instala los paquetes ca-certificates y coreutils, y las herramientas de línea de comandos de curl, openssl y jq:

    sudo apt-get update --yes
    
    sudo apt-get install --yes ca-certificates coreutils curl jq openssl
    
  9. Crea un par de claves para el certificado TLS de cliente:

    openssl genrsa -out private-key.pem 2048
    
    openssl rsa -in private-key.pem -pubout -out public-key.pem
    
  10. Consulta el servidor de metadatos para obtener la dirección de correo electrónico de la identidad de la cuenta de servicio de Google conectada a la instancia de VM:

    GSA_EMAIL=$(curl --silent --header "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email)
    
  11. Crea un archivo JSON que uses como cuerpo de la solicitud cuando solicites un certificado TLS de cliente de la API de Certificate Authority Service:

    cat << EOF > request.json
    {
      "config": {
        "publicKey": {
          "format": "PEM",
          "key": "$(base64 --wrap 0 public-key.pem)"
        },
        "subjectConfig": {
          "subject": {
            "commonName": "$(hostname --short)",
            "organization": "Example Organization"
          },
          "subjectAltName": {
            "dnsNames": [
              "$(hostname --fqdn)"
            ],
            "emailAddresses": [
              "$GSA_EMAIL"
            ]
          }
        },
        "x509Config": {
          "caOptions": {
            "isCa": false
          },
          "keyUsage": {
            "baseKeyUsage": {
              "digitalSignature": true,
              "keyEncipherment": true
            },
            "extendedKeyUsage": {
              "clientAuth": true
            }
          }
        }
      },
      "lifetime": "86400s"
    }
    EOF
    

    Para obtener más información sobre los campos de la sección de configuración, consulta el tipo CertificateConfig en la documentación de la API del servicio de CA.

  12. Solicita un token de acceso de OAuth 2.0 al servidor de metadatos:

    TOKEN=$(curl --silent --header "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token | jq --raw-output ".access_token")
    

    Este token de acceso proporciona los permisos otorgados a la cuenta de servicio de Google adjunta a la instancia de VM.

  13. Solicita un certificado TLS de cliente a la API del servicio de CA y almacena el cuerpo de la respuesta en un archivo:

    curl --silent --request POST \
        --header "Authorization: Bearer $TOKEN" \
        --header "Content-Type: application/json" \
        --data @request.json \
        --output response.json \
        "https://privateca.googleapis.com/v1/projects/PROJECT_ID/locations/CA_LOCATION/caPools/SUBORDINATE_CA_POOL_GATEWAYS/certificates"
    

    El comando usa el token de acceso para autenticar la solicitud a la API.

  14. Guarda el certificado de cliente y la cadena de certificados en un archivo:

    jq --raw-output --join-output ".pemCertificate , .pemCertificateChain[]" response.json > client-cert-chain.pem
    
  15. Usa curl para enviar una solicitud HTTPS desde la instancia de VM a la aplicación de ejemplo:

    curl --cert client-cert-chain.pem --key private-key.pem \
        --cacert root-ca-cert.pem \
        --resolve hello.example.com:443:$(cat ilb-ip.txt) \
        --silent https://hello.example.com | head -n1
    

    El resultado se verá así:

    Hello, world!
    

    Esta respuesta muestra que curl envió correctamente la solicitud HTTPS mediante mTLS. La aplicación de muestra respondió con el mensaje que ves en el resultado de la terminal.

    El comando curl realiza lo siguiente:

    • Las marcas --cert y --key le indican a curl que use el certificado TLS del cliente y la clave privada para autenticar la solicitud. El archivo de certificado del cliente contiene la cadena completa de certificados, desde el certificado de cliente hasta la CA raíz.

    • La marca --cacert indica a curl que verifique que la CA raíz que creaste en este instructivo o una de sus CA subordinadas emitió el certificado de servidor.

      Si omites esta marca, curl intenta verificar el certificado del servidor con el paquete de AC predeterminado del sistema operativo, como el paquete ca-certificates en Debian. La verificación falla porque el paquete de CA predeterminado no incluye la CA raíz que creaste en este instructivo.

    • La marca --resolve indica a curl que use la dirección IP del balanceador de cargas de red de transferencia interno como el destino para las solicitudes de host hello.example.com en el puerto 443.

      Si omites esta marca, curl intenta usar DNS para resolver el nombre de host hello.example.com. La resolución de DNS falla porque no hay una entrada de DNS para este nombre de host.

      En tu propio entorno, te recomendamos que crees un registro A de DNS que apunte a la dirección IP del balanceador de cargas de red de transferencia interno ($LOAD_BALANCER_IP). Para crear este registro mediante Cloud DNS, sigue la documentación sobre administración de registros.

    • La marca --silent suprime los informes de progreso de descarga de respuesta en la salida de la terminal.

    • El comando canaliza el resultado de curl a head -n1. El resultado es que el resultado en la terminal solo incluye la primera línea del cuerpo de la respuesta.

  16. Sal de la sesión de SSH:

    exit
    

En esta sección, solicitaste un certificado TLS del cliente directamente desde la API del servicio de CA. En la situación en la que el cliente es la puerta de enlace de salida de otra malla de servicios en un clúster de Kubernetes separado, puedes usar la herramienta cert-manager y el emisor del servicio de autoridad certificada con la misma CA raíz para proporcionar certificados de cliente a la puerta de enlace de salida.

En otras situaciones, puedes usar herramientas como Hashicorp Vault, Terraform o gcloud a fin de solicitar certificados TLS de cliente para cargas de trabajo fuera de la malla de servicios. Para obtener más información, consulta la documentación del servicio de CA a fin de obtener soluciones de muestra y la documentación gcloud para el servicio de CA.

Agrega certificados de CA al almacén de confianza (opcional)

En esta sección opcional, se muestra cómo agregar certificados de CA al almacén de certificados de CA de confianza para la distribución de Linux en Debian. Estas instrucciones también se aplican a las distribuciones derivadas de Debian, como Ubuntu.

Agregar tus certificados de CA a este almacén significa que no necesitas especificar la ubicación de los certificados de CA de confianza cuando envías solicitudes HTTPS mediante curl, Python, Go y Ruby.

  1. Conéctate a la instancia de VM mediante SSH:

    gcloud compute ssh cas-tutorial-client --zone ZONE
    

    Ejecuta el resto de los comandos en esta sección desde la sesión de SSH.

  2. Copia el certificado de CA raíz en el directorio /usr/local/share/ca-certificates y asegúrate de que el archivo tenga la extensión .crt:

    sudo cp root-ca-cert.pem /usr/local/share/ca-certificates/cas-rootca.crt
    
  3. Configura los permisos del archivo para que todos los usuarios puedan leer el archivo del certificado de CA raíz:

    sudo chmod 644 /usr/local/share/ca-certificates/cas-rootca.crt
    
  4. Ejecuta la secuencia de comandos update-ca-certificates:

    sudo update-ca-certificates
    

    Esta secuencia de comandos agrega el certificado al conjunto de certificados de confianza en el directorio /etc/ssl/certs y en el archivo /etc/ssl/certs/ca-certificates.crt.

    Este es el resultado:

    Updating certificates in /etc/ssl/certs...
    1 added, 0 removed; done.
    Running hooks in /etc/ca-certificates/update.d...
    done.
    
  5. Usa curl para enviar una solicitud HTTPS desde la instancia de VM a la aplicación de ejemplo:

    curl --cert client-cert-chain.pem --key private-key.pem \
       --resolve hello.example.com:443:$(cat ilb-ip.txt) \
       --silent https://hello.example.com | head -n1
    

    El resultado se verá así:

    Hello, world!
    

    Esta respuesta muestra que curl envió correctamente la solicitud HTTPS con mTLS y validó el certificado TLS del servidor desde la puerta de enlace de entrada mediante el almacén de certificados de CA predeterminado.

  6. Sal de la sesión de SSH:

    exit
    

Solucionar problemas

Si el controlador de la entidad emisora del servicio de CA no crea el secreto de certificado TLS, consulta los registros del controlador de entidades emisora del servicio de CA:

kubectl logs deployment/google-cas-issuer --namespace cert-manager

Si tienes problemas para instalar Cloud Service Mesh, ejecuta la herramienta de asmcli para validar tu proyecto de Cloud y el clúster de GKE.

Si tienes otros problemas con este instructivo, te recomendamos que revises los siguientes documentos:

Limpia

Para evitar que se apliquen cargos continuos a tu cuenta de Google Cloud por los recursos que se usaron en este instructivo, puedes borrar el proyecto o borrar los recursos individuales.

Borra el proyecto

  1. En Cloud Shell, borra el proyecto:

    gcloud projects delete PROJECT_ID
    

Borra recursos

Si deseas conservar el proyecto de Google Cloud que usaste en este instructivo, borra los recursos individuales:

  1. En Cloud Shell, anula el registro del clúster de GKE desde GKE Hub:

    gcloud container hub memberships unregister CLUSTER_NAME \
        --gke-cluster ZONE/CLUSTER_NAME
    
  2. Borra el clúster de GKE:

    gcloud container clusters delete CLUSTER_NAME \
        --zone ZONE --async --quiet
    
  3. Borra las vinculaciones de políticas de IAM en el grupo de CA subordinado:

    gcloud privateca pools remove-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    
    gcloud privateca pools remove-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    
  4. Inhabilita y programa la eliminación de las CA subordinadas y la CA raíz:

    gcloud privateca subordinates disable SUBORDINATE_CA_GATEWAYS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_GATEWAYS \
        --quiet
    
    gcloud privateca subordinates delete SUBORDINATE_CA_GATEWAYS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_GATEWAYS \
        --ignore-active-certificates \
        --quiet
    
    gcloud privateca subordinates disable SUBORDINATE_CA_SIDECARS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_SIDECARS \
        --quiet
    
    gcloud privateca subordinates delete SUBORDINATE_CA_SIDECARS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_SIDECARS \
        --ignore-active-certificates \
        --quiet
    
    gcloud privateca roots disable ROOT_CA \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --quiet
    
    gcloud privateca roots delete ROOT_CA \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --ignore-active-certificates \
        --quiet
    
  5. Borra la vinculación de políticas de IAM para la cuenta de servicio de Google del controlador de la entidad emisora de servicios de CA:

    gcloud iam service-accounts remove-iam-policy-binding \
        CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[cert-manager/ksa-google-cas-issuer]" \
        --role roles/iam.workloadIdentityUser
    
  6. Borra las cuentas de servicio de Google:

    gcloud iam service-accounts delete --quiet \
        CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com
    
    gcloud iam service-accounts delete --quiet \
        CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com
    
  7. Borra la dirección IP del balanceador de cargas reservado:

    gcloud compute addresses delete asm-ingress-gateway-ilb \
        --region REGION --quiet
    
  8. Borra la instancia de VM de Compute Engine:

    gcloud compute instances delete cas-tutorial-client \
        --zone ZONE --quiet
    

¿Qué sigue?