Todos os produtos
Search
Central de documentação

Alibaba Cloud Service Mesh:Implementar controle de acesso refinado com políticas OPA

Última atualização: Jun 28, 2026

O Service Mesh (ASM) integra o Open Policy Agent (OPA), um projeto graduado da CNCF, como sidecar junto aos pods da sua aplicação. Com o OPA, você define políticas de autorização em Rego para controlar o acesso no nível da requisição, permitindo ou bloqueando solicitações com base em caminhos de URL, métodos HTTP, claims JWT ou conteúdo do corpo da requisição.

O OPA é implantado como sidecar no mesmo pod dos containers da sua aplicação. Para proteger uma aplicação, o OPA verifica a autorização de cada requisição destinada a um microsserviço antes do processamento.

OPA architecture

Pré-requisitos

Ative o plug-in OPA e o controle de escopo de injeção

  1. Faça login no console do ASM. No painel de navegação à esquerda, escolha Service Mesh > Mesh Management.

  2. Na página Mesh Management, clique em nome da instância do ASM. No painel de navegação à esquerda, escolha Mesh Security Center > OPA Policy.

  3. Na página OPA Policy, selecione Enable Open Policy Agent (OPA) Plug-in e Enable OPA Injection Range Control e clique em Enable OPA. Na mensagem de Note, clique em OK.

Crie uma política OPA

As políticas OPA são definidas no plano de controle do ASM e enviadas automaticamente para os clusters do plano de dados. Os sidecars OPA nos pods correspondentes aplicam cada política a todas as requisições recebidas.

A política de exemplo a seguir define duas funções com permissões diferentes:

  • guest: pode apenas executar GET /productpage

  • admin: pode executar GET /productpage e GET /api/v1/products

Os usuários se autenticam via HTTP Basic Auth. O OPA extrai o nome de usuário do cabeçalho Authorization, consulta a função atribuída e verifique se essa função tem permissão para o método e o caminho solicitados.

Opção A: Usar o console do ASM

  1. Faça login no console do ASM. No painel de navegação à esquerda, escolha Service Mesh > Mesh Management.

  2. Na página Mesh Management, clique em nome da instância do ASM. No painel de navegação à esquerda, escolha Mesh Security Center > OPA Policy.

  3. Na página OPA Policy, clique em Create, selecione default na lista suspensa Namespace, defina Name como bookinfo-opa e clique em Add Matching Label. Na seção Matching Label, defina Name como version e Value como v1. Copie as regras Rego a seguir para o editor de código e clique em Create.

    Show the Rego rules

       package istio.authz
       import input.attributes.request.http as http_request
       allow {
           roles_for_user[r]
           required_roles[r]
       }
       roles_for_user[r] {
           r := user_roles[user_name][_]
       }
       required_roles[r] {
           perm := role_perms[r][_]
           perm.method = http_request.method
           perm.path = http_request.path
       }
       user_name = parsed {
           [_, encoded] := split(http_request.headers.authorization, " ")
           [parsed, _] := split(base64url.decode(encoded), ":")
       }
       user_roles = {
           "guest1": ["guest"],
           "admin1": ["admin"]
       }
       role_perms = {
           "guest": [
               {"method": "GET",  "path": "/productpage"},
           ],
           "admin": [
               {"method": "GET",  "path": "/productpage"},
               {"method": "GET",  "path": "/api/v1/products"},
           ],
       }

Opção B: Usar kubectl

  1. Crie um arquivo chamado opa.yaml com o seguinte conteúdo:

    Show the opa.yaml file

       apiVersion: istio.alibabacloud.com/v1beta1
       kind: ASMOPAPolicy
       metadata:
         name: bookinfo-opa
         namespace: default
       spec:
         workloadSelector:
            labels:
              version: v1
         policy: |
           package istio.authz
           import input.attributes.request.http as http_request
           allow {
               roles_for_user[r]
               required_roles[r]
           }
           roles_for_user[r] {
               r := user_roles[user_name][_]
           }
           required_roles[r] {
               perm := role_perms[r][_]
               perm.method = http_request.method
               perm.path = http_request.path
           }
           user_name = parsed {
               [_, encoded] := split(http_request.headers.authorization, " ")
               [parsed, _] := split(base64url.decode(encoded), ":")
           }
           user_roles = {
               "guest1": ["guest"],
               "admin1": ["admin"]
           }
           role_perms = {
               "guest": [
                   {"method": "GET",  "path": "/productpage"},
               ],
               "admin": [
                   {"method": "GET",  "path": "/productpage"},
                   {"method": "GET",  "path": "/api/v1/products"},
               ],
           }
  2. Conecte-se à instância do ASM com kubectl. Para mais informações, consulte Usar kubectl no plano de controle para acessar recursos do Istio. Em seguida, aplique a política:

       kubectl apply -f opa.yaml

Parâmetros principais

Parâmetro

Descrição

spec.policy

Conteúdo da política Rego. Para sintaxe Rego, consulte Policy Language.

workloadSelector

Limita a política a pods com rótulos correspondentes no namespace especificado. Se omitido, a política se aplica a todos os pods do namespace.

user_roles

Mapeia nomes de usuário para funções. Neste exemplo, guest1 recebe a função guest e admin1 recebe a função admin.

role_perms

Defina as combinações permitidas de método HTTP e caminho para cada função.

Importante
  • Defina default allow em apenas uma política por pod. Várias políticas com default allow causam falhas na atualização dinâmica.

  • Use seletores de rótulo para definir o escopo das políticas com precisão. Uma política Rego inválida bloqueia todo o tráfego para os serviços afetados.

  • O OPA executa como sidecar no mesmo pod da sua aplicação e ocupa as portas 15081 e 9191.

  • Por padrão, default allow está definido como false. Não o defina novamente para evitar conflitos.

Implantar a aplicação de exemplo e verifique a injeção do OPA

Implante a aplicação de exemplo Bookinfo e confirme que os sidecars OPA estão em execução em cada pod.

  1. Implante a aplicação Bookinfo. Para mais informações, consulte Implantar uma aplicação em uma instância do ASM.

  2. Crie um gateway de entrada, um gateway Istio e um serviço virtual. Para mais informações, consulte Usar recursos do Istio para rotear tráfego para diferentes versões de um serviço.

  3. Verifique se o OPA foi injetado em cada pod: na aba Container, confirme a presença tanto do sidecar istio-proxy quanto do container opa-istio. Verifique cada pod da aplicação para garantir que ambos os containers foram injetados.

    1. Faça login no console do ACK. No painel de navegação à esquerda, clique em Clusters.

    2. Na página Clusters, clique em nome do cluster e escolha Workloads > Pods no painel de navegação à esquerda.

    3. Na página Pods, selecione default na lista suspensa Namespace e clique em nome de um pod.

    OPA injection verification

Testar o controle de acesso

Envie requisições como diferentes usuários para confirme que o OPA aplica as permissões baseadas em funções.

Defina o endereço IP do gateway de entrada como uma variável de ambiente:

export GATEWAY_IP=<ingress-gateway-ip>

Testar como guest1 (função guest)

Acesse /productpage -- resultado esperado: 200 OK

curl -X GET http://$GATEWAY_IP/productpage --user guest1:password -I
HTTP/1.1 200 OK

Acesse /api/v1/products -- resultado esperado: 403 Forbidden

curl -X GET http://$GATEWAY_IP/api/v1/products --user guest1:password -I
HTTP/1.1 403 Forbidden

O usuário guest1 possui a função guest, que permite apenas GET /productpage.

Testar como admin1 (função admin)

Acesse /productpage -- resultado esperado: 200 OK

curl -X GET http://$GATEWAY_IP/productpage --user admin1:password -I
HTTP/1.1 200 OK

Acesse /api/v1/products -- resultado esperado: 200 OK

curl -X GET http://$GATEWAY_IP/api/v1/products --user admin1:password -I
HTTP/1.1 200 OK

O usuário admin1 possui a função admin, que permite tanto GET /productpage quanto GET /api/v1/products.

Atualize uma política OPA dinamicamente

É possível atualizar políticas OPA em tempo de execução sem reiniciar os pods. No exemplo a seguir, o usuário guest1 recebe as funções guest e admin.

Edite a política:

kubectl edit asmopapolicy bookinfo-opa -n default

No editor, atualize a seção user_roles para atribuir ambas as funções a guest1:

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMOPAPolicy
metadata:
  name: bookinfo-opa
  namespace: default
spec:
  policy: |
    package istio.authz
    import input.attributes.request.http as http_request
    allow {
        roles_for_user[r]
        required_roles[r]
    }
    roles_for_user[r] {
        r := user_roles[user_name][_]
    }
    required_roles[r] {
        perm := role_perms[r][_]
        perm.method = http_request.method
        perm.path = http_request.path
    }
    user_name = parsed {
        [_, encoded] := split(http_request.headers.authorization, " ")
        [parsed, _] := split(base64url.decode(encoded), ":")
    }
    user_roles = {
        "guest1": ["guest", "admin"],
        "admin1": ["admin"]
    }
    role_perms = {
        "guest": [
            {"method": "GET",  "path": "/productpage"},
        ],
        "admin": [
            {"method": "GET",  "path": "/productpage"},
            {"method": "GET",  "path": "/api/v1/products"},
        ],
    }

Alteração principal: "guest1": ["guest"] agora é "guest1": ["guest", "admin"].

Verifique a política atualizada

Após a atualização, guest1 consegue acessar ambos os caminhos:

curl -X GET http://$GATEWAY_IP/productpage --user guest1:password -I
HTTP/1.1 200 OK
curl -X GET http://$GATEWAY_IP/api/v1/products --user guest1:password -I
HTTP/1.1 200 OK

Antes da atualização, guest1 recebia 403 Forbidden para /api/v1/products. Após a atualização, ambos os caminhos retornam 200 OK, confirmando a atualização dinâmica da política.

Cenários de exemplo

Cenário 1: Autorizar requisições com base em claims JWT

O OPA pode verificar JSON Web Tokens (JWTs) no cabeçalho Authorization e conceder ou negar acesso com base nas claims do token.

A política a seguir permite uma requisição GET para /productpage apenas quando o JWT contém Role: guest e userGroup: visitor:

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMOPAPolicy
metadata:
  name: policy-jwt
  namespace: default
spec:
  policy: |
    package istio.authz

    allow {
      input.attributes.request.http.method == "GET"
      input.parsed_path[0] == "productpage"
      # Verify JWT signature with shared secret
      io.jwt.verify_hs256(bearer_token, "B41BD5F462719C6D6118E673A2389")
      claims.Role == "guest"
      claims.userGroup == "visitor"
    }
    claims := payload {
       [_, payload, _] := io.jwt.decode(bearer_token)
    }
    bearer_token := t {
      v := input.attributes.request.http.headers.authorization
      startswith(v, "Bearer ")
      t := substring(v, count("Bearer "), -1)
    }

Campo

Descrição

input.attributes.request.http.method

Método HTTP. Definido como GET neste exemplo.

input.parsed_path[0]

Primeiro segmento do caminho da requisição, identificando a aplicação de destino.

claims.Role

Valor necessário da claim Role no JWT. Definido como guest neste exemplo.

claims.userGroup

Valor necessário da claim userGroup no JWT. Definido como visitor neste exemplo.

Codifique os campos Role e userGroup em uma string JWT usando uma ferramenta JWT.

JWT encoding

Teste a política:

curl --location --request GET 'http://$GATEWAY_IP/productpage' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiZ3Vlc3QxIiwiUm9sZSI6Imd1ZXN0IiwidXNlckdyb3VwIjoidmlzaXRvciJ9.44OnUFZwOzSWzC7hyVfcle-uYk8byv7q_BBxS10AEWc'

Saída esperada: 200. Uma requisição com JWT inválido ou ausente retorna 403.

Cenário 2: Referenciar cruzadamente o corpo HTTP com claims JWT

O OPA pode referenciar cruzadamente valores entre o corpo da requisição e as claims JWT. A política a seguir permite uma requisição GET para /productpage apenas quando o username no corpo da requisição corresponde à claim Role no JWT e a claim userGroup é manager:

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMOPAPolicy
metadata:
  name: policy-body
  namespace: default
spec:
  policy: |
    package istio.authz

    allow {
      input.attributes.request.http.method == "GET"
      input.parsed_path[0] == "productpage"
      io.jwt.verify_hs256(bearer_token, "B41BD5F462719C6D6118E673A2389")
      claims.Role == input.parsed_body.username
      claims.userGroup == "manager"
    }
    claims := payload {
       [_, payload, _] := io.jwt.decode(bearer_token)
    }
    bearer_token := t {
      v := input.attributes.request.http.headers.authorization
      startswith(v, "Bearer ")
      t := substring(v, count("Bearer "), -1)
    }

Campo

Descrição

claims.Role == input.parsed_body.username

A claim Role no JWT deve corresponder ao campo username no corpo da requisição.

claims.userGroup

A claim userGroup deve ser manager.

Codifique as claims em um JWT usando uma ferramenta JWT.

JWT encoding for body validation

Teste a política:

curl --location --request GET 'http://$GATEWAY_IP/productpage' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiZ3Vlc3QxIiwiUm9sZSI6ImFkbWluIiwidXNlckdyb3VwIjoibWFuYWdlciJ9.pAUvTeONHF-i5Ps-EUYYXk-hnaz-j-ZgP_wXJZMBiR0' \
--header 'Content-Type: application/json' \
--header 'Cookie: session=eyJ1c2VyIjoiYWRtaW4ifQ.YRz90g.GT34_5BqlFTwGqabZk_qGZzxYQ0' \
--data-raw '{
    "username":"admin",
    "password":"12****"
}'

Saída esperada: 200. A claim Role do JWT (admin) corresponde ao username do corpo (admin) e userGroup é manager. Um JWT incompatível ou ausente retorna 403.

Cenário 3: Aplicar uma lista de permissões de usuários com contexto adicional

Baseado no Cenário 2, esta política adiciona uma verificação de lista de permissões: a claim username no JWT também deve constar em uma lista predefinida de bookinfo_managers.

A política permite uma requisição GET para /productpage apenas se todas as condições a seguir forem atendidas:

  • A claim Role no JWT corresponde ao username no corpo da requisição.

  • A claim userGroup é manager.

  • A claim username está na lista bookinfo_managers (user1, user2 ou user3).

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMOPAPolicy
metadata:
  name: policy-range
  namespace: default
spec:
  policy: |
    package istio.authz
    bookinfo_managers = [{"name": "user1"}, {"name": "user2"}, {"name": "user3"}]

    allow {
      input.attributes.request.http.method == "GET"
      input.parsed_path[0] == "productpage"
      io.jwt.verify_hs256(bearer_token, "B41BD5F462719C6D6118E673A2389")
      claims.Role == input.parsed_body.username
      claims.userGroup == "manager"
      claims.username == bookinfo_managers[_].name
    }
    claims := payload {
       [_, payload, _] := io.jwt.decode(bearer_token)
    }
    bearer_token := t {
      v := input.attributes.request.http.headers.authorization
      startswith(v, "Bearer ")
      t := substring(v, count("Bearer "), -1)
    }

Campo

Descrição

bookinfo_managers

Lista de permissões de nomes de usuário de gerentes autorizados.

claims.username == bookinfo_managers[_].name

A claim username no JWT deve corresponder a uma entrada na lista bookinfo_managers.

Codifique as claims em um JWT usando uma ferramenta JWT.

JWT encoding for context validation

Teste a política:

curl --location --request GET 'http://$GATEWAY_IP/productpage' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxIiwiUm9sZSI6ImFkbWluIiwidXNlckdyb3VwIjoibWFuYWdlciJ9.2X0Fmb96jBexLcVm_55t8ZY6XveSxUAsQ1j3ar5dI_g' \
--header 'Content-Type: application/json' \
--header 'Cookie: session=eyJ1c2VyIjoiYWRtaW4ifQ.YRz90g.GT34_5BqlFTwGqabZk_qGZzxYQ0' \
--data-raw '{
    "username":"admin",
    "password":"12****"
}'

Saída esperada: 200. A claim username do JWT (user1) está na lista bookinfo_managers, a claim Role corresponde ao username do corpo e userGroup é manager. Uma requisição que falhar em qualquer condição retorna 403.

Perguntas frequentes

Como verifico se um pod usa políticas OPA?

O OPA executa como sidecar no mesmo pod da sua aplicação. Conecte-se ao pod e consulte a API do OPA:

curl 127.0.0.1:15081/v1/policies

Como valido políticas Rego antes da implantação?

Use o OPA Playground para testar e depurar políticas Rego online antes de aplicá-las à sua instância do ASM.

Consulte também

Para definir políticas OPA usando ConfigMaps em vez de recursos ASMOPAPolicy: