Proteger um gateway

Esta página explica como proteger um gateway usando vários recursos de segurança:

  • Políticas de SSL para garantir que o gateway use os protocolos e algoritmos seguros necessários

  • Certificados para proteger o tráfego de cliente para gateway e de gateway para back-ends com TLS

  • Política de segurança do Google Cloud Armor para proteger os Serviços contra ataques DDoS

Para saber mais sobre segurança de gateway, consulte Segurança de gateway.

Antes de começar

Antes de começar, verifique se você realizou as tarefas a seguir:

  • Ativar a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a Google Cloud CLI para essa tarefa, instale e, em seguida, inicialize a CLI gcloud. Se você instalou a CLI gcloud anteriormente, instale a versão mais recente executando gcloud components update.

Requisitos do GKE Gateway Controller

  • Para o Autopilot, o GKE versão 1.26 ou posterior.
  • Google Cloud CLI versão 407.0.0 ou mais recente.
  • A API Gateway é compatível apenas com clusters nativos da VPC.
  • Se você estiver usando o GatewayClasses interno, ative uma sub-rede somente proxy.
  • O cluster precisa ter o complemento HttpLoadBalancing ativado.
  • Se você estiver usando o Istio, será necessário fazer upgrade do Istio para uma das seguintes versões:
    • 1.15.2 ou mais recente
    • 1.14.5 ou mais recente
    • 1.13.9 ou mais recente
  • Se você estiver usando a VPC compartilhada, será necessário atribuir o papel Compute Network User à conta de serviço do GKE referente ao projeto de serviço no projeto host.

Restrições e limitações

Além das restrições e limitações do controlador de gateway do GKE, as seguintes limitações se aplicam especificamente à segurança do gateway:

  • As configurações de TLS que usam um certificado SSL em gateways não são compatíveis com a versão 1.28.4-gke.1083000 do GKE. Use um secret do Kubernetes como solução alternativa para essa versão do GKE.
  • Não é possível usar a anotação networking.gke.io/certmap com um tls.certificateRefs no mesmo recurso de gateway. Se você referenciar um CertificateMap em um gateway, o GKE o tratará como um erro.
  • Não é possível usar o mesmo serviço de back-end para um gateway regional e global se você estiver fazendo referência a uma política de segurança de back-end do Google Cloud Armor na GCPBackendPolicy. É preciso criar dois serviços e políticas separados para esse caso de uso.

  • O controlador de gateway não é compatível com o recurso ManagedCertificate.

  • O controlador Gateway não é compatível com a anotação networking.gke.io/managed-certificates.

  • O campo appProtocol na configuração do serviço aceita apenas letras maiúsculas para o valor do protocolo (HTTP, HTTPS ou HTTP2). O uso de letras minúsculas resulta no uso de HTTP como protocolo com os back-ends.

Para uma lista de campos compatíveis com a API Gateway e recursos do GatewayClass disponíveis no GKE, consulte Recursos adicionais do GatewayClass.

Proteger um gateway usando um secret do Kubernetes

Neste exemplo, você configura um gateway usando um secret do Kubernetes.

Armazenar um certificado em um secret do Kubernetes

É possível usar um certificado emitido e validado pela autoridade de certificação (CA, na sigla em inglês) ou criar um certificado autoassinado. As etapas a seguir usam um certificado autoassinado.

  1. Criar uma chave privada

    openssl genrsa -out PRIVATE_KEY_FILE 2048
    

    Substitua PRIVATE_KEY_FILE pelo nome do arquivo de chave privada, como private-key.pem. Para mais informações, consulte Selecionar ou criar uma chave privada.

  2. Crie um arquivo de configuração OpenSSL.

    cat <<EOF >CONFIG_FILE
    [req]
    default_bits              = 2048
    req_extensions            = extension_requirements
    distinguished_name        = dn_requirements
    prompt                    = no
    
    [extension_requirements]
    basicConstraints          = CA:FALSE
    keyUsage                  = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName            = @sans_list
    
    [dn_requirements]
    0.organizationName        = example
    commonName                = store.example.com
    
    [sans_list]
    DNS.1                     = store.example.com
    EOF
    

    Substitua CONFIG_FILE pelo nome do novo arquivo de configuração, como config-file.cnf.

  3. Crie um arquivo de solicitação de assinatura de certificado (CSR):

    openssl req -new -key PRIVATE_KEY_FILE \
        -out CSR_FILE \
        -config CONFIG_FILE
    

    Substitua CSR_FILE pelo nome do novo arquivo CSR, como cert.pem. Para saber mais, consulte Criar uma CSR.

  4. Assinar a CSR:

    openssl x509 -req \
        -signkey PRIVATE_KEY_FILE \
        -in CSR_FILE \
        -out CERTIFICATE_FILE \
        -extfile CONFIG_FILE \
        -extensions extension_requirements \
        -days 30
    

    Substitua CERTIFICATE_FILE pelo caminho e nome do arquivo gerado pelo comando, como cert-file.pem. Para mais informações, consulte Assinar o CSR.

  5. Crie um secret TLS do Kubernetes usando a chave e o arquivo de certificado que você criou:

    kubectl create secret tls store-example-com \
        --cert=CERTIFICATE_FILE \
        --key=PRIVATE_KEY_FILE
    

    O GKE salva o certificado e a chave como um recurso do Kubernetes que pode ser anexado ao gateway.

Crie um gateway e um HTTPRoute

  1. Salve o seguinte manifesto como external-gateway.yaml:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: external-http
    spec:
      gatewayClassName: gke-l7-global-external-managed
      listeners:
      - name: https
        protocol: HTTPS
        port: 443
        tls:
          mode: Terminate
          certificateRefs:
          - name: store-example-com
    

    Este manifesto descreve um Gateway com as seguintes propriedades:

    • gatewayClassName: gke-l7-global-external-managed: implanta um balanceador de carga de aplicativo externo global.
    • protocol: HTTPS e port: 443: necessários para ativar o TLS.
    • tls: faz referência ao secret do Kubernetes criado na etapa anterior.
  2. Aplique o manifesto ao cluster:

    kubectl apply -f external-gateway.yaml
    
  3. Salve o seguinte manifesto como store-external-route.yaml:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-external
      labels:
        gateway: external-http
    spec:
      parentRefs:
      - name: external-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-v1
          port: 8080
    

    Esse manifesto descreve um HTTPRoute que corresponde ao tráfego para store.example.com e o envia ao serviço store-v1.

  4. Aplique o manifesto ao cluster:

    kubectl apply -f store-external-route.yaml
    

Verifique o gateway

Verifique se o gateway funciona enviando uma solicitação pela Internet.

  1. Consiga o endereço IP do gateway:

    kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"
    

    O resultado será assim:

    203.0.113.12
    

    Essa saída é um endereço IP público, o que significa que qualquer cliente com acesso à Internet pode se conectar a ela.

  2. Acesse o domínio do gateway usando curl:

    curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert CERTIFICATE_FILE -v
    

    Substitua:

    • GATEWAY_IP_ADDRESS: o endereço IP do balanceador de carga do gateway.
    • CERTIFICATE_FILE: o arquivo de certificado que você gerou. Salve esse arquivo na máquina que está usando para se conectar ao gateway. O certificado é necessário para autenticar o gateway porque ele usa um certificado autoassinado.

    A opção --resolve resolve o nome de domínio para o endereço IP do gateway, que é necessário porque o DNS não está configurado para este domínio.

    O resultado será assim:

    ...
    * TLSv1.2 (OUT), TLS handshake, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=example; CN=store.example.com
    *  start date: Apr 19 15:54:50 2021 GMT
    *  expire date: Apr 19 15:54:50 2022 GMT
    *  common name: store.example.com (matched)
    *  issuer: O=example; CN=store.example.com
    *  SSL certificate verify ok.
    ...
    {
      "cluster_name": "gw",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal",
      "pod_name": "store-v1-84b47c7f58-tj5mn",
      "pod_name_emoji": "😍",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-04-19T16:30:08"
      # Several lines of output omitted here.
    }
    

    Essa saída inclui um handshake de TLS bem-sucedido seguido por uma resposta do aplicativo. A conexão TLS é encerrada no gateway e o aplicativo responde ao cliente de forma segura.

Proteger o balanceador de carga para o tráfego de aplicativos usando TLS

É possível criptografar o tráfego do balanceador de carga para pods de back-end usando o campo ports[].appProtocol. Os campos aceitos para appProtocol são: HTTP, HTTPS e HTTP2.

O manifesto a seguir descreve um serviço que especifica que o balanceador de carga precisa usar o tráfego HTTPS para se comunicar com os pods de back-end:

apiVersion: v1
kind: Service
metadata:
  name: store-v2
spec:
  selector:
    app: store
    version: v2
  ports:
  - port: 8080
    targetPort: 8080
    appProtocol: HTTPS

O balanceador de carga não verifica o certificado usado pelos pods de back-end. É sua responsabilidade garantir que o certificado usado nos pods de back-end seja válido.

Proteger o cliente para o tráfego do balanceador de carga usando políticas de SSL

Quando os aplicativos são expostos por meio de um gateway externo que usa HTTPS, é importante usar os protocolos mais recentes ou especificar a versão mínima de SSL ou TLS. É possível proteger o cliente para o tráfego do balanceador de carga usando políticas de SSL.

Para saber mais sobre as políticas de SSL que podem ser anexadas ao gateway e como criá-las, consulte Configurar políticas de SSL para proteger o cliente para o tráfego do balanceador de carga.

Proteja seus back-ends usando o Google Cloud Armor

As políticas de segurança do Google Cloud Armor ajudam a proteger seus aplicativos com balanceamento de carga contra ataques baseados na Web. Depois de configurar uma política de segurança do Google Cloud Armor, você pode referenciá-la em um GCPBackendPolicy aplicado aos serviços do Kubernetes.

Para configurar as políticas do Google Cloud Armor com gateway, consulte Configurar a política de segurança do Google Cloud Armor para proteger seus serviços de back-end.

A seguir