Alibaba Cloud Service Mesh (ASM) menangani otentikasi JWT melalui dua resource Istio yang bekerja bersama:
-
RequestAuthentication mendefinisikan cara token divalidasi—issuer dan kunci penandatanganan mana yang dipercaya. Resource ini menolak permintaan yang membawa token tidak valid, tetapi mengizinkan permintaan yang sama sekali tidak membawa token.
-
AuthorizationPolicy memberlakukan keputusan akses—apakah akan mengizinkan atau menolak permintaan berdasarkan keberadaan token, klaim (claims), atau path permintaan.
RequestAuthentication saja tidak memblokir permintaan tanpa autentikasi. Untuk mewajibkan penggunaan token, pasangkan dengan AuthorizationPolicy.
Algoritma JWT apa saja yang didukung oleh ASM?
Algoritma yang didukung bergantung pada versi instans ASM Anda:
-
Sebelum v1.13: Hanya RSA
-
v1.13 dan seterusnya: Semua algoritma standar yang tercantum di bawah ini
| Family algoritma | Algoritma yang didukung |
|---|---|
| RSA | RS256, RS384, RS512 |
| RSA-PSS | PS256, PS384, PS512 |
| ECDSA | ES256, ES384, ES512 |
| HMAC | HS256, HS384, HS512 |
| Edwards-curve | EdDSA |
Bagaimana cara menggunakan parameter jwksUri?
Catatan: jwksUri memerlukan ASM v1.13 atau yang lebih baru.
Bidang jwksUri dalam resource RequestAuthentication memberi tahu ASM tempat mengambil kunci publik yang digunakan untuk memverifikasi JWT. Cara Anda mengonfigurasinya bergantung pada lokasi hosting endpoint JSON Web Key Set (JWKS):
-
Di dalam kluster terkelola — Arahkan
jwksUrilangsung ke alamat layanan dalam kluster. -
Di luar kluster terkelola — Buat ServiceEntry terlebih dahulu agar ASM dapat mengakses endpoint eksternal tersebut.
Contoh berikut menggunakan JWT contoh dan JWKS contoh dari proyek Istio.
Endpoint JWKS di dalam kluster terkelola
Pada contoh ini, layanan nginx-proxy di kluster Container Service for Kubernetes (ACK) menyediakan JWKS di /get_jwks pada Port 80. jwksUri lengkapnya adalah http://nginx-proxy.{Namespace}.svc.cluster.local:80/get_jwks.
-
Verifikasi bahwa endpoint JWKS dapat dijangkau:
curl nginx-proxy/get_jwksOutput yang diharapkan:
{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-e****","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65p****-P7KfIupjf59vsdo91bSP9C8H07pSAGQ****_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5****_pbhLdKXbi66GlVeK6ABZOUW3WYt****-91gVuoeJT_DwtGGcp4ignkgXfkiE****-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoU****_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZ****_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqT****_EyxOGuHJrLsn00****"}]}Jika kumpulan kunci JSON yang valid dikembalikan, berarti endpoint tersebut berfungsi.
-
Buat resource RequestAuthentication di Konsol ASM.
-
Masuk ke Konsol ASM.
-
Di panel navigasi sebelah kiri, pilih Service Mesh > Mesh Management.
-
Pada halaman Mesh Management, temukan instans ASM target. Klik nama instans atau klik Manage di kolom Actions.
-
Di panel navigasi sebelah kiri, pilih Mesh Security Center > RequestAuthentication.
-
Pada halaman RequestAuthentication, klik Create from YAML. Pilih Namespace dan Template, tempel YAML berikut, lalu klik Create.
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: foo spec: jwtRules: - issuer: testing@secure.istio.io jwksUri: 'http://nginx-proxy/get_jwks' selector: matchLabels: app: httpbin
-
-
Uji konfigurasi dengan mengirim permintaan yang menyertakan JWT dari Pod
sleepke layananhttpbin:# Ambil dan dekode JWT contoh TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.14/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - # Kirim permintaan dengan JWT kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" \ -c sleep -n foo -- \ curl "http://httpbin.foo:8000/headers" -sS -o /dev/null \ -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"Kode status
200mengonfirmasi bahwa otentikasi JWT berfungsi.
Endpoint JWKS di luar kluster terkelola
Ketika endpoint JWKS di-hosting di luar kluster ACK yang dikelola oleh ASM, buat ServiceEntry agar mesh dapat mengaksesnya. Contoh ini menggunakan HTTP. Untuk HTTPS, tambahkan DestinationRule seperti yang ditunjukkan pada langkah opsional.
-
Buat ServiceEntry untuk endpoint JWKS eksternal.
-
Buat file bernama service-entry.yaml:
apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: external-svc-https namespace: foo spec: addresses: - 11.11.XX.XX # Ganti dengan alamat IP endpoint JWKS Anda. endpoints: - address: 11.11.XX.XX # Ganti dengan alamat IP endpoint JWKS Anda. hosts: - 11.11.XX.XX # Ganti dengan alamat IP endpoint JWKS Anda. location: MESH_EXTERNAL ports: - name: http number: 80 protocol: HTTP - name: https number: 443 protocol: HTTPS resolution: STATIC -
Terapkan ServiceEntry:
kubectl apply -f service-entry.yaml
-
-
(Opsional) Untuk mengambil JWKS melalui HTTPS, buat DestinationRule yang mengaktifkan TLS:
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: external-svc-https namespace: foo spec: host: ${The host where ServiceEntry resides} trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: SIMPLE -
Buat resource RequestAuthentication.
-
Masuk ke Konsol ASM.
-
Di panel navigasi sebelah kiri, pilih Service Mesh > Mesh Management.
-
Pada halaman Mesh Management, temukan instans ASM target. Klik nama instans atau klik Manage di kolom Actions.
-
Di panel navigasi sebelah kiri, pilih Mesh Security Center > RequestAuthentication.
-
Pada halaman RequestAuthentication, klik Create from YAML. Pilih Namespace dan Template, tempel YAML berikut, lalu klik Create.
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: foo spec: jwtRules: - issuer: tes****@secure.istio.io jwksUri: '${Your jwksUri}' selector: matchLabels: app: httpbin
-
-
Uji konfigurasi:
# Kirim permintaan dengan JWT dari Pod sleep ke httpbin kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" \ -c sleep -n foo -- \ curl "http://httpbin.foo:8000/headers" -sS -o /dev/null \ -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"Kode status
200mengonfirmasi bahwa otentikasi JWT berfungsi.
Bagaimana cara melewati otentikasi JWT untuk path tertentu?
Gabungkan resource RequestAuthentication dengan AuthorizationPolicy yang menggunakan action: DENY dan notPaths. RequestAuthentication memvalidasi token pada gerbang masuk (ingress gateway), sedangkan AuthorizationPolicy menolak permintaan tanpa autentikasi ke semua path kecuali yang Anda kecualikan.
Contoh berikut mengecualikan /productpage dari otentikasi JWT, sementara JWT yang valid tetap diwajibkan untuk /api/v1/products/0 dan /api/v1/products/1.
-
Deploy aplikasi contoh Bookinfo dan verifikasi akses.
Deploy aplikasi Bookinfo di kluster ACK yang telah ditambahkan ke instans ASM. Untuk informasi selengkapnya, lihat Deploy aplikasi di kluster ACK yang ditambahkan ke instans ASM.
Verifikasi bahwa semua path dapat diakses:
curl "http://<ingress-gateway-ip>/productpage" -sS -o /dev/null -w "%{http_code}\n" curl "http://<ingress-gateway-ip>/api/v1/products/0" -sS -o /dev/null -w "%{http_code}\n" curl "http://<ingress-gateway-ip>/api/v1/products/1" -sS -o /dev/null -w "%{http_code}\n"Setiap perintah harus mengembalikan
200. -
Buat resource RequestAuthentication yang berlaku untuk gerbang masuk (ingress gateway).
-
Masuk ke Konsol ASM.
-
Di panel navigasi sebelah kiri, pilih Service Mesh > Mesh Management.
-
Pada halaman Mesh Management, temukan instans ASM target. Klik nama instans atau klik Manage di kolom Actions.
-
Di panel navigasi sebelah kiri, pilih Mesh Security Center > RequestAuthentication.
-
Pada halaman RequestAuthentication, klik Create from YAML. Pilih Namespace dan Template, tempel YAML berikut, lalu klik Create.
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: istio-system spec: jwtRules: - issuer: testing@secure.istio.io jwks: >- { "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-e****","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQ****_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5****_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVu****_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoU****_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZ****_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqT****_EyxOGuHJrLsn00****"}]} selector: matchLabels: app: istio-ingressgateway
RequestAuthentication ini berlaku untuk ingress gateway. Resource ini memvalidasi tanda tangan JWT tetapi tidak memblokir permintaan tanpa token—tugas tersebut menjadi tanggung jawab AuthorizationPolicy.
-
-
Buat AuthorizationPolicy yang mewajibkan JWT pada semua path kecuali
/productpage.-
Masuk ke Konsol ASM.
-
Di panel navigasi sebelah kiri, pilih Service Mesh > Mesh Management.
-
Pada halaman Mesh Management, temukan instans ASM target. Klik nama instans atau klik Manage di kolom Actions.
-
Di panel navigasi sebelah kiri, pilih Mesh Security Center > AuthorizationPolicy.
-
Pada halaman AuthorizationPolicy, klik Create from YAML. Pilih Namespace dan Template, tempel YAML berikut, lalu klik Create.
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: test-exclude namespace: istio-system spec: action: DENY rules: - from: - source: notRequestPrincipals: - '*' to: - operation: notPaths: - /productpage selector: matchLabels: app: istio-ingressgateway
Cara kerja kebijakan ini: Aturan DENY menargetkan permintaan yang memenuhi kedua kondisi berikut: (1) permintaan tidak memiliki identitas JWT yang valid (
notRequestPrincipals: ['*']), dan (2) permintaan ditujukan ke path apa pun kecuali/productpage(notPaths: [/productpage]). Akibatnya, permintaan tanpa autentikasi ke/productpagedilewatkan, sedangkan permintaan tanpa autentikasi ke semua path lainnya ditolak dengan kode status403. -
-
Verifikasi konfigurasi.
Tetapkan JWT contoh sebagai variabel lingkungan:
export TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1****.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5p****.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9****-LS9qd_vpdLG4Tn1A15NxfCjp5f7Q****-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZz****__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCg****_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvH****_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8****Uji permintaan tanpa JWT:
curl "http://<ingress-gateway-ip>/productpage" -sS -o /dev/null -w "%{http_code}\n" # Diharapkan: 200 (path yang dikecualikan) curl "http://<ingress-gateway-ip>/api/v1/products/0" -sS -o /dev/null -w "%{http_code}\n" # Diharapkan: 403 (tidak ada JWT, akses ditolak) curl "http://<ingress-gateway-ip>/api/v1/products/1" -sS -o /dev/null -w "%{http_code}\n" # Diharapkan: 403 (tidak ada JWT, akses ditolak)Uji permintaan dengan JWT yang valid:
curl "http://<ingress-gateway-ip>/productpage" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null -w "%{http_code}\n" # Diharapkan: 200 curl "http://<ingress-gateway-ip>/api/v1/products/0" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null -w "%{http_code}\n" # Diharapkan: 200 curl "http://<ingress-gateway-ip>/api/v1/products/1" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null -w "%{http_code}\n" # Diharapkan: 200Path Tanpa JWT Dengan JWT yang valid /productpage200(dikecualikan)200/api/v1/products/0403(ditolak)200/api/v1/products/1403(ditolak)200