Configura la finalización de TLS en la puerta de enlace de entrada

Descripción general

En esta página, se muestra cómo configurar una terminación de TLS en la puerta de enlace de entrada en Cloud Service Mesh para administrar el tráfico HTTPS externo a tus servicios. Para obtener una introducción más básica sobre cómo configurar puertas de enlace, consulta la guía de puertas de enlace. Aprenderás a configurar la puerta de enlace para que realice comunicaciones seguras con TLS, lo que habilitará el acceso encriptado a tus aplicaciones. Este proceso aprovecha las capacidades de Cloud Service Mesh para exponer servicios de forma segura.

Antes de comenzar

Para completar los pasos de este documento, necesitas los siguientes recursos:

  • Un clúster de Kubernetes con Cloud Service Mesh instalado. Consulta la guía de instalación para obtener detalles sobre cómo instalar Cloud Service Mesh.

Configura tu entorno

Ejecuta los siguientes comandos desde una estación de trabajo que pueda acceder al clúster que deseas usar. Asegúrate de que la herramienta de kubectl esté configurada para usar el contexto de clúster específico del clúster.

  1. Configure las variables de entorno.

    export CSM_INGRESSGATEWAY_NAMESPACE=CSM_INGRESSGATEWAY_NAMESPACE
    export CSM_INGRESSGATEWAY_DEPLOYMENT_NAME=CSM_INGRESSGATEWAY_DEPLOYMENT_NAME
    export CSM_INGRESSGATEWAY_SERVICE_NAME=CSM_INGRESSGATEWAY_SERVICE_NAME
    
  2. Implementa la aplicación foo en tu clúster. Instala el siguiente archivo yaml:

    apiVersion: v1
    kind: Service
    metadata:
      name: foo
      namespace: foo
    spec:
      selector:
        app: test-backend
      ports:
      - port: 8080
        targetPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: foo
      namespace: foo
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: test-backend
      template:
        metadata:
          labels:
            app: test-backend
        spec:
          containers:
          - name: whereami
            image: gcr.io/google-samples/whereami:v1.2.23
            ports:
            - containerPort: 8080
    EOF
    
  3. Genera certificados y claves.

    Para proteger tu puerta de enlace de entrada, necesitarás certificados y claves TLS. Puedes usar cualquier herramienta de generación de certificados o seguir estos pasos con openssl para crear las credenciales necesarias.

    • Crea un certificado y una clave de AC raíz
    mkdir example_certs
    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=Example Corp/CN=example.com' \
      -keyout example.com.key -out example.com.crt
    
    • Genera un certificado y una clave para la entrada
    openssl req -out foo.example.com.csr -newkey rsa:2048 -nodes \
      -keyout foo.example.com.key -subj "/CN=foo.example.com/O=Foo Org"
    
    openssl x509 -req -sha256 -days 365 -CA example.com.crt \
      -CAkey example.com.key -set_serial 0 \
      -in foo.example.com.csr -out foo.example.com.crt
    

Configura una puerta de enlace de entrada de TLS

En los siguientes pasos, se describe cómo configurar una puerta de enlace de entrada de TLS.

Almacena el certificado TLS

  1. Crea el espacio de nombres. Este espacio de nombres se usa para implementar la puerta de enlace de entrada.

    kubectl create namespace ${CSM_INGRESSGATEWAY_NAMESPACE}
    
  2. Aplica la etiqueta de inserción predeterminada al espacio de nombres:

    kubectl label namespace ${CSM_INGRESSGATEWAY_NAMESPACE} \
        istio.io/rev- istio-injection=enabled --overwrite
    
  3. Almacena las credenciales de TLS en un secreto de Kubernetes:

    kubectl create -n ${CSM_INGRESSGATEWAY_NAMESPACE} secret tls foo-credential \
      --key=example_certs/foo.example.com.key \
      --cert=example_certs/foo.example.com.crt
    

Aplica el certificado TLS a la puerta de enlace

Existen dos maneras de hacer que la puerta de enlace use el certificado TLS recién creado.

Implementación con credenciales montadas (preferida)

  1. Copia el manifiesto de la puerta de enlace de entrada predeterminada en un archivo local.

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/ingress-gateway-external-lb/ingress-gateway.yaml > ingress-gateway.yaml
    
  2. Modifica la especificación de implementación en ingress-gateway.yaml para activar la credencial secreta de TLS.

    apiVersion: apps/v1
    kind: Deployment
    ...
    spec:
      ...
        spec:
            ...
            volumeMounts:
            - name: foo-credential # Add new volume mount specifying mount path.
              mountPath: /etc/secrets/foo-credential 
              readOnly: true
          volumes:
          - name: foo-credential # Point volume mount to the Kubernetes secret holding the TLS certificate and keys.
            secret:
              secretName: foo-credential
    

    Luego, crea los recursos relacionados con la puerta de enlace de entrada.

    kubectl --namespace ${CSM_INGRESSGATEWAY_NAMESPACE} apply --filename ingress-gateway.yaml 
    
  3. Define la puerta de enlace de entrada.

    Crea un recurso de puerta de enlace para controlar el tráfico HTTPS en el puerto 443 que haga referencia a los secretos activados:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: secure-gateway
      namespace: ${CSM_INGRESSGATEWAY_NAMESPACE}
    spec:
      selector:
        app: asm-ingressgateway
        istio: ingressgateway
      servers:
      - port:
          number: 443
          name: https
          protocol: HTTPS
        tls:
          mode: SIMPLE
          serverCertificate: /etc/secrets/foo-credential/foo.example.com.crt
          privateKey: /etc/secrets/foo-credential/foo.example.com.key
        hosts:
        - "foo.example.com"
    EOF
    

Implementación sin credenciales montadas

  1. Aplica el archivo de manifiesto de la puerta de enlace de entrada.

    kubectl --namespace ${CSM_INGRESSGATEWAY_NAMESPACE} apply --filename https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/ingress-gateway-external-lb/ingress-gateway.yaml
    

    Resultado esperado:

    serviceaccount/asm-ingressgateway created
    role.rbac.authorization.k8s.io/asm-ingressgateway created
    rolebinding.rbac.authorization.k8s.io/asm-ingressgateway created
    deployment.apps/asm-ingressgateway created
    service/asm-ingressgateway created
    poddisruptionbudget.policy/asm-ingressgateway created
    horizontalpodautoscaler.autoscaling/asm-ingressgateway created
    
  2. Define la puerta de enlace de entrada.

    Crea un recurso de puerta de enlace para controlar el tráfico HTTPS en el puerto 443:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: secure-gateway
      namespace: ${CSM_INGRESSGATEWAY_NAMESPACE}
    spec:
      selector:
        app: asm-ingressgateway
        istio: ingressgateway
      servers:
      - port:
          number: 443
          name: https
          protocol: HTTPS
        tls:
          mode: SIMPLE
          credentialName: foo-credential
        hosts:
        - "foo.example.com"
    EOF
    

Prueba de tráfico

  1. Enruta el tráfico al servicio foo.

    Define un VirtualService para dirigir el tráfico a la implementación de foo:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: foo-routing
      namespace: ${CSM_INGRESSGATEWAY_NAMESPACE}
    spec:
      hosts:
      - "foo.example.com"
      gateways:
      - secure-gateway
      http:
      - match:
        - uri:
            prefix: /status
        - uri:
            prefix: /delay
        route:
        - destination:
            host: foo
            port:
              number: 8080
    EOF
    
  2. Configura el balanceador de cargas externo para que se conecte con la puerta de enlace de entrada del clúster.

  3. Prueba la conexión segura.

    Usa el siguiente comando curl para verificar la configuración:

    export EXTERNAL_LB_IP_ADDRESS=EXTERNAL_LB_IP_ADDRESS
    curl -v -H "Host: foo.example.com" --resolve "foo.example.com:443:$EXTERNAL_LB_IP_ADDRESS" \
      --cacert example_certs/example.com.crt "https://foo.example.com:443/ping"
    

    Reemplaza EXTERNAL_LB_IP_ADDRESS por la IP del balanceador de cargas externo.

    El resultado es similar a este:

      {
        "cluster_name": "gke-us",
        "host_header": "34.120.175.141",
        "pod_name": "whereami-deployment-954cbf78-mtlpf",
        "pod_name_emoji": "😎",
        "project_id": "my-project",
        "timestamp": "2021-11-29T17:01:59",
        "zone": "us-central1-b"
      }
    

¿Qué sigue?