全部产品
Search
文档中心

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

更新时间:Jul 02, 2025

Service Mesh (ASM) terintegrasi dengan Plugin Open Policy Agent (OPA). Anda dapat menggunakan OPA untuk mendefinisikan kebijakan kontrol akses guna menerapkan kontrol akses granular halus pada aplikasi Anda. ASM memungkinkan Anda mendefinisikan kebijakan OPA di bidang kontrol dan mendorong kebijakan tersebut ke kluster pada bidang data. Topik ini menjelaskan cara mendefinisikan kebijakan OPA di ASM untuk menerapkan kontrol akses granular halus pada aplikasi Anda. Sebagai contoh, Anda dapat mendefinisikan kebijakan OPA untuk mengizinkan atau memblokir permintaan berdasarkan URL permintaan atau token dalam header permintaan. Topik ini juga menyediakan skenario contoh di mana kebijakan OPA digunakan untuk menerapkan kontrol akses.

Prasyarat

Informasi latar belakang

OPA adalah proyek Lulus dari Cloud Native Computing Foundation (CNCF). Sebagai mesin kebijakan, OPA dapat digunakan untuk menerapkan kontrol akses granular halus pada aplikasi Anda. Anda dapat menerapkan OPA sebagai layanan mandiri bersama dengan mikro layanan. Untuk melindungi aplikasi, pastikan bahwa setiap permintaan ke mikro layanan aplikasi diotorisasi sebelum permintaan diproses. Untuk memeriksa otorisasi, mikro layanan membuat panggilan API ke OPA untuk memeriksa apakah permintaan tersebut diotorisasi.OPA

Langkah 1: Aktifkan plugin OPA dan fitur pengendalian ruang lingkup injeksi OPA

  1. Masuk ke Konsol ASM. Di panel navigasi di sebelah kiri, pilih Service Mesh > Mesh Management.

  2. Di halaman Mesh Management, klik nama instance ASM. Di panel navigasi di sebelah kiri, pilih Mesh Security Center > OPA Policy.

  3. Di halaman OPA Policy, pilih Enable Open Policy Agent (OPA) Plug-in dan Enable OPA Injection Range Control, lalu klik Enable OPA. Di pesan Note, klik OK.

Langkah 2: Buat kebijakan OPA

Setelah Anda membuat kebijakan OPA di bidang kontrol instance ASM, kebijakan OPA didorong ke kluster pada bidang data. Kemudian, OPA di pod kluster menggunakan kebijakan OPA untuk menerapkan kontrol akses granular halus. Anda dapat membuat kebijakan OPA dengan menggunakan metode berikut:

Metode 1: Buat kebijakan OPA di konsol ASM

  1. Masuk ke Konsol ASM. Di panel navigasi di sebelah kiri, pilih Service Mesh > Mesh Management.

  2. Di halaman Mesh Management, klik nama instance ASM. Di panel navigasi di sebelah kiri, pilih Mesh Security Center > OPA Policy.

  3. Di halaman OPA Policy, klik Create, pilih default dari daftar drop-down Namespace, atur Name menjadi bookinfo-opa, lalu klik Add Matching Label. Di bagian Label Pencocokan, atur Name menjadi version dan Value menjadi v1. Salin konten berikut ke editor kode Rego Rule, lalu klik Create.

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

Metode 2: Buat kebijakan OPA menggunakan kubectl

  1. Buat file opa.yaml yang berisi konten berikut:

    Tampilkan file 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 Anda mendefinisikan kebijakan OPA untuk pod, pastikan hanya satu kebijakan OPA yang berisi bidang default allow. Jika beberapa kebijakan OPA berlaku untuk pod dan bidang default allow didefinisikan di setiap kebijakan OPA, kebijakan OPA gagal diperbarui secara dinamis karena adanya beberapa bidang default allow.

    • Kami menyarankan Anda menggunakan label untuk menentukan ruang lingkup efektif kebijakan OPA saat Anda mendefinisikan kebijakan OPA. Kebijakan Rego yang tidak valid membuat layanan tidak dapat diakses.

    • OPA berada di pod yang sama dengan kontainer bisnis dan menggunakan port 15081 dan 9191.

    • Secara default, bidang default allow dalam kebijakan OPA disetel ke false. Jangan atur ulang bidang default allow. Jika tidak, akan terjadi konflik. Tabel berikut menjelaskan beberapa parameter file opa.yaml.

    Parameter

    Deskripsi

    spec

    Konten kebijakan yang ditulis dalam Rego. Untuk informasi lebih lanjut tentang sintaks Rego, lihat Bahasa Kebijakan.

    workloadSelector

    Ruang lingkup efektif kebijakan OPA di namespace tertentu. Secara default, kebijakan OPA berlaku untuk semua pod di namespace. Setelah Anda mengatur parameter ini, kebijakan OPA hanya berlaku untuk pod dengan label tertentu.

    user_roles

    Peran yang ditetapkan kepada pengguna. Dalam contoh ini, peran tamu diberikan kepada pengguna guest1, dan peran admin diberikan kepada pengguna admin1.

    role_perms

    Izin setiap peran. Dalam contoh ini, peran tamu diberikan izin untuk mengakses aplikasi menggunakan URL yang berisi /productpage, dan peran admin diberikan izin untuk mengakses aplikasi menggunakan URL yang berisi /productpage atau /api/v1/products.

  2. Jalankan perintah berikut untuk membuat kebijakan OPA.

    Untuk informasi lebih lanjut tentang cara menggunakan kubectl untuk terhubung ke instance ASM, lihat Gunakan kubectl di bidang kontrol untuk mengakses sumber daya Istio.

    kubectl apply -f opa.yaml

Langkah 3: Suntikkan OPA

Sebarkan aplikasi sampel Bookinfo di instance ASM dan periksa apakah OPA disuntikkan ke setiap pod aplikasi Bookinfo.

  1. Sebarkan aplikasi Bookinfo di instance ASM. Untuk informasi lebih lanjut, lihat Sebarkan aplikasi di instance ASM.

  2. Buat gateway ingress, gateway Istio, dan layanan virtual. Untuk informasi lebih lanjut, lihat Gunakan sumber daya Istio untuk merutekan lalu lintas ke versi layanan yang berbeda.

  3. Periksa apakah OPA disuntikkan ke pod setiap aplikasi dalam aplikasi Bookinfo.

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

    2. Di halaman Clusters, temukan kluster yang diinginkan dan klik namanya. Di panel di sebelah kiri, pilih Workloads > Pods.

    3. Di halaman Pods, pilih default dari daftar drop-down Namespace dan klik nama pod aplikasi yang diinginkan.

      Di tab Container, Anda dapat menemukan bahwa proxy sidecar bernama istio-proxy dan OPA bernama opa-istio disuntikkan ke setiap container. Periksa container setiap aplikasi secara bergantian untuk memastikan bahwa proxy sidecar dan OPA disuntikkan ke setiap container.注入OPA代理

Langkah 4: Verifikasi bahwa kebijakan OPA menerapkan kontrol akses sesuai harapan

  1. Jalankan perintah berikut untuk mengakses aplikasi menggunakan URL yang berisi /productpage:

    curl -X GET http://<Alamat IP gateway ingress>/productpage --user guest1:password -I

    Output yang diharapkan:

    HTTP/1.1 200 OK
  2. Jalankan perintah berikut untuk mengakses aplikasi menggunakan URL yang berisi /api/v1/products:

    curl -X GET http://<Alamat IP gateway ingress>/api/v1/products --user guest1:password -I

    Output yang diharapkan:

    HTTP/1.1 403 Forbidden

    Hasil yang diharapkan menunjukkan bahwa peran tamu diberikan kepada pengguna guest1 dan pengguna guest1 memiliki izin untuk mengakses aplikasi menggunakan URL yang berisi /productpage, tetapi tidak menggunakan URL yang berisi /api/v1/products.

  3. Jalankan perintah berikut untuk mengakses aplikasi menggunakan URL yang berisi /productpage:

    curl -X GET http://{{Alamat IP gateway ingress}}/productpage --user admin1:password -I

    Output yang diharapkan:

    HTTP/1.1 200 OK
  4. Jalankan perintah berikut untuk mengakses aplikasi menggunakan URL yang berisi /api/v1/products:

    curl -X GET http://<Alamat IP gateway ingress>/api/v1/products --user admin1:password -I

    Output yang diharapkan:

    HTTP/1.1 200 OK

    Hasil yang diharapkan menunjukkan bahwa peran admin diberikan kepada pengguna admin1 dan pengguna admin1 memiliki izin untuk mengakses aplikasi menggunakan URL yang berisi /productpage atau /api/v1/products. Hasil sebelumnya menunjukkan bahwa kebijakan OPA yang didefinisikan menerapkan kontrol akses sesuai harapan.

Langkah 5: Perbarui kebijakan OPA secara dinamis

Jalankan perintah berikut untuk masuk ke antarmuka pengeditan kebijakan OPA:

kubectl edit asmopapolicy bookinfo-opa -n default 

Dalam keluaran perintah, edit kebijakan OPA untuk memberikan peran tamu dan admin kepada pengguna 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"},
        ],
    }
  • user_roles: peran yang ditetapkan kepada pengguna. Dalam contoh ini, peran tamu dan admin diberikan kepada pengguna guest1, dan peran admin diberikan kepada pengguna admin1.

  • role_perms: izin setiap peran. Dalam contoh ini, peran tamu diberikan izin untuk mengakses aplikasi menggunakan URL yang berisi /productpage, dan peran admin diberikan izin untuk mengakses aplikasi menggunakan URL yang berisi /productpage atau /api/v1/products.

Langkah 6: Verifikasi bahwa kebijakan OPA diperbarui secara dinamis

  1. Jalankan perintah berikut untuk mengakses aplikasi menggunakan URL yang berisi /productpage:

    curl -X GET http://<Alamat IP gateway ingress>/productpage --user guest1:password -I

    Output yang diharapkan:

    HTTP/1.1 200 OK
  2. Jalankan perintah berikut untuk mengakses aplikasi menggunakan URL yang berisi /api/v1/products:

    curl -X GET http://<Alamat IP gateway ingress>/api/v1/products --user guest1:password -I

    Output yang diharapkan:

    HTTP/1.1 200 OK

    Sebelum kebijakan OPA diperbarui, pengguna guest1 dapat mengakses aplikasi menggunakan URL yang berisi /productpage, tetapi tidak /api/v1/products. Setelah kebijakan OPA diperbarui, pengguna guest1 dapat mengakses aplikasi menggunakan URL yang berisi /productpage atau /api/v1/products. Hasilnya menunjukkan bahwa kebijakan OPA diperbarui secara dinamis.

Skema contoh

Skema 1: Otentikasi permintaan dengan memeriksa JWT

Saat aplikasi menerima permintaan, OPA memeriksa JSON Web Token (JWT) di header permintaan. Permintaan untuk mengakses aplikasi diizinkan hanya jika JWT memenuhi persyaratan tertentu.

Kebijakan OPA berikut mendefinisikan bahwa permintaan untuk mengakses aplikasi Productpage diizinkan hanya jika permintaan menggunakan metode GET dan permintaan berisi JWT di mana bidang Role disetel ke guest dan bidang userGroup disetel ke 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 disetel ke GET.

  • input.parsed_path[0]: aplikasi yang akan diakses.

  • claims.Role: nilai yang diharapkan dari bidang Role dalam JWT. Dalam contoh ini, nilainya disetel ke guest.

  • claims.userGroup: nilai yang diharapkan dari bidang userGroup dalam JWT. Dalam contoh ini, nilainya disetel ke visitor.

Anda dapat menggunakan alat JWT untuk mengkodekan informasi permintaan seperti bidang Role dan userGroup menjadi string JWT.请求授权

Jalankan perintah berikut untuk mengakses aplikasi Productpage:

curl --location --request GET 'http://{Alamat IP gateway ingress}/productpage' \
--header 'Authorization: Bearer 
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiZ3Vlc3QxIiwiUm9sZSI6Imd1ZXN0IiwidXNlckdyb3VwIjoidmlzaXRvciJ9.44OnUFZwOzSWzC7hyVfcle-uYk8byv7q_BBxS10AEWc'

Output yang diharapkan:

200

Kode status 200 dikembalikan, yang menunjukkan bahwa aplikasi Productpage dapat diakses menggunakan permintaan GET yang berisi JWT di mana bidang Role disetel ke guest dan bidang userGroup disetel ke visitor. Jika Anda menggunakan JWT yang tidak valid atau permintaan tidak berisi JWT, kode kesalahan 403 dikembalikan. Ini menunjukkan bahwa permintaan untuk mengakses aplikasi Productpage ditolak.

Skema 2: Otentikasi permintaan dengan memeriksa badan permintaan HTTP dan JWT

Anda dapat menggunakan kebijakan OPA untuk mengizinkan permintaan HTTP hanya jika nilai parameter username dalam badan permintaan sama dengan nilai bidang Role dalam JWT permintaan.

Kebijakan OPA berikut mendefinisikan bahwa permintaan untuk mengakses aplikasi Productpage diizinkan hanya jika permintaan menggunakan metode GET, nilai parameter username dalam badan permintaan sama dengan nilai bidang Role dalam JWT permintaan, dan bidang userGroup dalam JWT disetel ke 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 disetel ke GET.

  • input.parsed_path[0]: aplikasi yang akan diakses.

  • claims.Role: nilai yang diharapkan dari bidang Role dalam JWT. Dalam contoh ini, nilainya disetel ke input.parsed_body.username. Ini menunjukkan bahwa nilai parameter username dalam badan permintaan harus sama dengan nilai bidang Role dalam JWT permintaan.

  • claims.userGroup: nilai yang diharapkan dari bidang userGroup dalam JWT. Dalam contoh ini, nilainya disetel ke manager.

Anda dapat menggunakan alat JWT untuk mengkodekan informasi permintaan seperti bidang Role dan userGroup menjadi string JWT.body

Jalankan perintah berikut untuk mengakses aplikasi Productpage:

curl --location --request GET 'http://{Alamat IP gateway ingress}/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:

200

Kode status 200 dikembalikan, yang menunjukkan bahwa aplikasi Productpage dapat diakses menggunakan permintaan GET yang berisi JWT di mana nilai bidang Role sama dengan nilai parameter username dalam badan permintaan dan bidang userGroup disetel ke manager. Jika Anda menggunakan JWT yang tidak valid atau permintaan tidak berisi JWT, kode kesalahan 403 dikembalikan. Ini menunjukkan bahwa permintaan untuk mengakses aplikasi Productpage ditolak.

Skema 3: Otentikasi permintaan dengan memeriksa lebih banyak informasi konteks

Anda dapat menggunakan kebijakan OPA untuk memeriksa lebih banyak informasi konteks selain informasi yang diperiksa dalam Skema 2. Dalam contoh ini, nilai bidang username dalam JWT harus masuk dalam rentang nilai yang ditentukan oleh bidang bookinfo_managers.

Kebijakan OPA berikut mendefinisikan bahwa permintaan untuk mengakses aplikasi Productpage diizinkan hanya jika permintaan menggunakan metode GET, nilai parameter username dalam badan permintaan sama dengan nilai bidang Role dalam JWT permintaan, nilai bidang username dalam JWT masuk dalam rentang nilai yang ditentukan oleh bidang bookinfo_managers, dan bidang userGroup dalam JWT disetel ke 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 disetel ke GET.

  • input.parsed_path[0]: aplikasi yang akan diakses.

  • claims.Role: nilai yang diharapkan dari bidang Role dalam JWT. Dalam contoh ini, nilainya disetel ke input.parsed_body.username. Ini menunjukkan bahwa nilai parameter username dalam badan permintaan harus sama dengan nilai bidang Role dalam JWT permintaan.

  • claims.userGroup: nilai yang diharapkan dari bidang userGroup dalam JWT. Dalam contoh ini, nilainya disetel ke manager.

  • claims.username: nilai yang diharapkan dari bidang username dalam JWT. Dalam contoh ini, nilainya disetel ke bookinfo_managers[_].name. Ini menunjukkan bahwa nilai bidang username dalam JWT harus masuk dalam rentang nilai yang ditentukan oleh bidang bookinfo_managers.

Anda dapat menggunakan alat JWT untuk mengkodekan informasi permintaan menjadi string JWT.上下文

Jalankan perintah berikut untuk mengakses aplikasi Productpage:

curl --location --request GET 'http://{Alamat IP gateway ingress}/productpage' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9eyJ1c2VybmFtZSI6InVzZXIxIiwiUm9sZSI6ImFkbWluIiwidXNlckdyb3VwIjoibWFuYWdlciJ9.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:

200

Kode status 200 dikembalikan, yang menunjukkan bahwa aplikasi Productpage dapat diakses menggunakan permintaan GET yang berisi JWT di mana nilai bidang Role sama dengan nilai parameter username dalam badan permintaan, nilai bidang username dalam JWT masuk dalam rentang nilai yang ditentukan oleh bidang bookinfo_managers, dan bidang userGroup disetel ke manager. Jika Anda menggunakan JWT yang tidak valid atau permintaan tidak berisi JWT, kode kesalahan 403 dikembalikan. Ini menunjukkan bahwa permintaan untuk mengakses aplikasi Productpage ditolak.

Tanya Jawab Umum

Bagaimana cara memeriksa apakah pod menggunakan kebijakan OPA?

OPA diterapkan dalam mode sidecar di pod yang sama dengan kontainer bisnis. Untuk memeriksa apakah pod menggunakan kebijakan OPA, sambungkan ke pod dan jalankan perintah berikut:

curl 127.0.0.1:15081/v1/policies

Bagaimana cara memeriksa kebijakan yang ditulis dalam Rego?

Situs resmi OPA menyediakan alat online yang dapat Anda gunakan untuk memeriksa kebijakan yang ditulis dalam Rego.

Referensi

Jika Anda ingin menggunakan ConfigMaps untuk mendefinisikan kebijakan OPA, baca topik berikut: