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.

Pré-requisitos
Uma instância do ASM versão 1.9.7 ou posterior. Para mais informações, consulte Crie uma instância do ASM.
Um cluster adicionado à instância do ASM. Para mais informações, consulte Adicionar um cluster a uma instância do ASM.
Injeção automática de proxy sidecar ativada para o namespace
default. Para mais informações, consulte a seção "Ative injeção automática de proxy sidecar" no tópico Gerencie namespaces globais.
Ative o plug-in OPA e o controle de escopo de injeção
Faça login no console do ASM. No painel de navegação à esquerda, escolha Service Mesh > Mesh Management.
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.
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 /productpageadmin: pode executar
GET /productpageeGET /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
Faça login no console do ASM. No painel de navegação à esquerda, escolha Service Mesh > Mesh Management.
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.
-
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.
Opção B: Usar kubectl
-
Crie um arquivo chamado
opa.yamlcom o seguinte conteúdo: -
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 |
|
|
Conteúdo da política Rego. Para sintaxe Rego, consulte Policy Language. |
|
|
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. |
|
|
Mapeia nomes de usuário para funções. Neste exemplo, |
|
|
Defina as combinações permitidas de método HTTP e caminho para cada função. |
Defina
default allowem apenas uma política por pod. Várias políticas comdefault allowcausam 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 allowestá definido comofalse. 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.
Implante a aplicação Bookinfo. Para mais informações, consulte Implantar uma aplicação em uma instância do ASM.
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.
-
Verifique se o OPA foi injetado em cada pod: na aba Container, confirme a presença tanto do sidecar
istio-proxyquanto do containeropa-istio. Verifique cada pod da aplicação para garantir que ambos os containers foram injetados.Faça login no console do ACK. No painel de navegação à esquerda, clique em Clusters.
Na página Clusters, clique em nome do cluster e escolha Workloads > Pods no painel de navegação à esquerda.
Na página Pods, selecione default na lista suspensa Namespace e clique em nome de um pod.

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 |
|
|
Método HTTP. Definido como |
|
|
Primeiro segmento do caminho da requisição, identificando a aplicação de destino. |
|
|
Valor necessário da claim |
|
|
Valor necessário da claim |
Codifique os campos Role e userGroup em uma string JWT usando uma ferramenta JWT.

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 |
|
|
A claim |
|
|
A claim |
Codifique as claims em um JWT usando uma ferramenta JWT.

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
Roleno JWT corresponde aousernameno corpo da requisição.A claim
userGroupémanager.A claim
usernameestá na listabookinfo_managers(user1,user2ouuser3).
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 |
|
|
Lista de permissões de nomes de usuário de gerentes autorizados. |
|
|
A claim |
Codifique as claims em um JWT usando uma ferramenta JWT.

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: