Configurar o encerramento de TLS no gateway de entrada

Visão geral

Esta página demonstra como configurar uma terminação TLS no gateway de entrada no Cloud Service Mesh para gerenciar o tráfego HTTPS externo para seus serviços. Para uma introdução mais básica sobre como configurar gateways, consulte o guia de gateways. Você vai aprender a configurar o gateway para comunicação segura usando TLS, ativando o acesso criptografado aos seus aplicativos. Esse processo aproveita os recursos do Cloud Service Mesh para expor serviços com segurança.

Antes de começar

Você precisa dos seguintes recursos para concluir as etapas deste documento:

  • Um cluster do Kubernetes com o Cloud Service Mesh instalado. Consulte o guia de instalação para saber como instalar o Cloud Service Mesh.

Configurar o ambiente

Execute os comandos a seguir em uma estação de trabalho que possa acessar o cluster que você pretende usar. Verifique se a ferramenta kubectl está configurada para usar o contexto do cluster específico.

  1. Defina as variáveis de ambiente.

    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. Implante o aplicativo foo no cluster. Instale com o seguinte 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. Gere certificados e chaves.

    Para proteger seu gateway de entrada, você vai precisar de certificados e chaves TLS. Você pode usar qualquer ferramenta de geração de certificados ou seguir estas etapas usando o openssl para criar as credenciais necessárias.

    • Criar um certificado e uma chave de CA raiz
    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
    
    • Gerar um certificado e uma chave para a 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
    

Configurar um gateway de entrada TLS

As etapas a seguir descrevem como configurar um gateway de entrada TLS.

Armazenar o certificado TLS

  1. Crie o namespace. Esse namespace é usado para implantar o gateway de entrada.

    kubectl create namespace ${CSM_INGRESSGATEWAY_NAMESPACE}
    
  2. Aplique o rótulo de injeção padrão ao namespace:

    kubectl label namespace ${CSM_INGRESSGATEWAY_NAMESPACE} \
        istio.io/rev- istio-injection=enabled --overwrite
    
  3. Armazene as credenciais TLS em um secret do 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
    

Aplicar o certificado TLS ao gateway

Há duas maneiras de fazer com que o gateway use o certificado TLS recém-criado.

Implantação com credenciais montadas (preferencial)

  1. Copie o manifesto de gateway de entrada padrão para um arquivo local.

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/ingress-gateway-external-lb/ingress-gateway.yaml > ingress-gateway.yaml
    
  2. Modifique a especificação de implantação em ingress-gateway.yaml para montar a credencial secreta 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
    

    Em seguida, crie os recursos relacionados ao gateway de entrada.

    kubectl --namespace ${CSM_INGRESSGATEWAY_NAMESPACE} apply --filename ingress-gateway.yaml 
    
  3. Defina o gateway de entrada.

    Crie um recurso de gateway para processar o tráfego HTTPS na porta 443 que referencia os segredos montados:

    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
    

Implantação sem credenciais montadas

  1. Aplique o arquivo de manifesto do gateway 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
    

    Saída esperada:

    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. Defina o gateway de entrada.

    Crie um recurso de gateway para processar o tráfego HTTPS na porta 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
    

Testar o tráfego

  1. Encaminhar o tráfego para o serviço foo.

    Defina um VirtualService para direcionar o tráfego à implantação 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. Configure o balanceador de carga externo para se conectar ao gateway de entrada do cluster.

  3. Teste a conexão segura.

    Use o seguinte comando curl para verificar a configuração:

    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"
    

    Substitua EXTERNAL_LB_IP_ADDRESS pelo IP do balanceador de carga externo.

    O resultado será assim:

      {
        "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"
      }
    

A seguir