Vista geral da política de autorização

Ao contrário de uma aplicação monolítica que pode estar a ser executada num único local, as apps de microserviços distribuídas globalmente fazem chamadas através de limites de rede. Isto significa mais pontos de entrada nas suas aplicações e mais oportunidades para ataques maliciosos. Além disso, como os pods do Kubernetes têm IPs transitórios, as regras de firewall tradicionais baseadas em IP não são adequadas para proteger o acesso entre cargas de trabalho. Numa arquitetura de microsserviços, é necessária uma nova abordagem à segurança. Com base em funcionalidades de segurança, como as contas de serviço do Kubernetes e as políticas de segurança do Istio, o Cloud Service Mesh oferece ainda mais capacidades para ajudar a proteger as suas aplicações.

Esta página oferece aos operadores de aplicações uma vista geral do AuthorizationPolicyrecurso personalizado (CR). As políticas de autorização permitem-lhe ativar o controlo de acesso em cargas de trabalho nas camadas de aplicação (L7) e de transporte (L3/4). Configura as políticas de autorização para especificar autorizações. O que é que este serviço ou utilizador tem autorização para fazer?

Políticas de autorização

Os pedidos entre serviços na sua malha (e entre utilizadores finais e serviços) são permitidos por predefinição. Usa o AuthorizationPolicy CR para definir políticas detalhadas para as suas cargas de trabalho. Depois de aplicar as políticas de autorização, o Cloud Service Mesh distribui-as pelos proxies sidecar. À medida que os pedidos chegam a uma carga de trabalho, o proxy sidecar verifica as políticas de autorização para determinar se o pedido deve ser permitido ou recusado.

Âmbito da política

Pode aplicar uma política a toda a malha de serviços, a um espaço de nomes ou a uma carga de trabalho individual.

  • Para aplicar uma política ao nível da malha, especifique o espaço de nomes raiz, istio-system, no campo metadata:namespace:

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "mesh-wide"
      namespace: istio-system
    spec:
    ...
    
  • Para aplicar uma política a um espaço de nomes, especifique o espaço de nomes no campo metadata:namespace:

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "currencyservice"
      namespace: currencyservice
    spec:
    ...
    
  • Para restringir uma política a uma carga de trabalho específica, inclua um campo selector.

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "frontend"
      namespace: demo
    spec:
      selector:
        matchLabels:
          app: frontend
       ...
    

Estrutura básica

Uma política de autorização inclui o âmbito da política, um action e uma lista de rules:

  • Conforme descrito na secção anterior, o âmbito da política pode ser toda a malha, um espaço de nomes ou uma carga de trabalho específica. Se o incluir, o campo selector especifica o destino da política.

  • O campo action especifica se deve ALLOW ou DENY o pedido. Se não especificar uma ação, por predefinição, a ação é definida como ALLOW. Para maior clareza, recomendamos que especifique sempre a ação. (As políticas de autorização também suportam as ações AUDIT e CUSTOM.)

  • O elemento rules especifica quando acionar a ação.

    • O campo from no rules especifica as origens do pedido.

    • O campo to no elemento rules especifica as operações do pedido.

    • O campo when especifica condições adicionais necessárias para aplicar a regra.

No exemplo seguinte:

  • A política é aplicada a pedidos ao serviço frontend no espaço de nomes demo.

  • Os pedidos são permitidos quando "hello:world" está no cabeçalho do pedido; caso contrário, os pedidos são recusados.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "hello-world"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: frontend
  action: ALLOW
  rules:
  - when:
    - key: request.headers[hello]
      values: ["world"]

Operação de controlo de acesso a pedido

Pode controlar o acesso a operações específicas, como métodos HTTP ou portas TCP, adicionando uma secção to em rules. No exemplo seguinte, apenas os métodos HTTP GET e POST são permitidos para o currencyservice no espaço de nomes demo.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: currencyservice
 namespace: demo
spec:
 selector:
   matchLabels:
     app: currencyservice
 action: ALLOW
 rules:
 - to:
   - operation:
       methods: ["GET", "POST"]

Controlo de acesso na identidade autenticada

Nos exemplos anteriores, as políticas permitem pedidos de cargas de trabalho não autenticadas. Se tiver o STRICTTLS mútuo (mTLS) ativado, pode restringir o acesso com base na identidade da carga de trabalho ou do espaço de nomes de onde o pedido é proveniente na secção source.

  • Use o campo principals ou notPrincipal para controlar o acesso ao nível da carga de trabalho.

  • Use o campo namespaces ou notNamespaces para controlar o acesso ao nível do espaço de nomes.

Todos os campos acima requerem que tenha o STRICT mTLS ativado. Se não conseguir definir o mTLS, consulte o artigo Rejeitar pedidos de texto simples para ver uma solução alternativa.STRICT

Carga de trabalho identificada

No exemplo seguinte, os pedidos ao currencyservice só são permitidos a partir do serviço frontend. As solicitações ao currencyservice de outras cargas de trabalho são recusadas.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "currencyservice"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: currencyservice
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["example-project-1234.svc.id.goog/ns/demo/sa/frontend-sa"]

Para especificar uma conta de serviço, o principals para autoridade de certificação do Cloud Service Mesh (CA da malha) e o serviço de autoridade de certificação (serviço de CA) têm de estar no seguinte formato:

principals: ["PROJECT_ID.svc.id.goog/ns/NAMESPACE/sa/SERVICE_ACCOUNT_NAME"]

PROJECT_ID.svc.id.googé o domínio de confiança para a CA de malha. Se estiver a usar a AC do Istio (anteriormente conhecida como Citadel), o domínio de confiança predefinido é cluster.local.

Espaço de nomes identificado

O exemplo seguinte mostra uma política que nega pedidos se a origem não for o espaço de nomes foo:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin-deny
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: DENY
 rules:
 - from:
   - source:
       notNamespaces: ["foo"]

Correspondência de valores

A maioria dos campos nas políticas de autorização suporta todos os seguintes esquemas de correspondência:

  • Correspondência exata: correspondência exata da string.
  • Correspondência de carateres universais com o caráter universal "*":
    • Correspondência de prefixos: uma string com um "*" no final. Por exemplo, "test.example.*" corresponde a "test.example.com" ou "test.example.com.cn".
    • Correspondência de sufixo: uma string com um "*" inicial. Por exemplo, "*.example.com" corresponde a "eng.example.com" ou "test.eng.example.com".
  • Correspondência de presença: para especificar que um campo tem de estar presente e não estar vazio, use o formato fieldname: ["*"]. Isto é diferente de deixar um campo não especificado, o que significa que corresponde a qualquer coisa, incluindo vazio.

Existem algumas exceções. Por exemplo, os seguintes campos só suportam a correspondência exata:

  • O campo key na secção when
  • O ipBlocks na secção source
  • O campo ports na secção to

A política de exemplo seguinte permite o acesso a caminhos com o prefixo /test/* ou o sufixo */info:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: tester
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/test/*", "*/info"]

Correspondência de exclusão

Para fazer corresponder condições negativas, como notValues no campo when, notIpBlocks no campo source e notPorts no campo to, o Cloud Service Mesh suporta a correspondência de exclusão. O exemplo seguinte requer um pedido válido principals, que é derivado da autenticação JWT, se o caminho do pedido não for /healthz. Assim, a política exclui os pedidos ao caminho /healthz da autenticação JWT:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: disable-jwt-for-healthz
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        notPaths: ["/healthz"]
    from:
    - source:
        requestPrincipals: ["*"]

Rejeite pedidos de texto simples

No Cloud Service Mesh 1.5 e posterior, o mTLS automático está ativado por predefinição. Com o mTLS automático, um proxy sidecar do lado do cliente deteta automaticamente se o servidor tem um sidecar. O sidecar do cliente envia mTLS para cargas de trabalho com sidecars e envia texto simples para cargas de trabalho sem sidecars. Para a melhor segurança, recomendamos que ative o mTLS ESTRICTO.

Se não conseguir ativar o mTLS com o modo STRICT para uma carga de trabalho ou um espaço de nomes, pode:

  • criar uma política de autorização para permitir explicitamente o tráfego com namespaces não vazio ou principals não vazio, ou
  • Rejeite tráfego com namespaces ou principals vazios.

Uma vez que o namespaces e o principals só podem ser extraídos com um pedido mTLS, estas políticas rejeitam efetivamente qualquer tráfego de texto simples.

A seguinte política nega o pedido se o principal no pedido estiver vazio (que é o caso dos pedidos de texto simples). A política permite pedidos se o principal não estiver vazio. O símbolo ["*"] significa uma correspondência não vazia e a utilização com notPrincipals significa uma correspondência no principal vazio.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-mtls
  namespace: NAMESPACE
spec:
  action: DENY
  rules:
  - from:
    - source:
        notPrincipals: ["*"]

Precedência da política de autorização

Pode configurar políticas de autorização ALLOW e DENY separadas, mas tem de compreender a precedência das políticas e o comportamento predefinido para se certificar de que as políticas fazem o que pretende. O diagrama seguinte descreve a precedência das políticas.

precedência da política de autorização

As políticas de exemplo nas secções seguintes ilustram alguns dos comportamentos predefinidos e as situações em que podem ser úteis.

Não permitir nada

O exemplo seguinte mostra uma política ALLOW que não corresponde a nada. Por predefinição, se não existirem outras políticas ALLOW, os pedidos são sempre recusados.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-nothing
spec:
  action: ALLOW

É uma boa prática de segurança começar com a política de não permitir nada e adicionar gradualmente mais políticas ALLOW para abrir mais acesso a uma carga de trabalho.

Negar todo o acesso

O exemplo seguinte mostra uma política DENY que corresponde a tudo. Uma vez que as políticas de DENY são avaliadas antes das políticas de ALLOW, todos os pedidos são recusados, mesmo que exista uma política de ALLOW que corresponda ao pedido.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
spec:
  action: DENY
  rules:
  - {}

Uma política de negação total é útil se quiser desativar temporariamente todo o acesso a uma carga de trabalho.

Permitir todo o acesso

O exemplo seguinte mostra uma política ALLOW que corresponde a tudo e permite o acesso total a uma carga de trabalho. A política de permissão total torna outras políticas inúteis porque permite sempre o pedido.ALLOW

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-all
spec:
  action: ALLOW
  rules:
  - {}

Uma política de autorização total é útil se quiser expor temporariamente o acesso total a uma carga de trabalho. Se existirem políticas DENY, os pedidos podem continuar a ser recusados, uma vez que as políticas DENY são avaliadas antes das políticas ALLOW.

Práticas recomendadas

  1. Crie uma conta de serviço do Kubernetes para cada serviço e especifique a conta de serviço na implementação. Por exemplo:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: frontend-sa
      namespace: demo
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
      namespace:demo
    spec:
      selector:
        matchLabels:
          app: frontend
      template:
        metadata:
          labels:
            app: frontend
        spec:
          serviceAccountName: frontend-sa
        ...
    
  2. Comece com uma política de não permitir nada e adicione progressivamente mais políticas ALLOW para abrir mais acesso a cargas de trabalho.

  3. Se estiver a usar JWTs para o seu serviço:

    1. Crie uma política DENY para bloquear pedidos não autenticados, por exemplo:

      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: requireJWT
        namespace: admin
      spec:
        action: DENY
        rules:
        -  from:
          - source:
              notRequestPrincipals: ["*"]
      
    2. Aplicar uma política de não autorização.

    3. Defina políticas ALLOW para cada carga de trabalho. Para ver exemplos, consulte Token JWT.

O que se segue?

Saiba mais sobre as funcionalidades de segurança da Cloud Service Mesh:

Saiba mais sobre as políticas de autorização na documentação do Istio: