Tous les produits
Search
Centre de documentation

Alibaba Cloud Service Mesh:Utiliser des politiques OPA pour un contrôle d'accès granulaire

Dernière mise à jour :Aug 24, 2026

Service Mesh (ASM) s'intègre au plugin Open Policy Agent (OPA), ce qui permet d'appliquer un contrôle d'accès granulaire à vos applications via des politiques OPA. ASM vous permet de définir ces politiques sur le plan de contrôle et de les pousser vers les clusters du plan de données. Cette rubrique explique comment utiliser cette fonctionnalité pour contrôler l'accès en fonction de critères tels que l'URL de la requête et les jetons présents dans l'en-tête de la requête.

Prérequis

Contexte

Hébergé par la CNCF en tant que projet en incubation, Open Policy Agent (OPA) est un moteur de politiques permettant de mettre en œuvre un contrôle d'accès granulaire pour vos applications. En tant que moteur de politiques polyvalent, OPA peut être déployé en tant que service autonome aux côtés des microservices. Pour protéger les applications, chaque requête adressée à un microservice doit être autorisée avant son traitement. Pour vérifier cette autorisation, le microservice effectue un appel API vers OPA afin de déterminer si la requête est légitime.OPA

Étape 1 : Activer le plugin OPA et le contrôle de portée

  1. Connectez-vous à la console ASM. Dans le volet de navigation de gauche, sélectionnez Service Mesh > Mesh Management.

  2. Sur la page Mesh Management , cliquez sur le nom de l'instance ASM. Dans le volet de navigation de gauche, sélectionnez Mesh Security Center > OPA Policy.

  3. Sur la page OPA Policy , activez les options Enable Open Policy Agent (OPA) Plugin et Enable OPA Injection Scope Control , puis cliquez sur Enable OPA . Dans la boîte de dialogue Note qui s'affiche, cliquez sur OK .

Étape 2 : Créer une politique OPA

Vous créez une ressource ASMOPAPolicy sur le plan de contrôle ASM. ASM pousse ensuite cette ressource vers le cluster du plan de données, où le moteur OPA présent dans chaque pod concerné l'utilise pour appliquer un contrôle d'accès granulaire.

Option 1 : Utiliser la console ASM

  1. Connectez-vous à la console ASM. Dans le volet de navigation de gauche, sélectionnez Service Mesh > Mesh Management.

  2. Sur la page Mesh Management , cliquez sur le nom de l'instance ASM. Dans le volet de navigation de gauche, sélectionnez Mesh Security Center > OPA Policy.

  3. Sur la page OPA Policy , cliquez sur Create . Sélectionnez le namespace default , définissez le Name de la politique OPA sur bookinfo-opa , puis cliquez sur Add Matching Label . Définissez le Name sur version et la Value sur v1 . Copiez les règles Rego suivantes dans la zone de texte, puis cliquez sur Create .

    Afficher les règles Rego

    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"},
        ],
    }

Option 2 : Utiliser kubectl

  1. Créez un fichier nommé opa.yaml contenant le code suivant.

    Afficher opa.yaml

    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"},
            ],
        }
    Remarque
    • Lorsque vous définissez une politique OPA pour un pod, vous ne pouvez inclure qu'un seul champ default allow . Si plusieurs politiques OPA s'appliquent à un même pod et que chacune définit un champ default allow , la présence de multiples champs default allow entraîne l'échec des mises à jour dynamiques.

    • Définissez la portée des politiques à l'aide de libellés. Une règle Rego invalide peut rendre un service inaccessible.

    • Le moteur d'exécution OPA et le conteneur d'application s'exécutent dans le même pod et occupent les ports 15081 et 9191.

    • Par défaut, les politiques OPA appliquent la règle allow = false . Ne redéfinissez pas default allow afin d'éviter les conflits.

    Paramètre

    Description

    spec

    Les règles de la politique, rédigées dans le langage Rego. Pour plus d'informations sur la syntaxe Rego, consultez la documentation Rego .

    workloadSelector

    Spécifie la portée de la politique au sein du namespace. Si ce paramètre est omis, la politique s'applique à tous les pods du namespace. S'il est spécifié, elle ne s'applique qu'aux pods dont les libellés correspondent.

    user_roles

    Accorde des permissions de rôle aux utilisateurs. Dans cet exemple, l'utilisateur guest1 reçoit le rôle guest , et l'utilisateur admin1 reçoit le rôle admin .

    role_perms

    Définit les permissions associées à chaque rôle. Dans cet exemple, le rôle guest peut accéder à /productpage , tandis que le rôle admin peut accéder à /productpage et à /api/v1/products .

  2. Exécutez la commande suivante pour créer la politique OPA.

    Pour savoir comment se connecter à une instance ASM à l'aide de kubectl, consultez la section Utiliser kubectl sur le plan de contrôle pour accéder aux ressources Istio .

    kubectl apply -f opa.yaml

Étape 3 : Injecter le proxy OPA

Déployez l'application exemple Bookinfo sur l'instance ASM et vérifiez qu'ASM a injecté le proxy OPA dans chaque pod.

  1. Déployez l'application exemple Bookinfo sur l'instance ASM. Pour plus d'informations, consultez la section Déployer une application dans un cluster associé à une instance ASM .

  2. Créez une passerelle d'entrée, une passerelle Istio et un service virtuel. Pour plus d'informations, consultez la section Utiliser les ressources Istio pour router le trafic en fonction des versions .

  3. Vérifiez si le proxy OPA est injecté dans chaque pod d'application.

    1. Connectez-vous à la console ACK . Dans le volet de navigation de gauche, cliquez sur Clusters .

    2. Sur la page Clusters , cliquez sur le nom de votre cluster. Dans le volet de navigation de gauche, cliquez sur Workloads > Pods .

    3. Sur la page Pods , sélectionnez default dans la liste déroulante Namespace , puis cliquez sur le nom du pod d'application cible.

      Dans l'onglet Containers , vérifiez que le pod contient à la fois les conteneurs istio-proxy (le proxy sidecar) et opa-istio (le proxy OPA).

Étape 4 : Vérifier la politique de contrôle d'accès OPA

  1. Exécutez la commande suivante pour accéder à /productpage .

    curl -X GET http://<INGRESS_GATEWAY_IP>/productpage --user guest1:password -I

    Résultat attendu :

    HTTP/1.1 200 OK
  2. Exécutez la commande suivante pour accéder à /api/v1/products .

    curl -X GET http://<INGRESS_GATEWAY_IP>/api/v1/products --user guest1:password -I

    Résultat attendu :

    HTTP/1.1 403 Forbidden

    Ces résultats confirment que l'utilisateur guest1, doté du rôle guest, peut accéder à /productpage mais se voit refuser l'accès à /api/v1/products .

  3. Exécutez la commande suivante pour accéder à /productpage .

    curl -X GET http://<INGRESS_GATEWAY_IP>/productpage --user admin1:password -I

    Résultat attendu :

    HTTP/1.1 200 OK
  4. Exécutez la commande suivante pour accéder à /api/v1/products .

    curl -X GET http://<INGRESS_GATEWAY_IP>/api/v1/products --user admin1:password -I

    Résultat attendu :

    HTTP/1.1 200 OK

    Les résultats indiquent que admin1 dispose du rôle admin . L'utilisateur admin1 peut accéder à la fois à /productpage et à /api/v1/products . Cela confirme que la politique de contrôle d'accès OPA fonctionne comme prévu.

Étape 5 : Mettre à jour dynamiquement une politique OPA

Exécutez la commande suivante pour modifier la politique OPA.

kubectl edit asmopapolicy bookinfo-opa -n default 

Dans la sortie, modifiez la politique OPA pour accorder à guest1 les rôles guest et admin .

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"},
        ],
    }
  • user_roles : Accorde des permissions de rôle aux utilisateurs. Dans cet exemple, l'utilisateur guest1 reçoit les rôles guest et admin , tandis que l'utilisateur admin1 reçoit le rôle admin .

  • role_perms : Définit les permissions associées à chaque rôle. Dans cet exemple, le rôle guest peut accéder à /productpage , tandis que le rôle admin peut accéder à la fois à /productpage et à /api/v1/products .

Étape 6 : Vérifier la mise à jour dynamique

  1. Exécutez la commande suivante pour accéder à /productpage .

    curl -X GET http://<INGRESS_GATEWAY_IP>/productpage --user guest1:password -I

    Résultat attendu :

    HTTP/1.1 200 OK
  2. Exécutez la commande suivante pour accéder à /api/v1/products .

    curl -X GET http://<INGRESS_GATEWAY_IP>/api/v1/products --user guest1:password -I

    Résultat attendu :

    HTTP/1.1 200 OK

    Auparavant, guest1 ne pouvait accéder qu'à /productpage . Après la mise à jour, guest1 peut également accéder à /api/v1/products , ce qui confirme le succès de la mise à jour dynamique de la politique.

Scénarios

Scénario 1 : Autoriser les requêtes en fonction des revendications JWT

Ce scénario illustre la procédure d'autorisation des requêtes basée sur les revendications contenues dans un jeton Web JSON (JWT). La politique vérifie le JWT présent dans l'en-tête de la requête, afin de n'autoriser que les requêtes fiables à accéder à l'application.

La stratégie ASMOPAPolicy ci-dessous autorise l'accès à l'application Productpage uniquement si la requête utilise la méthode GET, si la revendication Role du JWT est définie sur guest et si la revendication userGroup est définie sur 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"
      # set certificate 'B41BD5F462719C6D6118E673A2389'
      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)
    }
  • input.attributes.request.http.method : Méthode de la requête. Dans cet exemple, la valeur est GET.

  • input.parsed_path[0] : Application ciblée par l'accès.

  • claims.Role : Restreint le JWT. Dans cet exemple, la valeur Role doit être guest.

  • claims.userGroup : Restreint le JWT. Dans cet exemple, la valeur userGroup doit être visitor.

Utilisez un outil JWT pour encoder les informations de la requête, telles que Role et userGroup, dans une chaîne JWT. Dans la section Payload de l'outil d'encodage JWT, outre Role et userGroup, vous devez également définir name sur guest1, configurer la clé de signature sur B41BD5F462719C6D6118 et sélectionner l'algorithme HS256. Après l'encodage, vous obtenez la chaîne JWT nécessaire à l'autorisation de la requête.

Exécutez la commande suivante pour accéder à l'application Productpage.

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

Résultat attendu :

HTTP/1.1 200 OK

Une réponse 200 indique que la requête GET adressée à l'application Productpage a abouti. Ce résultat s'observe lorsque la requête inclut un jeton JWT dont la revendication Role est définie sur guest et la revendication userGroup sur visitor. Si un jeton JWT incorrect est utilisé, ou si la requête ne contient aucun jeton JWT, une réponse 403 est renvoyée, signalant l'échec de l'accès à l'application Productpage.

Scénario 2 : Restreindre le corps de la requête HTTP

Ce scénario montre comment autoriser les requêtes en validant les champs du corps de la requête HTTP par rapport aux revendications du JWT.

La stratégie ASMOPAPolicy ci-dessous autorise l'accès à l'application Productpage uniquement si la requête utilise la méthode GET, si le champ username du corps de la requête correspond à la revendication Role du JWT, et si la revendication userGroup est définie sur 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)
    }
  • input.attributes.request.http.method : Méthode de la requête. Dans cet exemple, la valeur est GET.

  • input.parsed_path[0] : Application ciblée par l'accès.

  • claims.Role : Restreint le JWT. Dans cet exemple, la valeur est définie sur input.parsed_body.username, ce qui impose que le champ username du corps de la requête corresponde à la revendication Role du JWT.

  • claims.userGroup : Restreint le JWT. Dans cet exemple, la valeur userGroup doit être manager.

Utilisez un outil JWT pour encoder les informations de la requête, telles que Role et userGroup, dans une chaîne JWT.

Exécutez la commande suivante pour accéder à l'application Productpage.

curl --location --request GET 'http://<INGRESS_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****"
}'

Résultat attendu :

HTTP/1.1 200 OK

Une réponse 200 OK indique qu'une requête GET peut accéder à l'application Productpage si le champ username du corps de la requête correspond à la revendication Role du JWT et si la revendication userGroup du JWT est définie sur manager. Des jetons JWT invalides ou absents entraînent une réponse 403 Forbidden.

Scénario 3 : Restreindre davantage d'informations contextuelles

En vous basant sur le scénario 2, vous pouvez restreindre davantage d'informations contextuelles. Par exemple, vous pouvez exiger que la revendication username du JWT figure dans la liste bookinfo_managers.

La stratégie ASMOPAPolicy ci-dessous autorise l'accès à l'application Productpage uniquement si la requête utilise la méthode GET, si le champ username du corps de la requête correspond à la revendication Role du JWT, si la revendication username du JWT figure dans la liste bookinfo_managers et si la revendication userGroup est définie sur manager.

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)
    }
  • input.attributes.request.http.method : Méthode de la requête. Dans cet exemple, la valeur est GET.

  • input.parsed_path[0] : Application ciblée par l'accès.

  • claims.Role : Restreint le JWT. Dans cet exemple, la valeur est définie sur input.parsed_body.username, ce qui impose que le nom d'utilisateur du corps de la requête corresponde à la revendication Role du JWT.

  • claims.userGroup : Restreint le JWT. Dans cet exemple, la valeur userGroup doit être manager.

  • claims.username : Restreint le JWT. Dans cet exemple, la valeur est définie sur bookinfo_managers[_].name, ce qui impose que la revendication username du JWT figure dans la liste bookinfo_managers.

Utilisez un outil JWT pour encoder les informations de la requête dans une chaîne JWT.

Exécutez la commande suivante pour accéder à l'application Productpage.

curl --location --request GET 'http://<INGRESS_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****"
}'

Résultat attendu :

HTTP/1.1 200 OK

Une réponse 200 OK indique qu'une requête GET peut accéder à l'application Productpage si le champ username du corps de la requête correspond à la revendication Role du JWT, si la revendication username du JWT figure dans la liste bookinfo_managers et si la revendication userGroup du JWT est définie sur manager. Des jetons JWT invalides ou absents entraînent une réponse 403 Forbidden.

FAQ

Comment vérifier les politiques OPA sur un pod ?

Le moteur OPA s'exécute en tant que sidecar dans le pod de l'application. Pour afficher toutes les politiques OPA appliquées à un pod, connectez-vous au pod et exécutez la commande suivante :

curl 127.0.0.1:15081/v1/policies

Comment tester la syntaxe Rego ?

OPA met à disposition un outil de test en ligne permettant de valider les politiques Rego.

Références

Si vous utilisiez auparavant des ConfigMaps pour configurer les politiques OPA, consultez les rubriques suivantes :