Như ở 1 bài viết mình đã có nhắc đến authentication và authorization cũng với test một vài feature istio trong bài viết bên dưới:
Nếu bạn đang tò mò security của istio có j, thì chúng ta sẽ đi chi tiết.
Security
links: https://istio.io/latest/docs/reference/config/security/
1) Authorization Policy
Configuration for access control on workloads.
The evaluation is determined by the following rules:
- If there are any CUSTOM policies that match the request, evaluate and deny the request if the evaluation result is deny.
- If there are any DENY policies that match the request, deny the request.
- If there are no ALLOW policies for the workload, allow the request.
- If any of the ALLOW policies match the request, allow the request.
- Deny the request.
Giờ chúng ta sẽ kiểm tra bằng các run chạy sem ntn he:
Đầu tiên bạn cần tạo ra 1 namespace và enable auto inject sidecar trên ns đó:
kubectl label namespace default istio-injection=enabled
Ở đó mình chọn là inject ns default.
Mình ví dụ bạn có 2 workload A và B:
và bạn muốn cấu hình những access controls trên workload B với các ví dụ sau đây:
1.1) It sets the action
to “ALLOW” to create an allow policy. The default action is “ALLOW” but it is useful to be explicit in the policy.
Giờ chúng ta deploy app “fleetman-webapp” trong links dưới cung cấp yaml:
https://github.com/mrnim94/recheck-instio/tree/main/authen-author-istio/httpin
Ở bài viết này mình sẽ viết tắt:
vs: VirtualService
gw: Gateway
dr: DestinationRule
tại các bạn thấy mình viết tắt lại đéo hiểu thằng này nó đang nói đến Kind nào hí hí.
1.1.1) Action ALLOW
Với action: ALLOW thì sẽ deny All and chỉ allow cho các đối tượng cụ thể được phép access.
Allows requests from:
– Service account
To access the workload with:
– All methods and All paths
– Specify particular methods(GET/POST/…) – Chỉ định nhưng methods cụ thể
– Specify particular paths(/ip) or prefix(/abc*)
Giờ deploy
– 1 busybox-default – service account cùng ns với workload httpbin
– 1 busybox-sample – service account khác ns với workload httpbin
Giờ cho 2 busybox tấn công con httpbin
Note: để mTLS mode strict có thể hoạt động.
Cấu hình mTLS mode strict apply vào ns default
# cấu hình authen
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
labels:
name: default
namespace: default
spec:
mtls:
mode: STRICT
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
labels:
app.kubernetes.io/instance: author-default-httpbin
name: author-default
namespace: default
spec:
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/default/sa/busybox-sa
to:
- operation:
methods:
- GET
paths:
- /ip
- /status*
Câu hỏi làm sao để chúng ta kiếm được đúng Source Workload of Service account (SA của workload Nguồn)
Tiến hành kiểm tra:
EndUser –> Gw -> Vs -> Svc -> Deployment TOANG
while true; do curl -sS fleetman-webapp.nimtechnology.com/ip; echo; sleep 1; done
EndUser -> port-forward OK
kubectl -n default port-forward deployment.apps/deploy-httpbin 8080:80
while true; do curl -sS localhost:8080/ip; echo; sleep 1; done
Workload Service account (Source):
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ip : OK
trường hợp đúng rule AuthorizationPolicy
– Cùng ns = default, có SA = busybox-sa —> service: GET – fleetman-webapp.nimtechnology.com/ip : Toang
ko có rule liên quan đến istio-gateway
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/status/200 : OK
trường hợp đúng rule AuthorizationPolicy (prefix /status*)
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ : Toang
ko match rule nào cả
– Khác ns = sample, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ip : Toang
ko match rule nào cả
Giờ đổi lại Allow access cho ns sample và SA busybox-sa với file yaml bên dưới:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
labels:
app.kubernetes.io/instance: author-default-httpbin
name: author-default
namespace: default
spec:
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/sample/sa/busybox-sa
to:
- operation:
methods:
- GET
paths:
- /ip
- /status*
– Cùng ns = sample, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ip : OK
Đổi lại cho Đúng là ok thôi
– Các workload ở ns default sẽ toang hết.
Thật ra các workload CI/CD của các công ty đa số phân chia bằng namespace và workload selector
Nhìn source của nó namespace,… nhưng không thấy thông số nói về workload
–> nếu muốn chỉ định workload source thì chỉ có thể dụng Service account
Giờ sửa lại file AuthorizationPolicy chút
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
labels:
app.kubernetes.io/instance: author-default-httpbin
name: author-default
namespace: default
spec:
action: ALLOW
rules:
- from:
- source:
namespaces:
- default
- go-demo-8
principals:
- cluster.local/ns/default/sa/busybox-sa
- source:
namespaces:
- sample
principals:
- cluster.local/ns/sample/sa/busybox-sa
to:
- operation:
methods:
- GET
paths:
- /ip
- /status*
– Chúng ta cho phép tất cả workload trong namespace khác “sample” allow acess
– Chỉ có 1 vài workload cùng ns “default” allow acess
Chúng ta có 1 app mới là với SA mới nhưng ở ns default.
Namspace và Service account (source):
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ip : OK
trường hợp đúng rule AuthorizationPolicy
– Cùng ns = default, có SA = busybox-sa —> service: GET – fleetman-webapp.nimtechnology.com/ip : Toang
ko có rule liên quan đến istio-gateway
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/status/200 : OK
trường hợp đúng rule AuthorizationPolicy (prefix /status*)
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ : Toang
ko match rule nào cả
– Cùng ns = default, có SA = busybox-sa-1 —> service: GET – httpbin.default.svc.cluster.local/ip : Toang
ko match rule nào cả
– Khác ns = sample, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ip : OK
– Cùng ns = sample, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/status/200 : OK
trường hợp đúng rule AuthorizationPolicy (prefix /status*)
Với các config ở trên thì chúng ta mới chỉnh quan tâm đến source (namespace và workload)
Ngoài chúng ta apply author lên toàn namespace thì chúng ta forcus xuống từng workload
với config như dưới “selector->matchLabels”
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: author-default
namespace: default
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/busybox-sa"]
namespaces: ["default","go-demo-8"]
- source:
principals: ["cluster.local/ns/sample/sa/busybox-sa"]
namespaces: ["sample"]
to:
- operation:
methods: ["GET"]
paths: ["/ip","/status*"]
OK giờ mình deploy thêm app mới với domain gw là: http://fleetman-webapp-1.nimtechnology.com/
matchLabels:
– EndUser –> Gw(http://fleetman-webapp.nimtechnology.com) -> Vs -> Svc(httpbin) -> Deployment(app: httpbin) TOANG
ko match rule nào cả
– EndUser –> Gw(http://fleetman-webapp.nimtechnology.com) -> Vs -> Svc(httpbin) -> Deployment(app: httpbin) OK
vì chúng chỉ apply author cho workload app: httpbin
– Cùng ns = default, có SA = busybox-sa —> service(ns: default): GET – httpbin.default.svc.cluster.local/ : Toang
ko match rule nào cả
– Cùng ns = default, có SA = busybox-sa —> service(ns: default): GET – httpbin-1.default.svc.cluster.local/ : OK
chúng chỉ apply author cho workload app: httpbin
Có Điều lưu ý là phần ALLOW với ver 1.9.7 thì nếu ko có selector -> matchLabels nó sẽ không allow, kiểu phải chỉ rõ mày muốn allow cho ai và tao sẽ chặn all
Nếu bạn ko chỉ định rõ workload nào được áp allow và chỉ có namespace thì sẽ như bên dưới.
1.1.2) Action DENY
Với action: DENY thì sẽ allow All and chỉ deny chặn một vài workload cụ thể.
Vẫn bài lab ở trên chúng ta sẽ chuyển action thành deny:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
labels:
app.kubernetes.io/instance: author-default-httpbin
name: author-default
namespace: default
spec:
action: DENY
rules:
- from:
- source:
namespaces:
- default
- go-demo-8
principals:
- cluster.local/ns/default/sa/busybox-sa
- source:
namespaces:
- sample
principals:
- cluster.local/ns/sample/sa/busybox-sa
to:
- operation:
methods:
- GET
paths:
- /ip
- /status*
selector:
matchLabels:
app: httpbin
Namspace và Service account (source):
– EndUser –> Gw(http://fleetman-webapp.nimtechnology.com) -> Vs -> Svc(httpbin) -> Deployment(app: httpbin) OK
– EndUser –> Gw(http://fleetman-webapp.nimtechnology.com) -> Vs -> Svc(httpbin) -> Deployment(app: httpbin) OK
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ip : Toang
– Cùng ns = default, có SA = busybox-sa —> service: GET – fleetman-webapp.nimtechnology.com/ip : OK
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/status/200 : Toang
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ : OK
– Cùng ns = default, có SA = busybox-sa-1 —> service: GET – httpbin.default.svc.cluster.local/ip : OK
– Khác ns = sample, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/ip : Toang
– Cùng ns = sample, có SA = busybox-sa —> service: GET – httpbin.default.svc.cluster.local/status/200 : Toang
– Cùng ns = default, có SA = busybox-sa —> service: GET – httpbin-1.default.svc.cluster.local/ip : OK
1.1.3) Action AUDIT
A request will be internally marked that it should be audited if there is an AUDIT policy on the workload that matches the request. A separate plugin must be configured and enabled to actually fulfill the audit decision and complete the audit behavior. The request will not be audited if there are no such supporting plugins enabled. Currently, the only supported plugin is the Stackdriver plugin.
Mình không có stackdriver nên là ko lab được
1.1.4) Action CUSTOM
Note: The CUSTOM action is currently an experimental feature and is subject to breaking changes in later versions.
Thấy dòng trên là không lab được òi
1.2) Authorization Policy follow nimtechnology ways
1.2.1) Normal
Bạn có thể thấy đa số khi workload A call sang workload B thì dev sẽ call sang domain được cấu hình trên GW istio.
Chúng ta cần sử dụng JWT
Tạo RequestAuthentication apply vào ingressgateway
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: req-authen-ingressgateway-jwt
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
jwtRules:
- issuer: "testing@secure.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.11/security/tools/jwt/samples/jwks.json"
issuer: nó có liên quan đến jwksUri
jwksUri: jwks.json trên github ????
Tạo AuthorizationPolicy
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: author-ingress-gateway-jwt
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["*"]
Ý nghĩ của Author Policy là deny tất cả các request mà ko có header Authorization
Giờ chúng ta thực hiện curl để hiểu hơn:
curl -sS fleetman-webapp.nimtechnology.com/get -v
curl --header "Authorization: Bearer nimtechnology" -sS fleetman-webapp.nimtechnology.com/get -v
TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.11/security/tools/jwt/samples/demo.jwt -s)
curl --header "Authorization: Bearer $TOKEN" -sS fleetman-webapp.nimtechnology.com/get -v
Giờ thử decode jwt sem payload là gìTOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.11/security/tools/jwt/samples/demo.jwt -s)
1.2.2) Per Path
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: author-ingress-gateway-jwt
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["*"]
to:
- operation:
paths: ["/get"]
1.2.3) a JWT access a few hosts
Nhưng các lab ở 2.1 và 2.2 chúng ta thấy là chỉ cần có bearer token JWT thì EndUser có thể truy cập hosts trên Gateway.
Vậy nếu chúng ta muốn là Only User A –> access –> host: fleetman-webapp.nimtechnology.com
Thì chúng ta cần dùng tới khái niệm là: HTTP header Attribute
Khi mà decode bearer token
>>>trong ví dụ này mình sử dụng:
notRequestPrincipals: ["iss/sub"]
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: author-ingress-gateway-jwt-attribute
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
to:
- operation:
paths: ["/get"]
hosts: ["fleetman-webapp.nimtechnology.com"]
Chúng ra sẽ thấy chỉ có:
iss: testing@secure.istio.io
sub: testing@secure.istio.io
–> access vào http://fleetman-webapp.nimtechnology.com/get
curl --header -sS fleetman-webapp.nimtechnology.com/get -v
TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.11/security/tools/jwt/samples/demo.jwt -s)
curl --header "Authorization: Bearer $TOKEN" \
--header "x-token: test" \
-sS fleetman-webapp.nimtechnology.com/get -v
TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.11/security/tools/jwt/samples/demo.jwt -s)
>>>Đưa token tào lao dô
curl --header "Authorization: Bearer nimtechnology" \
-sS fleetman-webapp.nimtechnology.com/get -v
Hiện tại mình apply author trên paths /get
Bạn curl fleetman-webapp.nimtechnology.com hay fleetman-webapp.nimtechnology.com/ip đều được nhé
links tham khảo siêu hay mới tìm được:
https://istiobyexample.dev/jwt/
1.2.4) HTTP header Attribute
Bạn thực hiện thêm và check các header trong phần AuthorizationPolicy
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: author-ingress-gateway-attribute
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY
rules:
- to:
- operation:
paths: ["/get"]
hosts: ["fleetman-webapp.nimtechnology.com"]
when:
- key: request.headers[x-token]
notValues: ["admin"]
curl --header -sS fleetman-webapp.nimtechnology.com/get -v
curl --header "x-token: admin" \
-sS fleetman-webapp.nimtechnology.com/get -v
Nếu bạn muốn tăng độ khó cho game thì có thể sài mix 2.3 và 2.4
1.2.5) Source IP
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: author-ingress-gateway-jwt-attribute
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY
rules:
- from:
- source:
ipBlocks: ["$CLIENT_IP"]
Cái này block IP
Links các file yaml
https://github.com/mrnim94/recheck-instio/tree/main/authen-author-istio