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

  • Identity-Aware Proxy (IAP) para fornecer uma camada de autenticação e autorização antes de permitir o acesso a um serviço

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 Standard, o GKE versão 1.24 ou posterior.
  • 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:

  • 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.
  • O Gerenciador de certificados é compatível com certificados autogerenciados e gerenciados pelo Google, mas não é compatível com gateways regionais.
  • Ao usar certificados SSL gerenciados pelo Google, é necessário criar os certificados SSL fora do GKE antes de anexá-los ao gateway.

  • Os certificados SSL gerenciados pelo Google não são compatíveis com gateways regionais. Para mais informações sobre os métodos de encerramento de TLS para cada GatewayClass, consulte Suporte a GatewayClass TLS para.

  • 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.

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 é obrigató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 um gateway usando um certificado SSL

Neste exemplo, você configura um gateway com um certificado SSL gerenciado pelo Google.

Criar um certificado SSL

  1. Crie um recurso SslCertificate global gerenciado pelo Google:

    gcloud compute ssl-certificates create store-example-com \
        --domains=store.example.com \
        --global
    

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
          options:
            networking.gke.io/pre-shared-certs: 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.mode:Terminate: encerra o TLS usando seu certificado SSL.
  2. Aplique o manifesto ao cluster:

    kubectl apply -f external-gateway.yaml
    
  3. Salve o seguinte manifesto HTTPRoute 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
    
  4. Implantar o HTTPRoute no cluster:

    kubectl apply -f store-external-route.yaml
    

    A implantação do gateway pode levar vários minutos.

Verifique o gateway

  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. Atualize um registro A ou AAAA para direcionar seu domínio ao endereço IP do gateway.

    Essa etapa é necessária apenas se você estiver configurando um certificado SSL gerenciado pelo Google. Se você estiver configurando um certificado autogerenciado, pule esta etapa.

    Depois que os registros DNS forem atualizados, pode levar até 10 minutos para o balanceador de carga começar a usar o certificado gerenciado pelo Google.

  3. Verifique se o gateway está funcionando enviando uma solicitação pela Internet usando curl:

    curl https://store.example.com -v
    

    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",
      "zone": "us-west1-a"
    }
    

    Essa saída inclui um handshake de TLS bem-sucedido e uma resposta do aplicativo. O TLS é encerrado no gateway corretamente, e o aplicativo responde ao cliente de forma segura.

Proteger um gateway usando o Gerenciador de certificados

Neste exemplo, você configura um gateway usando o Gerenciador de certificados.

Criar um CertificateMap

  1. Crie um CertificateMap:

    gcloud certificate-manager maps create store-example-com-map
    
  2. Carregue o certificado e a chave autogerenciados em um Certificate:

    gcloud certificate-manager certificates create store-example-com-cert \
        --certificate-file="cert.pem" \
        --private-key-file="PRIVATE_KEY_FILE"
    
  3. Crie um CertificateMapEntry que atribua o certificado a CertificateMap:

    gcloud certificate-manager maps entries create store-example-com-map-entry \
        --map=store-example-com-map \
        --hostname=store.example.com \
        --certificates=store-example-com-cert
    

Crie um gateway e um HTTPRoute

  1. Salve o seguinte manifesto como cert-map-gateway.yaml:

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

    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.

    Não há uma seção TLS porque o TLS está configurado com o Gerenciador de certificados usando a anotação networking.gke.io/certmap.

  2. Aplique o manifesto ao cluster:

    kubectl apply -f cert-map-gateway.yaml
    

    A implantação do gateway pode levar vários minutos.

  3. Salve o seguinte manifesto como cert-map-http-route.yaml:

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: HTTPRoute
    metadata:
      name: foo
      namespace: default
    spec:
      parentRefs:
      - name: external-http
      hostnames:
      - foo.example.com
      rules:
      - matches:
        - path:
            value: /
        backendRefs:
        - name: foo-v1
          port: 8080
    
  4. Aplique o manifesto ao cluster:

    kubectl apply -f cert-map-http-route.yaml
    

Verifique o gateway

  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. Atualize um registro A ou AAAA para direcionar seu domínio ao endereço IP do gateway.

    Essa etapa é necessária apenas se você estiver configurando um certificado SSL gerenciado pelo Google. Se você estiver configurando um certificado autogerenciado, pule esta etapa.

    Depois que os registros DNS forem atualizados, pode levar até 10 minutos para o balanceador de carga começar a usar o certificado gerenciado pelo Google.

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

    curl https://store.example.com -v
    

    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",
      "zone": "us-west1-a"
    }
    

    Essa saída inclui um handshake de TLS bem-sucedido e uma resposta do aplicativo. O TLS é encerrado no gateway corretamente, 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.

Autenticar solicitações para seus back-ends usando o Identity-Aware Proxy

O Identity-Aware Proxy ajuda a proteger seus back-ends contra tráfego indesejado autenticando clientes que enviam solicitações aos seus aplicativos e aplicando a autorização de tráfego com base em papéis. Depois de ativar o Identity-Aware Proxy para GKE, é possível referenciar suas credenciais do OAuth em um GCPBackendPolicy aplicado aos serviços do Kubernetes.

Para configurar o Identity-Aware Proxy com o gateway, consulte Configurar o Identity-Aware Proxy.

A seguir