All Products
Search
Document Center

Alibaba Cloud Service Mesh:Gunakan kebijakan OPA untuk kontrol akses detail halus

Last Updated:Aug 21, 2026

Service Mesh (ASM) terintegrasi dengan plugin Open Policy Agent (OPA), memungkinkan kontrol akses detail halus untuk aplikasi Anda melalui kebijakan OPA. ASM memungkinkan Anda menentukan kebijakan ini pada control plane dan mendorongnya ke kluster data plane. Topik ini menjelaskan cara menggunakan fitur ini untuk mengontrol akses berdasarkan kriteria seperti URL permintaan dan token dalam header permintaan.

Prasyarat

Latar Belakang

Sebagai proyek inkubasi yang dihosting oleh CNCF, Open Policy Agent (OPA) adalah mesin kebijakan yang dapat digunakan untuk menerapkan kontrol akses detail halus pada aplikasi Anda. Sebagai mesin kebijakan tujuan umum, OPA dapat dideploy sebagai layanan mandiri bersama layanan mikro. Untuk melindungi aplikasi, setiap permintaan ke layanan mikro harus melalui otorisasi sebelum diproses. Untuk memeriksa otorisasi tersebut, layanan mikro melakukan panggilan API ke OPA guna menentukan apakah permintaan tersebut diizinkan.OPA

Langkah 1: Aktifkan plugin OPA dan kontrol cakupan

  1. Login ke Konsol ASM. Di panel navigasi kiri, pilih Service Mesh > Mesh Management.

  2. Pada halaman Mesh Management, klik nama instans ASM. Di panel navigasi kiri, pilih Mesh Security Center > OPA Policy.

  3. Pada halaman OPA Policy, pilih Enable Open Policy Agent (OPA) Plugin dan Enable OPA Injection Scope Control, klik Enable OPA, lalu klik OK pada kotak dialog Note.

Langkah 2: Buat kebijakan OPA

Anda membuat resource ASMOPAPolicy pada control plane ASM. ASM kemudian mendorong resource ini ke kluster data plane, tempat mesin OPA di setiap Pod terkait menggunakannya untuk menerapkan kontrol akses detail halus.

Opsi 1: Gunakan Konsol ASM

  1. Login ke Konsol ASM. Di panel navigasi kiri, pilih Service Mesh > Mesh Management.

  2. Pada halaman Mesh Management, klik nama instans ASM. Di panel navigasi kiri, pilih Mesh Security Center > OPA Policy.

  3. Pada halaman OPA Policy, klik Create. Pilih namespace default, atur Name kebijakan OPA menjadi bookinfo-opa, lalu klik Add Matching Label. Atur Name menjadi version dan Value menjadi v1. Salin aturan Rego berikut ke dalam kotak teks, lalu klik Create.

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

Opsi 2: Gunakan kubectl

  1. Buat file bernama opa.yaml dengan konten berikut.

    Lihat 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"},
            ],
        }
    Catatan
    • Saat menentukan kebijakan OPA untuk sebuah Pod, Anda hanya boleh menyertakan satu field default allow. Jika beberapa kebijakan OPA berlaku untuk satu Pod dan masing-masing mendefinisikan field default allow, maka field default allow ganda tersebut akan menyebabkan pembaruan dinamis gagal.

    • Cakup kebijakan menggunakan label. Aturan Rego yang tidak valid dapat membuat layanan tidak dapat diakses.

    • Mesin eksekusi OPA dan kontainer aplikasi berjalan dalam Pod yang sama serta menggunakan Port 15081 dan 9191.

    • Kebijakan OPA secara default bernilai allow = false. Jangan mendefinisikan ulang default allow untuk menghindari konflik.

    Parameter

    Deskripsi

    spec

    Aturan kebijakan, ditulis dalam bahasa Rego. Untuk informasi selengkapnya tentang sintaksis Rego, lihat Rego.

    workloadSelector

    Menentukan cakupan kebijakan dalam namespace. Jika dihilangkan, kebijakan berlaku untuk semua Pod dalam namespace tersebut. Jika ditentukan, kebijakan hanya berlaku untuk Pod dengan label yang sesuai.

    user_roles

    Memberikan izin peran kepada pengguna. Dalam contoh ini, pengguna guest1 diberikan peran guest, dan pengguna admin1 diberikan peran admin.

    role_perms

    Menentukan izin setiap peran. Dalam contoh ini, peran guest dapat mengakses /productpage, sedangkan peran admin dapat mengakses /productpage dan /api/v1/products.

  2. Jalankan perintah berikut untuk membuat kebijakan OPA.

    Untuk informasi selengkapnya tentang cara menghubungkan ke instans ASM menggunakan kubectl, lihat Gunakan kubectl pada control plane untuk mengakses resource Istio.

    kubectl apply -f opa.yaml

Langkah 3: Injeksikan proxy OPA

Deploy aplikasi sampel Bookinfo ke instans ASM dan pastikan bahwa ASM telah menginjeksikan proxy OPA ke setiap Pod.

  1. Deploy aplikasi sampel Bookinfo ke instans ASM. Untuk informasi selengkapnya, lihat Deploy aplikasi di kluster yang terkait dengan instans ASM.

  2. Buat ingress gateway, gateway Istio, dan virtual service. Untuk informasi selengkapnya, lihat Gunakan resource Istio untuk merutekan traffic berdasarkan versi.

  3. Periksa apakah proxy OPA telah diinjeksikan ke setiap Pod aplikasi.

    1. Masuk ke Konsol ACK. Di panel navigasi kiri, klik Clusters.

    2. Pada halaman Clusters, klik nama kluster Anda. Di panel navigasi kiri, klik Workloads > Pods.

    3. Pada halaman Pods, pilih default dari daftar drop-down Namespace lalu klik nama Pod aplikasi target.

      Pada tab Containers, verifikasi bahwa Pod berisi kontainer istio-proxy (sidecar proxy) dan opa-istio (proxy OPA).

Langkah 4: Verifikasi kebijakan kontrol akses OPA

  1. Jalankan perintah berikut untuk mengakses /productpage.

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

    Output yang diharapkan:

    HTTP/1.1 200 OK
  2. Jalankan perintah berikut untuk mengakses /api/v1/products.

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

    Output yang diharapkan:

    HTTP/1.1 403 Forbidden

    Hasil ini mengonfirmasi bahwa pengguna guest1, dengan peran guest, dapat mengakses /productpage tetapi ditolak saat mengakses /api/v1/products.

  3. Jalankan perintah berikut untuk mengakses /productpage.

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

    Output yang diharapkan:

    HTTP/1.1 200 OK
  4. Jalankan perintah berikut untuk mengakses /api/v1/products.

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

    Output yang diharapkan:

    HTTP/1.1 200 OK

    Hasil ini menunjukkan bahwa admin1 diberikan peran admin. admin1 dapat mengakses baik /productpage maupun /api/v1/products. Hal ini menunjukkan bahwa kebijakan kontrol akses OPA berfungsi sebagaimana mestinya.

Langkah 5: Perbarui kebijakan OPA secara dinamis

Jalankan perintah berikut untuk mengubah kebijakan OPA.

kubectl edit asmopapolicy bookinfo-opa -n default 

Pada output, edit kebijakan OPA untuk memberikan guest1 kedua peran guest dan 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: Memberikan izin peran kepada pengguna. Dalam contoh ini, pengguna guest1 diberikan peran guest dan admin, sedangkan pengguna admin1 diberikan peran admin.

  • role_perms: Menentukan izin setiap peran. Dalam contoh ini, peran guest dapat mengakses /productpage, sedangkan peran admin dapat mengakses /productpage dan /api/v1/products.

Langkah 6: Verifikasi pembaruan dinamis

  1. Jalankan perintah berikut untuk mengakses /productpage.

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

    Output yang diharapkan:

    HTTP/1.1 200 OK
  2. Jalankan perintah berikut untuk mengakses /api/v1/products.

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

    Output yang diharapkan:

    HTTP/1.1 200 OK

    Sebelumnya, guest1 hanya dapat mengakses /productpage. Setelah pembaruan, guest1 juga dapat mengakses /api/v1/products, yang mengonfirmasi bahwa pembaruan kebijakan dinamis berhasil.

Skenario

Skenario 1: Otorisasi permintaan berdasarkan klaim JWT

Skenario ini menunjukkan cara mengotorisasi permintaan berdasarkan klaim dalam JSON Web Token (JWT). Kebijakan ini memverifikasi JWT dalam header permintaan, sehingga hanya permintaan tepercaya yang dapat mengakses aplikasi.

ASMOPAPolicy berikut hanya mengizinkan akses ke aplikasi Productpage ketika permintaan menggunakan metode GET, klaim Role dalam JWT bernilai guest, dan klaim userGroup bernilai 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: Metode permintaan. Dalam contoh ini, nilainya adalah GET.

  • input.parsed_path[0]: Aplikasi yang diakses.

  • claims.Role: Membatasi JWT. Dalam contoh ini, Role harus bernilai guest.

  • claims.userGroup: Membatasi JWT. Dalam contoh ini, userGroup harus bernilai visitor.

Gunakan tool JWT untuk mengencode informasi permintaan seperti Role dan userGroup ke dalam string JWT. Di bagian Payload tool encoding JWT, selain Role dan userGroup, Anda juga perlu mengatur name menjadi guest1, kunci penandatanganan menjadi B41BD5F462719C6D6118, dan memilih algoritma HS256. Setelah diencode, Anda dapat memperoleh string JWT untuk otorisasi permintaan.

Jalankan perintah berikut untuk mengakses aplikasi Productpage.

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

Output yang diharapkan:

HTTP/1.1 200 OK

Respons 200 menunjukkan bahwa permintaan GET ke aplikasi Productpage berhasil. Hal ini terjadi ketika permintaan mencakup Token JWT dengan klaim Role bernilai guest dan klaim userGroup bernilai visitor. Jika Token JWT yang salah digunakan atau permintaan tidak berisi Token JWT, respons 403 akan dikembalikan, yang menunjukkan bahwa akses ke aplikasi Productpage gagal.

Skenario 2: Batasi badan permintaan HTTP

Skenario ini menunjukkan cara mengotorisasi permintaan dengan memvalidasi bidang dalam badan permintaan HTTP terhadap klaim dalam JWT.

ASMOPAPolicy berikut hanya mengizinkan akses ke aplikasi Productpage ketika permintaan menggunakan metode GET, username dalam badan permintaan cocok dengan klaim Role dalam JWT, dan klaim userGroup bernilai 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: Metode permintaan. Dalam contoh ini, nilainya adalah GET.

  • input.parsed_path[0]: Aplikasi yang diakses.

  • claims.Role: Membatasi JWT. Dalam contoh ini, nilainya diatur ke input.parsed_body.username, yang mensyaratkan bahwa username dalam badan permintaan harus cocok dengan klaim Role dalam JWT.

  • claims.userGroup: Membatasi JWT. Dalam contoh ini, userGroup harus bernilai manager.

Gunakan tool JWT untuk mengencode informasi permintaan seperti Role dan userGroup ke dalam string JWT.

Jalankan perintah berikut untuk mengakses aplikasi 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****"
}'

Output yang diharapkan:

HTTP/1.1 200 OK

Respons 200 OK menunjukkan bahwa permintaan GET dapat mengakses aplikasi Productpage jika username dalam badan permintaan cocok dengan klaim Role dalam JWT dan klaim userGroup dalam JWT bernilai manager. JWT yang tidak valid atau tidak ada akan menghasilkan respons 403 Forbidden.

Skenario 3: Batasi informasi kontekstual lebih lanjut

Berdasarkan Skenario 2, Anda dapat membatasi informasi kontekstual lebih lanjut. Misalnya, Anda dapat mensyaratkan bahwa klaim username dalam JWT harus berada dalam daftar bookinfo_managers.

ASMOPAPolicy berikut hanya mengizinkan akses ke aplikasi Productpage ketika permintaan menggunakan metode GET, username dalam badan permintaan cocok dengan klaim Role dalam JWT, klaim username dalam JWT berada dalam daftar bookinfo_managers, dan klaim userGroup bernilai 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: Metode permintaan. Dalam contoh ini, nilainya adalah GET.

  • input.parsed_path[0]: Aplikasi yang diakses.

  • claims.Role: Membatasi JWT. Dalam contoh ini, nilainya diatur ke input.parsed_body.username, yang mensyaratkan bahwa username dalam badan permintaan harus cocok dengan klaim Role dalam JWT.

  • claims.userGroup: Membatasi JWT. Dalam contoh ini, userGroup harus bernilai manager.

  • claims.username: Membatasi JWT. Dalam contoh ini, nilainya diatur ke bookinfo_managers[_].name, yang mensyaratkan bahwa klaim username dalam JWT harus ada dalam daftar bookinfo_managers.

Gunakan tool JWT untuk mengencode informasi permintaan ke dalam string JWT.

Jalankan perintah berikut untuk mengakses aplikasi 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****"
}'

Output yang diharapkan:

HTTP/1.1 200 OK

Respons 200 OK menunjukkan bahwa permintaan GET dapat mengakses aplikasi Productpage jika username dalam badan permintaan cocok dengan klaim Role dalam JWT, klaim username dalam JWT ada dalam daftar bookinfo_managers, dan klaim userGroup dalam JWT bernilai manager. JWT yang tidak valid atau tidak ada akan menghasilkan respons 403 Forbidden.

FAQ

Bagaimana cara memeriksa kebijakan OPA pada sebuah Pod?

Mesin OPA berjalan sebagai sidecar dalam Pod aplikasi. Untuk melihat semua kebijakan OPA yang berlaku pada sebuah Pod, login ke Pod tersebut dan jalankan perintah berikut:

curl 127.0.0.1:15081/v1/policies

Bagaimana cara menguji sintaksis Rego?

OPA menyediakan tool pengujian online untuk memvalidasi kebijakan Rego.

Referensi

Jika sebelumnya Anda menggunakan ConfigMap untuk mengonfigurasi kebijakan OPA, lihat topik berikut: