Firewall pada istio
Jika kita bermain dengan arsitektur microservice, harusnya kita sudah tahu apa itu istio. Istio merupakan sebuah open-source service mesh yang bisa digunakan di kubernetes.
Disini kita mencoba membuat firewall pada istio yang nantinya app hanya bisa diakses dari IP public tertentu saja. Kita bisa menggunakan kind: AuthorizationPolicy milik istio untuk membuat firewallnya.
Namun sebelum kesana, berikut arsitektur kubernetes yang saya gunakan:
Penjelasan:
- Disini saya menggunakan ALB (Application Load Balancer) untuk menerima traffic dari external (internet)
- Kemudian traffic diteruskan ke istio-ingressgateway (internal), dimana saya install dalam bentuk nodeport (buka loadbalancer)
- Pada nodeport istio ini kita akan tambahkan firewall AuthorizationPolicy agar hanya IP public tertentu saja yang bisa mengakses app dibelakangnya (service -> pod).
Karena ada 2 proxy (AWS ALB & Istio-ingressgateway) maka kita harus set numTrustedProxies pada istiooperator dulu sebelum menggunakan AuthorizationPolicy.
Prerequisite
Berikut spesifikasi yang saya gunakan:
- EKS dengan versi kubernetes 1.24
- Istio dengan versi 1.17.1
- Setingan svc istio-ingressgateway saya adalah externalTrafficPolicy: Cluster
Istio Operator
Pertama kita set dulu numTrustedProxies nya.
Anggaplah disini kita sudah install istionya, jadi kita tinggal patch saja konfigurasi istionya dengan istio operator.
Buat sebuah file dengan nama operator.yaml, lalu isikan konfigurasi berikut:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
defaultConfig:
gatewayTopology:
numTrustedProxies: 1
numTrustedProxies nya kita set 1 (bukan 2), kenapa? karena kita mau ambil real IP public nya, bukan IP privatenya. Nantinya IP publicnya akan dicek di AuthorizationPolicy apakah match? Jika match, maka request bisa diteruskan ke app, jika tidak maka akan di denied requestnya.
Kemudian kita patch konfigurasi istionya dengan command berikut (saya menggunakan istioctl):
$ cd istio-1.17.1/bin
$ ./istioctl install --set profile=default --set values.gateways.istio-ingressgateway.type=NodePort -f ../_ownconfig/operator.yaml
Note: Pastikan disini kalian setup istionya menggunakan nodeport, karena jika tidak kemungkinan konfigurasinya tidak akan bekerja.
Kita cek config pada istio seharusnya sudah ada numTrustedProxies
$ kubectl edit configmap istio -n istio-system
numTrustedProxies sudah terset 1.
Selanjutnya kita harus merestart pod istio-ingressgateway:
$ kubectl get deploy -n istio-system
$ kubectl rollout restart deployment istio-ingressgateway -n istio-system
$ kubectl get pods -n istio-system
Cek IP Public, apakah sudah terdeteksi dengan benar di pod?
Selanjutnya kita cek dulu apakah IP Publicnya sudah terbaca dengan benar jika kita get dari pod.
Disini saya menggunakan fungi getallheaders()
pada bahasa PHP.
Bisa dilihat, x-forwarded-for ada 2 IP (54.xxx, dan 172.31.xxx) dimana 54.xxx adalah IP Public dan 172.31.xx adalah IP private. Bagus, IP public sudah terbaca disini. Seharusnya pada x-envoy-external-address juga berisi IP Public 54.xxx.xxx.xxx (karena kita sudah set numTrustedProxies: 1)
AuthorizationPolicy
Buat file dengan nama test-whitelist-ip.yaml, isikan script berikut:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: istio-firewall-prometheus
namespace: istio-system
spec:
selector:
matchLabels:
app: istio-ingressgateway
action: ALLOW
rules:
- from:
- source:
remoteIpBlocks:
- 54.211.222.333
$ kubectl apply -f test-whitelist-ip.yaml
Kita bisa cek authorizationPolicy sudah terbuat di EKS dengan:
$ kubectl get authorizationpolicy -n istio-system
Test Firewall
Sekarang kita test, jika diakses dari selain IP public 54.211.222.333 seharusnya responsenya adalah RBAC: access denied
Mantap!