Post

Istio 5주차 정리

☸️ k8s(1.23.17) 배포 : NodePort(30000 HTTP, 30005 HTTPS)

1. 소스 코드 다운로드

1
2
3
4
5
6
git clone https://github.com/AcornPublishing/istio-in-action
cd istio-in-action/book-source-code-master
pwd # 각자 자신의 pwd 경로

# 결과
/home/devshin/workspace/istio/istio-in-action/book-source-code-master

2. Kind 클러스터 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
kind create cluster --name myk8s --image kindest/node:v1.23.17 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000 # Sample Application (istio-ingrssgateway) HTTP
    hostPort: 30000
  - containerPort: 30001 # Prometheus
    hostPort: 30001
  - containerPort: 30002 # Grafana
    hostPort: 30002
  - containerPort: 30003 # Kiali
    hostPort: 30003
  - containerPort: 30004 # Tracing
    hostPort: 30004
  - containerPort: 30005 # Sample Application (istio-ingrssgateway) HTTPS
    hostPort: 30005
  - containerPort: 30006 # TCP Route
    hostPort: 30006
  - containerPort: 30007 # kube-ops-view
    hostPort: 30007
  extraMounts: # 해당 부분 생략 가능
  - hostPath: /home/devshin/workspace/istio/istio-in-action/book-source-code-master # 각자 자신의 pwd 경로로 설정
    containerPath: /istiobook
networking:
  podSubnet: 10.10.0.0/16
  serviceSubnet: 10.200.1.0/24
EOF

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
Creating cluster "myk8s" ...
 ✓ Ensuring node image (kindest/node:v1.23.17) 🖼
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-myk8s"
You can now use your cluster with:

kubectl cluster-info --context kind-myk8s

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/

3. 클러스터 생성 확인

1
docker ps

✅ 출력

1
2
CONTAINER ID   IMAGE                   COMMAND                  CREATED              STATUS              PORTS                                                             NAMES
92fd38a0b2ec   kindest/node:v1.23.17   "/usr/local/bin/entr…"   About a minute ago   Up About a minute   0.0.0.0:30000-30007->30000-30007/tcp, 127.0.0.1:34207->6443/tcp   myk8s-control-plane

4. 노드에 기본 툴 설치

1
docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree psmisc lsof wget bridge-utils net-tools dnsutils tcpdump ngrep iputils-ping git vim -y'

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
Setting up bind9-libs:amd64 (1:9.18.33-1~deb12u2) ...
Setting up openssh-client (1:9.2p1-2+deb12u5) ...
Setting up libxext6:amd64 (2:1.3.4-1+b1) ...
Setting up dbus-daemon (1.14.10-1~deb12u1) ...
Setting up libnet1:amd64 (1.1.6+dfsg-3.2) ...
Setting up libpcap0.8:amd64 (1.10.3-1) ...
Setting up dbus (1.14.10-1~deb12u1) ...
invoke-rc.d: policy-rc.d denied execution of start.
/usr/sbin/policy-rc.d returned 101, not running 'start dbus.service'
Setting up libgdbm-compat4:amd64 (1.23-3) ...
Setting up xauth (1:1.1.2-1) ...
Setting up bind9-host (1:9.18.33-1~deb12u2) ...
Setting up libperl5.36:amd64 (5.36.0-7+deb12u2) ...
Setting up tcpdump (4.99.3-1) ...
Setting up ngrep (1.47+ds1-5+b1) ...
Setting up perl (5.36.0-7+deb12u2) ...
Setting up bind9-dnsutils (1:9.18.33-1~deb12u2) ...
Setting up dnsutils (1:9.18.33-1~deb12u2) ...
Setting up liberror-perl (0.17029-2) ...
Setting up git (1:2.39.5-0+deb12u2) ...
Processing triggers for libc-bin (2.36-9+deb12u4) ...

🛡️ Istio 1.17.8 설치

1. myk8s-control-plane 진입

1
2
docker exec -it myk8s-control-plane bash
root@myk8s-control-plane:/# 

2. (옵션) 코드 파일 마운트 확인

1
root@myk8s-control-plane:/# tree /istiobook/ -L 1

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/istiobook/
|-- 2025-04-27-190930_1_roundrobin.json
|-- 2025-04-27-191213_2_roundrobin.json
|-- 2025-04-27-191803_3_random.json
|-- 2025-04-27-220131_4_random.json
|-- 2025-04-27-221302_5_least_conn.json
|-- README.md
|-- appendices
|-- bin
|-- ch10
|-- ch11
|-- ch12
|-- ch13
|-- ch14
|-- ch2
|-- ch3
|-- ch4
|-- ch5
|-- ch6
|-- ch7
|-- ch8
|-- ch9
|-- forum-2.json
|-- prom-values-2.yaml
|-- services
`-- webapp-routes.json

3. istioctl 설치

1
2
3
4
5
6
root@myk8s-control-plane:/# export ISTIOV=1.17.8
echo 'export ISTIOV=1.17.8' >> /root/.bashrc

curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
istioctl version --remote=false

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Downloading istio-1.17.8 from https://github.com/istio/istio/releases/download/1.17.8/istio-1.17.8-linux-amd64.tar.gz ...

Istio 1.17.8 download complete!

The Istio release archive has been downloaded to the istio-1.17.8 directory.

To configure the istioctl client tool for your workstation,
add the /istio-1.17.8/bin directory to your environment path variable with:
	export PATH="$PATH:/istio-1.17.8/bin"

Begin the Istio pre-installation check by running:
	istioctl x precheck 

Try Istio in ambient mode
	https://istio.io/latest/docs/ambient/getting-started/
Try Istio in sidecar mode
	https://istio.io/latest/docs/setup/getting-started/
Install guides for ambient mode
	https://istio.io/latest/docs/ambient/install/
Install guides for sidecar mode
	https://istio.io/latest/docs/setup/install/

Need more information? Visit https://istio.io/latest/docs/ 
1.17.8

4. demo 프로파일로 Istio 컨트롤 플레인 배포

디버깅 레벨 높아짐

1
root@myk8s-control-plane:/# istioctl install --set profile=demo --set values.global.proxy.privileged=true -y

✅ 출력

1
2
3
4
5
6
7
✔ Istio core installed                                                                                                                            
✔ Istiod installed                                                                                                                                
✔ Ingress gateways installed                                                                                                                      
✔ Egress gateways installed                                                                                                                       
✔ Installation complete                                                                                                                           Making this installation the default for injection and validation.

Thank you for installing Istio 1.17.  Please take a few minutes to tell us about your install/upgrade experience!  https://forms.gle/hMHGiwZHPU7UQRWe9

5. 보조 도구 설치

1
root@myk8s-control-plane:/# kubectl apply -f istio-$ISTIOV/samples/addons

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
serviceaccount/grafana created
configmap/grafana created
service/grafana created
deployment.apps/grafana created
configmap/istio-grafana-dashboards created
configmap/istio-services-grafana-dashboards created
deployment.apps/jaeger created
service/tracing created
service/zipkin created
service/jaeger-collector created
serviceaccount/kiali created
configmap/kiali created
clusterrole.rbac.authorization.k8s.io/kiali-viewer created
clusterrole.rbac.authorization.k8s.io/kiali created
clusterrolebinding.rbac.authorization.k8s.io/kiali created
role.rbac.authorization.k8s.io/kiali-controlplane created
rolebinding.rbac.authorization.k8s.io/kiali-controlplane created
service/kiali created
deployment.apps/kiali created
serviceaccount/prometheus created
configmap/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
service/prometheus created
deployment.apps/prometheus created

6. 컨트롤 플레인 컨테이너에서 빠져나오기

1
2
root@myk8s-control-plane:/# exit
exit

7. 설치 리소스 확인

(1) Istio 시스템 네임스페이스의 모든 리소스 조회

1
kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
NAME                                        READY   STATUS    RESTARTS   AGE
pod/grafana-b854c6c8-q8d85                  1/1     Running   0          61s
pod/istio-egressgateway-85df6b84b7-fvmpz    1/1     Running   0          2m10s
pod/istio-ingressgateway-6bb8fb6549-dq7gl   1/1     Running   0          2m10s
pod/istiod-8d74787f-5cxpq                   1/1     Running   0          2m23s
pod/jaeger-5556cd8fcf-vrvvd                 1/1     Running   0          61s
pod/kiali-648847c8c4-6rj4t                  0/1     Running   0          60s
pod/prometheus-7b8b9dd44c-jn9sl             2/2     Running   0          60s

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                                                      AGE
service/grafana                ClusterIP      10.200.1.181   <none>        3000/TCP                                                                     61s
service/istio-egressgateway    ClusterIP      10.200.1.84    <none>        80/TCP,443/TCP                                                               2m10s
service/istio-ingressgateway   LoadBalancer   10.200.1.112   <pending>     15021:32369/TCP,80:31229/TCP,443:30393/TCP,31400:31152/TCP,15443:31075/TCP   2m10s
service/istiod                 ClusterIP      10.200.1.229   <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP                                        2m23s
service/jaeger-collector       ClusterIP      10.200.1.23    <none>        14268/TCP,14250/TCP,9411/TCP                                                 61s
service/kiali                  ClusterIP      10.200.1.33    <none>        20001/TCP,9090/TCP                                                           60s
service/prometheus             ClusterIP      10.200.1.153   <none>        9090/TCP                                                                     60s
service/tracing                ClusterIP      10.200.1.94    <none>        80/TCP,16685/TCP                                                             61s
service/zipkin                 ClusterIP      10.200.1.206   <none>        9411/TCP                                                                     61s

NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/grafana                1/1     1            1           61s
deployment.apps/istio-egressgateway    1/1     1            1           2m11s
deployment.apps/istio-ingressgateway   1/1     1            1           2m11s
deployment.apps/istiod                 1/1     1            1           2m23s
deployment.apps/jaeger                 1/1     1            1           61s
deployment.apps/kiali                  0/1     1            0           60s
deployment.apps/prometheus             1/1     1            1           60s

NAME                                              DESIRED   CURRENT   READY   AGE
replicaset.apps/grafana-b854c6c8                  1         1         1       61s
replicaset.apps/istio-egressgateway-85df6b84b7    1         1         1       2m10s
replicaset.apps/istio-ingressgateway-6bb8fb6549   1         1         1       2m11s
replicaset.apps/istiod-8d74787f                   1         1         1       2m23s
replicaset.apps/jaeger-5556cd8fcf                 1         1         1       61s
replicaset.apps/kiali-648847c8c4                  1         1         0       60s
replicaset.apps/prometheus-7b8b9dd44c             1         1         1       60s

NAME                             ENDPOINTS                                                     AGE
endpoints/grafana                10.10.0.8:3000                                                61s
endpoints/istio-egressgateway    10.10.0.7:8080,10.10.0.7:8443                                 2m10s
endpoints/istio-ingressgateway   10.10.0.6:15443,10.10.0.6:15021,10.10.0.6:31400 + 2 more...   2m10s
endpoints/istiod                 10.10.0.5:15012,10.10.0.5:15010,10.10.0.5:15017 + 1 more...   2m23s
endpoints/jaeger-collector       10.10.0.9:9411,10.10.0.9:14250,10.10.0.9:14268                61s
endpoints/kiali                                                                                60s
endpoints/prometheus             10.10.0.10:9090                                               60s
endpoints/tracing                10.10.0.9:16685,10.10.0.9:16686                               61s
endpoints/zipkin                 10.10.0.9:9411                                                61s

NAME                                                  SECRETS   AGE
serviceaccount/default                                1         2m24s
serviceaccount/grafana                                1         61s
serviceaccount/istio-egressgateway-service-account    1         2m11s
serviceaccount/istio-ingressgateway-service-account   1         2m11s
serviceaccount/istio-reader-service-account           1         2m23s
serviceaccount/istiod                                 1         2m23s
serviceaccount/istiod-service-account                 1         2m23s
serviceaccount/kiali                                  1         61s
serviceaccount/prometheus                             1         60s

NAME                                            DATA   AGE
configmap/grafana                               4      61s
configmap/istio                                 2      2m23s
configmap/istio-ca-root-cert                    1      2m12s
configmap/istio-gateway-deployment-leader       0      2m12s
configmap/istio-gateway-status-leader           0      2m12s
configmap/istio-grafana-dashboards              2      61s
configmap/istio-leader                          0      2m12s
configmap/istio-namespace-controller-election   0      2m12s
configmap/istio-services-grafana-dashboards     4      61s
configmap/istio-sidecar-injector                2      2m23s
configmap/kiali                                 1      61s
configmap/kube-root-ca.crt                      1      2m24s
configmap/prometheus                            5      60s

NAME                                                      TYPE                                  DATA   AGE
secret/default-token-4lgs9                                kubernetes.io/service-account-token   3      2m24s
secret/grafana-token-rx72f                                kubernetes.io/service-account-token   3      61s
secret/istio-ca-secret                                    istio.io/ca-root                      5      2m12s
secret/istio-egressgateway-service-account-token-qccxb    kubernetes.io/service-account-token   3      2m11s
secret/istio-ingressgateway-service-account-token-p8d86   kubernetes.io/service-account-token   3      2m11s
secret/istio-reader-service-account-token-m8dqz           kubernetes.io/service-account-token   3      2m23s
secret/istiod-service-account-token-s8bd5                 kubernetes.io/service-account-token   3      2m23s
secret/istiod-token-7jxvs                                 kubernetes.io/service-account-token   3      2m23s
secret/kiali-token-58q7t                                  kubernetes.io/service-account-token   3      61s
secret/prometheus-token-9n666                             kubernetes.io/service-account-token   3      60s

NAME                                              MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
poddisruptionbudget.policy/istio-egressgateway    1               N/A               0                     2m10s
poddisruptionbudget.policy/istio-ingressgateway   1               N/A               0                     2m10s
poddisruptionbudget.policy/istiod                 1               N/A               0                     2m23s

(2) Istio 관련 CRD 목록 조회

1
kubectl get crd | grep istio.io | sort

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
authorizationpolicies.security.istio.io    2025-05-10T02:12:25Z
destinationrules.networking.istio.io       2025-05-10T02:12:25Z
envoyfilters.networking.istio.io           2025-05-10T02:12:25Z
gateways.networking.istio.io               2025-05-10T02:12:25Z
istiooperators.install.istio.io            2025-05-10T02:12:25Z
peerauthentications.security.istio.io      2025-05-10T02:12:25Z
proxyconfigs.networking.istio.io           2025-05-10T02:12:25Z
requestauthentications.security.istio.io   2025-05-10T02:12:25Z
serviceentries.networking.istio.io         2025-05-10T02:12:25Z
sidecars.networking.istio.io               2025-05-10T02:12:25Z
telemetries.telemetry.istio.io             2025-05-10T02:12:25Z
virtualservices.networking.istio.io        2025-05-10T02:12:25Z
wasmplugins.extensions.istio.io            2025-05-10T02:12:26Z
workloadentries.networking.istio.io        2025-05-10T02:12:26Z
workloadgroups.networking.istio.io         2025-05-10T02:12:26Z

8. 실습을 위한 네임스페이스 설정

1
2
3
kubectl create ns istioinaction
kubectl label namespace istioinaction istio-injection=enabled
kubectl get ns --show-labels

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
namespace/istioinaction created

namespace/istioinaction labeled

NAME                 STATUS   AGE     LABELS
default              Active   10m     kubernetes.io/metadata.name=default
istio-system         Active   3m49s   kubernetes.io/metadata.name=istio-system
istioinaction        Active   0s      istio-injection=enabled,kubernetes.io/metadata.name=istioinaction
kube-node-lease      Active   10m     kubernetes.io/metadata.name=kube-node-lease
kube-public          Active   10m     kubernetes.io/metadata.name=kube-public
kube-system          Active   10m     kubernetes.io/metadata.name=kube-system
local-path-storage   Active   10m     kubernetes.io/metadata.name=local-path-storage

9. istio-ingressgateway NodePort 및 트래픽 정책 수정

1
2
3
4
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 8080, "nodePort": 30000}]}}'
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 443, "targetPort": 8443, "nodePort": 30005}]}}'
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'
kubectl describe svc -n istio-system istio-ingressgateway

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
service/istio-ingressgateway patched
service/istio-ingressgateway patched
service/istio-ingressgateway patched

Name:                     istio-ingressgateway
Namespace:                istio-system
Labels:                   app=istio-ingressgateway
                          install.operator.istio.io/owning-resource=unknown
                          install.operator.istio.io/owning-resource-namespace=istio-system
                          istio=ingressgateway
                          istio.io/rev=default
                          operator.istio.io/component=IngressGateways
                          operator.istio.io/managed=Reconcile
                          operator.istio.io/version=1.17.8
                          release=istio
Annotations:              <none>
Selector:                 app=istio-ingressgateway,istio=ingressgateway
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.200.1.112
IPs:                      10.200.1.112
Port:                     status-port  15021/TCP
TargetPort:               15021/TCP
NodePort:                 status-port  32369/TCP
Endpoints:                10.10.0.6:15021
Port:                     http2  80/TCP
TargetPort:               8080/TCP
NodePort:                 http2  30000/TCP
Endpoints:                10.10.0.6:8080
Port:                     https  443/TCP
TargetPort:               8443/TCP
NodePort:                 https  30005/TCP
Endpoints:                10.10.0.6:8443
Port:                     tcp  31400/TCP
TargetPort:               31400/TCP
NodePort:                 tcp  31152/TCP
Endpoints:                10.10.0.6:31400
Port:                     tls  15443/TCP
TargetPort:               15443/TCP
NodePort:                 tls  31075/TCP
Endpoints:                10.10.0.6:15443
Session Affinity:         None
External Traffic Policy:  Local
Internal Traffic Policy:  Cluster
Events:
  Type    Reason  Age   From                Message
  ----    ------  ----  ----                -------
  Normal  Type    0s    service-controller  LoadBalancer -> NodePort

10. Istio 관측 도구 - NodePort 서비스 포트 일괄 수정

1
2
3
4
kubectl patch svc -n istio-system prometheus -p '{"spec": {"type": "NodePort", "ports": [{"port": 9090, "targetPort": 9090, "nodePort": 30001}]}}'
kubectl patch svc -n istio-system grafana -p '{"spec": {"type": "NodePort", "ports": [{"port": 3000, "targetPort": 3000, "nodePort": 30002}]}}'
kubectl patch svc -n istio-system kiali -p '{"spec": {"type": "NodePort", "ports": [{"port": 20001, "targetPort": 20001, "nodePort": 30003}]}}'
kubectl patch svc -n istio-system tracing -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 16686, "nodePort": 30004}]}}'

✅ 출력

1
2
3
4
service/prometheus patched
service/grafana patched
service/kiali patched
service/tracing patched

🔐 자동 상호 TLS (Auto mTLS)

1. Webapp 및 Catalog 서비스 배포

1
2
3
4
5
6
7
8
9
10
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction

# 결과
serviceaccount/catalog created
service/catalog created
deployment.apps/catalog created
serviceaccount/webapp created
service/webapp created
deployment.apps/webapp created

2. Gateway 및 VirtualService 리소스 생성

1
2
3
4
5
kubectl apply -f services/webapp/istio/webapp-catalog-gw-vs.yaml -n istioinaction

# 결과
gateway.networking.istio.io/coolstore-gateway created
virtualservice.networking.istio.io/webapp-virtualservice create

3. Sleep 테스트 앱 매니페스트 확인

1
cat ch9/sleep.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sleep
---
apiVersion: v1
kind: Service
metadata:
  name: sleep
  labels:
    app: sleep
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: sleep
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sleep
  template:
    metadata:
      labels:
        app: sleep
    spec:
      serviceAccountName: sleep
      containers:
      - name: sleep
        image: governmentpaas/curl-ssl
        command: ["/bin/sleep", "3650d"]
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /etc/sleep/tls
          name: secret-volume
      volumes:
      - name: secret-volume
        secret:
          secretName: sleep-secret
          optional: true
---

4. Sleep 앱 배포 및 리소스 생성

1
2
3
4
5
6
kubectl apply -f ch9/sleep.yaml -n default

# 결과
serviceaccount/sleep created
service/sleep created
deployment.apps/sleep created

5. Sleep 리소스 배포 상태 확인

1
kubectl get deploy,pod,sa,svc,ep

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/sleep   1/1     1            1           41s

NAME                         READY   STATUS    RESTARTS   AGE
pod/sleep-6f8cfb8c8f-ckxzx   1/1     Running   0          41s

NAME                     SECRETS   AGE
serviceaccount/default   1         34m
serviceaccount/sleep     1         41s

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.200.1.1     <none>        443/TCP   34m
service/sleep        ClusterIP   10.200.1.204   <none>        80/TCP    41s

NAME                   ENDPOINTS         AGE
endpoints/kubernetes   172.18.0.2:6443   34m
endpoints/sleep        10.10.0.14:80     41s

6. Gateway 및 VirtualService 리소스 상태 확인

1
kubectl get gw,vs -n istioinaction

✅ 출력

1
2
3
4
5
NAME                                            AGE
gateway.networking.istio.io/coolstore-gateway   2m13s

NAME                                                       GATEWAYS                HOSTS                         AGE
virtualservice.networking.istio.io/webapp-virtualservice   ["coolstore-gateway"]   ["webapp.istioinaction.io"]   2m13s

7. Sleep → Webapp 평문 통신 요청 성공 확인

1
kubectl exec deploy/sleep -c sleep -- curl -s webapp.istioinaction/api/catalog -o /dev/null -w "%{http_code}\n"

✅ 출력

1
200

8. 평문 요청을 반복적으로 시뮬레이션하기

1
watch 'kubectl exec deploy/sleep -c sleep -- curl -s webapp.istioinaction/api/catalog -o /dev/null -w "%{http_code}\n"'

✅ 출력

1
2
3
Every 2.0s: kubectl exec deploy/sleep -c sleep -- curl -s webapp.istioinaction/api/catalog -o /dev/null -w "%{http_code}\n"    gram88: 11:44:51 AM
                                                                                                                                     in 0.132s (0)
200

9. Kiali를 통해 서비스 간 통신 상태 시각적으로 확인

unkonw → webapp: 평문 HTTP 통신 상태 시각화됨


🧩 이스티오의 PeerAuthentication 리소스 이해하기

1. 메시 범위 정책으로 모든 미인증 트래픽 거부하기

(1) 메시 전역 PeerAuthentication 설정 파일 확인

1
cat ch9/meshwide-strict-peer-authn.yaml 

✅ 출력

1
2
3
4
5
6
7
8
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "default"
  namespace: "istio-system"
spec:
  mtls:
    mode: STRICT

(2) 메시 전역 STRICT 모드 PeerAuthentication 적용

1
2
3
4
kubectl apply -f ch9/meshwide-strict-peer-authn.yaml -n istio-system

# 결과
peerauthentication.security.istio.io/default created

(3) Webapp 사이드카의 트래픽 로그 실시간 확인 시작

1
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f

✅ 출력

1
2
3
4
5
6
7
8
9
10
[2025-05-10T03:03:43.044Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 2 1 "-" "beegoServer" "4fe803fc-46c3-961a-a5df-1c1e12482a1a" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60900 10.200.1.219:80 10.10.0.12:36540 - default
[2025-05-10T03:03:43.043Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 3 3 "-" "curl/8.5.0" "4fe803fc-46c3-961a-a5df-1c1e12482a1a" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:57585 10.10.0.12:8080 10.10.0.14:58640 - default
[2025-05-10T03:03:45.204Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 1 1 "-" "beegoServer" "bd278a2f-d4ef-9865-bbfc-1f52d8c3064a" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60900 10.200.1.219:80 10.10.0.12:36542 - default
[2025-05-10T03:03:45.203Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 3 2 "-" "curl/8.5.0" "bd278a2f-d4ef-9865-bbfc-1f52d8c3064a" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:57585 10.10.0.12:8080 10.10.0.14:58642 - default
[2025-05-10T03:03:47.343Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 2 2 "-" "beegoServer" "e30f69be-9ba1-9e42-ac67-3e6e2311a26e" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60886 10.200.1.219:80 10.10.0.12:36552 - default
[2025-05-10T03:03:47.342Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 4 4 "-" "curl/8.5.0" "e30f69be-9ba1-9e42-ac67-3e6e2311a26e" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:38521 10.10.0.12:8080 10.10.0.14:58658 - default
[2025-05-10T03:03:49.514Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 2 1 "-" "beegoServer" "4323cfe1-4876-935b-b5a7-bb60fd53b09d" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60886 10.200.1.219:80 10.10.0.12:36564 - default
[2025-05-10T03:03:49.513Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 3 3 "-" "curl/8.5.0" "4323cfe1-4876-935b-b5a7-bb60fd53b09d" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:38521 10.10.0.12:8080 10.10.0.14:58666 - default
[2025-05-10T03:03:51.655Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 3 3 "-" "beegoServer" "702f62f5-d777-9f9e-81f5-087e6fb62c54" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60886 10.200.1.219:80 10.10.0.12:36574 - default
[2025-05-10T03:03:51.654Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 4 4 "-" "curl/8.5.0" "702f62f5-d777-9f9e-81f5-087e6fb62c54" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:57585 10.10.0.12:8080 10.10.0.14:58674 - default

(4) Sleep 앱에서 Webapp으로 평문 요청 전송 시도

1
kubectl exec deploy/sleep -c sleep -- curl -s http://webapp.istioinaction/api/catalog -o /dev/null -w "%{http_code}\n"

✅ 출력

1
2
000
command terminated with exit code 56

(5) 인증되지 않은 요청 실패로 인한 NR 에러 로그 확인

1
[2025-05-10T03:06:33.116Z] "- - -" 0 NR filter_chain_not_found - "-" 0 0 0 - "-" "-" "-" "-" "-" - - 10.10.0.12:8080 10.10.0.14:34678 - -

이 에러는 filter_chain_not_found로 인해 인증되지 않은 요청이 거부되었음을 나타냄


2. 상호 인증하기 않은 트래픽 허용하기

(1) PERMISSIVE 모드 PeerAuthentication 리소스 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
cat << EOF | kubectl apply -f -
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "default"             # Uses the "default" naming convention so that only one namespace-wide resource exists
  namespace: "istioinaction"  # Specifies the namespace to apply the policy
spec:
  mtls:
    mode: PERMISSIVE          # PERMISSIVE allows HTTP traffic.
EOF

# 결과
peerauthentication.security.istio.io/default created

(2) 생성된 PeerAuthentication 리소스 상태 확인

1
kubectl get PeerAuthentication -A 

✅ 출력

1
2
3
NAMESPACE       NAME      MODE         AGE
istio-system    default   STRICT       7m1s
istioinaction   default   PERMISSIVE   39s

(3) Istio 프록시 로그로 mTLS 적용 상태 모니터링

1
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f

✅ 출력

1
2
3
4
5
6
7
8
9
10
[2025-05-10T03:03:45.204Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 1 1 "-" "beegoServer" "bd278a2f-d4ef-9865-bbfc-1f52d8c3064a" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60900 10.200.1.219:80 10.10.0.12:36542 - default
[2025-05-10T03:03:45.203Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 3 2 "-" "curl/8.5.0" "bd278a2f-d4ef-9865-bbfc-1f52d8c3064a" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:57585 10.10.0.12:8080 10.10.0.14:58642 - default
[2025-05-10T03:03:47.343Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 2 2 "-" "beegoServer" "e30f69be-9ba1-9e42-ac67-3e6e2311a26e" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60886 10.200.1.219:80 10.10.0.12:36552 - default
[2025-05-10T03:03:47.342Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 4 4 "-" "curl/8.5.0" "e30f69be-9ba1-9e42-ac67-3e6e2311a26e" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:38521 10.10.0.12:8080 10.10.0.14:58658 - default
[2025-05-10T03:03:49.514Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 2 1 "-" "beegoServer" "4323cfe1-4876-935b-b5a7-bb60fd53b09d" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60886 10.200.1.219:80 10.10.0.12:36564 - default
[2025-05-10T03:03:49.513Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 3 3 "-" "curl/8.5.0" "4323cfe1-4876-935b-b5a7-bb60fd53b09d" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:38521 10.10.0.12:8080 10.10.0.14:58666 - default
[2025-05-10T03:03:51.655Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 3 3 "-" "beegoServer" "702f62f5-d777-9f9e-81f5-087e6fb62c54" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60886 10.200.1.219:80 10.10.0.12:36574 - default
[2025-05-10T03:03:51.654Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 4 4 "-" "curl/8.5.0" "702f62f5-d777-9f9e-81f5-087e6fb62c54" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:57585 10.10.0.12:8080 10.10.0.14:58674 - default
[2025-05-10T03:06:33.116Z] "- - -" 0 NR filter_chain_not_found - "-" 0 0 0 - "-" "-" "-" "-" "-" - - 10.10.0.12:8080 10.10.0.14:34678 - -
2025-05-10T03:08:47.637181Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012

(4) Sleep 앱에서 Webapp으로의 평문 요청 정상 응답 확인

1
kubectl exec deploy/sleep -c sleep -- curl -s http://webapp.istioinaction/api/catalog -o /dev/null -w "%{http_code}\n"

✅ 출력

1
200
1
2
[2025-05-10T03:14:05.224Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 13 12 "-" "beegoServer" "bff7c6ca-9096-924b-97c6-b9bde5a5efc0" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:56994 10.200.1.219:80 10.10.0.12:55086 - default
[2025-05-10T03:14:05.223Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 15 14 "-" "curl/8.5.0" "bff7c6ca-9096-924b-97c6-b9bde5a5efc0" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:57585 10.10.0.12:8080 10.10.0.14:60558 - default

(5) 다음 실습을 위한 PeerAuthentication 리소스 삭제

1
2
3
4
kubectl delete pa default -n istioinaction

# 결과
peerauthentication.security.istio.io "default" deleted

3. 워크로드별 PeerAuthentication 정책 적용하기

(1) 프록시 상태 확인으로 워크로드 동기화 상태 점검하기

1
docker exec -it myk8s-control-plane istioctl proxy-status

✅ 출력

1
2
3
4
5
NAME                                                   CLUSTER        CDS        LDS        EDS        RDS          ECDS         ISTIOD                    VERSION
catalog-6cf4b97d-bj4lh.istioinaction                   Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-5cxpq     1.17.8
istio-egressgateway-85df6b84b7-fvmpz.istio-system      Kubernetes     SYNCED     SYNCED     SYNCED     NOT SENT     NOT SENT     istiod-8d74787f-5cxpq     1.17.8
istio-ingressgateway-6bb8fb6549-dq7gl.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-5cxpq     1.17.8
webapp-7685bcb84-7grs9.istioinaction                   Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-5cxpq     1.17.8

(2) webapp 워크로드에 PERMISSIVE PeerAuthentication 리소스 정의

1
cat ch9/workload-permissive-peer-authn.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "webapp"
  namespace: "istioinaction"
spec:
  selector:
    matchLabels:
      app: webapp 
  mtls:
    mode: PERMISSIVE

(3) PeerAuthentication 리소스를 클러스터에 적용하기

1
2
3
4
kubectl apply -f ch9/workload-permissive-peer-authn.yaml

# 결과
peerauthentication.security.istio.io/webapp created

(4) 전체 PeerAuthentication 리소스 상태 확인

1
kubectl get pa -A

✅ 출력

1
2
3
NAMESPACE       NAME      MODE         AGE
istio-system    default   STRICT       14m
istioinaction   webapp    PERMISSIVE   18s

(5) webapp 프록시 로그에서 PERMISSIVE 적용 여부 확인

1
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f

(6) sleep → webapp으로의 HTTP 평문 요청 정상 동작 확인

1
kubectl exec deploy/sleep -c sleep -- curl -s http://webapp.istioinaction/api/catalog -o /dev/null -w "%{http_code}\n"

✅ 출력

1
200
1
2
[2025-05-10T03:19:53.660Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 9 8 "-" "beegoServer" "125541bd-f6d0-9987-b813-03ea022c3fc9" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:45070 10.200.1.219:80 10.10.0.12:36418 - default
[2025-05-10T03:19:53.659Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 10 10 "-" "curl/8.5.0" "125541bd-f6d0-9987-b813-03ea022c3fc9" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:38521 10.10.0.12:8080 10.10.0.14:42880 - default

(7) catalog 프록시 로그 확인

1
kubectl logs -n istioinaction -l app=catalog -c istio-proxy -f

(8) sleep → catalog 요청 실패 확인 (STRICT로 인해 000 응답)

1
kubectl exec deploy/sleep -c sleep -- curl -s http://catalog.istioinaction/api/items -o /dev/null -w "%{http_code}\n"

✅ 출력

1
2
000
command terminated with exit code 56
1
[2025-05-10T03:22:31.451Z] "- - -" 0 NR filter_chain_not_found - "-" 0 0 0 - "-" "-" "-" "-" "-" - - 10.10.0.13:3000 10.10.0.14:45024 - -

4. tcpdump로 서비스 간 트래픽 스니핑하기

(1) IstioProxy 부트스트랩 설정 정보 확인

1
kubectl get istiooperator -n istio-system installed-state -o yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
      proxy:
        autoInject: enabled
        clusterDomain: cluster.local
        componentLogLevel: misc:error
        enableCoreDump: false
        excludeIPRanges: ""
        excludeInboundPorts: ""
        excludeOutboundPorts: ""
        image: proxyv2
        includeIPRanges: '*'
        logLevel: warning
        privileged: true
        readinessFailureThreshold: 30
        readinessInitialDelaySeconds: 1
        readinessPeriodSeconds: 2
        resources:
          limits:
            cpu: 2000m
            memory: 1024Mi
          requests:
            cpu: 10m
            memory: 40Mi
        statusPort: 15020
        tracer: zipkin
...

(2) webapp 파드의 proxy 컨테이너 설정 확인

1
kubectl get pod -n istioinaction -l app=webapp -o json

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
...
                        "image": "docker.io/istio/proxyv2:1.17.8",
                        "imagePullPolicy": "IfNotPresent",
                        "name": "istio-proxy",
                        "ports": [
                            {
                                "containerPort": 15090,
                                "name": "http-envoy-prom",
                                "protocol": "TCP"
                            }
                        ],
                        "readinessProbe": {
                            "failureThreshold": 30,
                            "httpGet": {
                                "path": "/healthz/ready",
                                "port": 15021,
                                "scheme": "HTTP"
                            },
                            "initialDelaySeconds": 1,
                            "periodSeconds": 2,
                            "successThreshold": 1,
                            "timeoutSeconds": 3
                        },
                        "resources": {
                            "limits": {
                                "cpu": "2",
                                "memory": "1Gi"
                            },
                            "requests": {
                                "cpu": "10m",
                                "memory": "40Mi"
                            }
                        },
                        "securityContext": {
                            "allowPrivilegeEscalation": true,
                            "capabilities": {
                                "drop": [
                                    "ALL"
                                ]
                            },
                            "privileged": true,
                            "readOnlyRootFilesystem": true,
                            "runAsGroup": 1337,
                            "runAsNonRoot": true,
                            "runAsUser": 1337
                        },
...

(3) webapp 프록시 컨테이너 유저 확인

1
2
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- whoami
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- id

✅ 출력

1
2
istio-proxy
uid=1337(istio-proxy) gid=1337(istio-proxy) groups=1337(istio-proxy)

(4) sudo 권한 확인 및 tcpdump 명령 사용 가능 여부 확인

1
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- sudo whoami

✅ 출력

1
root
1
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- sudo tcpdump -h

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
tcpdump version 4.99.1
libpcap version 1.10.1 (with TPACKET_V3)
OpenSSL 3.0.2 15 Mar 2022
Usage: tcpdump [-AbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ] [--count]
		[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
		[ -i interface ] [ --immediate-mode ] [ -j tstamptype ]
		[ -M secret ] [ --number ] [ --print ] [ -Q in|out|inout ]
		[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]
		[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]
		[ --time-stamp-precision precision ] [ --micro ] [ --nano ]
		[ -z postrotate-command ] [ -Z user ] [ expression ]

(5) webapp 프록시에서 트래픽 스니핑(tcpdump) 실행

1
2
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy \
  -- sudo tcpdump -l --immediate-mode -vv -s 0 '(((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) and not (port 53)'

(6) sleep → webapp 평문 요청 테스트

1
2
3
4
kubectl exec deploy/sleep -c sleep -- curl -s webapp.istioinaction/api/catalog -o /dev/null -w "%{http_code}\n"

# 결과
200

(6.1) sleep -> webapp 요청 캡처 (HTTP)

1
2
3
4
5
6
03:41:56.343128 IP (tos 0x0, ttl 63, id 48359, offset 0, flags [DF], proto TCP (6), length 146)
    10-10-0-14.sleep.default.svc.cluster.local.45782 > webapp-7685bcb84-7grs9.http-alt: Flags [P.], cksum 0x14b2 (incorrect -> 0x3e7f), seq 2765665494:2765665588, ack 3387857729, win 502, options [nop,nop,TS val 2533578520 ecr 1765006870], length 94: HTTP, length: 94
	GET /api/catalog HTTP/1.1
	Host: webapp.istioinaction
	User-Agent: curl/8.5.0
	Accept: */*

(6.2) webapp -> catalog 호출 캡처 (HTTPS)

1
2
03:41:56.344988 IP (tos 0x0, ttl 64, id 38893, offset 0, flags [DF], proto TCP (6), length 1304)
    webapp-7685bcb84-7grs9.60838 > 10-10-0-13.catalog.istioinaction.svc.cluster.local.3000: Flags [P.], cksum 0x1937 (incorrect -> 0x2aff), seq 579087422:579088674, ack 975181635, win 587, options [nop,nop,TS val 1072992199 ecr 3856454488], length 1252

(6.3) catalog -> webapp 응답 캡처 (HTTPS)

1
2
03:41:56.347203 IP (tos 0x0, ttl 63, id 42046, offset 0, flags [DF], proto TCP (6), length 1788)
    10-10-0-13.catalog.istioinaction.svc.cluster.local.3000 > webapp-7685bcb84-7grs9.60838: Flags [P.], cksum 0x1b1b (incorrect -> 0xa41e), seq 1:1737, ack 1252, win 589, options [nop,nop,TS val 3856632941 ecr 1072992199], length 1736

(6.4) webapp -> sleep 응답 캡처 (HTTP)

1
2
3
4
5
6
7
8
9
10
11
03:41:56.355163 IP (tos 0x0, ttl 64, id 25012, offset 0, flags [DF], proto TCP (6), length 662)
    webapp-7685bcb84-7grs9.http-alt > 10-10-0-14.sleep.default.svc.cluster.local.45782: Flags [P.], cksum 0x16b6 (incorrect -> 0xed33), seq 1:611, ack 94, win 509, options [nop,nop,TS val 1765006883 ecr 2533578520], length 610: HTTP, length: 610
	HTTP/1.1 200 OK
	content-length: 357
	content-type: application/json; charset=utf-8
	date: Sat, 10 May 2025 03:41:56 GMT
	x-envoy-upstream-service-time: 4
	server: istio-envoy
	x-envoy-decorator-operation: webapp.istioinaction.svc.cluster.local:80/*
	
	[{"id":1,"color":"amber","department":"Eyewear","name":"Elinor Glasses","price":"282.00"},{"id":2,"color":"cyan","department":"Clothing","name":"Atlas Shirt","price":"127.00"},{"id":3,"color":"teal","department":"Clothing","name":"Small Metal Shoes","price":"232.00"},{"id":4,"color":"red","department":"Watches","name":"Red Dragon Watch","price":"232.00"}] [|http]

(7) 서비스 및 엔드포인트 IP 확인

1
kubectl get svc,ep -n istioinaction

✅ 출력

1
2
3
4
5
6
7
NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/catalog   ClusterIP   10.200.1.219   <none>        80/TCP    66m
service/webapp    ClusterIP   10.200.1.171   <none>        80/TCP    66m

NAME                ENDPOINTS         AGE
endpoints/catalog   10.10.0.13:3000   66m
endpoints/webapp    10.10.0.12:8080   66m

5. 워크로드 ID가 워크로드 서비스 어카운트에 연결돼 있는지 확인하기

(1) catalog 파드에서 포트 3000 트래픽 스니핑 시작

1
2
3
4
5
kubectl exec -it -n istioinaction deploy/catalog -c istio-proxy \
  -- sudo tcpdump -l --immediate-mode -vv -s 0 'tcp port 3000'
  
# 결과  
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes

(2) webapp의 루트 인증서 경로 확인

1
kubectl -n istioinaction exec deploy/webapp -c istio-proxy -- ls -l /var/run/secrets/istio/root-cert.pem

✅ 출력

1
lrwxrwxrwx 1 root root 20 May 10 02:38 /var/run/secrets/istio/root-cert.pem -> ..data/root-cert.pem

(3) webapp의 루트 인증서 상세 정보 확인

1
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- openssl x509 -in /var/run/secrets/istio/root-cert.pem -text -noout

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            c6:37:27:9c:46:cd:09:81:30:79:57:e0:39:01:4c:97
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O = cluster.local
        Validity
            Not Before: May 10 02:12:37 2025 GMT
            Not After : May  8 02:12:37 2035 GMT
        Subject: O = cluster.local
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:b6:77:c8:e9:26:3b:e3:78:e3:ad:bc:16:1e:78:
                    5f:ea:f4:d1:fb:49:46:79:fc:6c:4a:58:50:17:32:
                    e0:33:59:7f:45:50:8c:61:0f:2f:a0:34:6b:2d:22:
                    7a:72:51:ae:02:ca:9b:9d:28:c1:a1:4b:c6:b9:28:
                    85:7b:90:0c:81:e4:1a:0d:4b:4c:c2:8e:ba:72:c0:
                    7c:ba:5d:7e:5c:c4:28:3d:3e:95:20:4a:51:37:1e:
                    49:0d:98:fd:e7:f4:b0:d7:e5:77:b7:03:3a:94:c0:
                    7c:eb:52:ce:26:2b:09:67:48:11:4b:26:fd:5b:0f:
                    65:0c:02:84:a7:ed:88:f8:88:a7:64:14:59:4c:f6:
                    d4:fc:94:9b:21:47:0d:6c:1b:4d:b1:1f:05:ae:5a:
                    57:98:cc:b5:8f:ef:e8:f2:dd:06:3b:6d:44:b6:f8:
                    87:ae:e9:0e:82:26:77:d7:10:5f:f7:4c:11:e6:e1:
                    3a:59:93:2e:da:3b:79:9c:f9:d7:1b:44:5b:26:21:
                    cf:f4:38:07:82:a2:02:36:ca:6a:09:70:62:0a:c4:
                    65:68:11:c3:04:38:44:70:d2:10:e9:bc:c0:8b:6b:
                    9d:33:9f:35:03:74:17:c4:c6:b8:ff:25:95:4a:05:
                    f3:e0:fa:88:a8:22:63:d9:3f:9e:d2:33:fd:a6:73:
                    62:b5
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Certificate Sign
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Key Identifier: 
                B8:AD:47:DC:3C:DA:7D:2B:3E:CB:16:A8:02:C3:FE:20:30:28:74:92
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        8b:0c:1b:76:cd:5b:83:e7:f2:7c:ba:82:ce:0a:65:b6:54:fc:
        1d:5d:b3:fd:85:23:2d:21:ef:36:ae:85:2e:21:3a:a8:c3:29:
        49:f2:4e:76:7b:0d:bb:cc:83:6f:7c:33:de:6c:92:be:88:7a:
        e9:a7:09:2d:80:78:da:bc:26:e8:e0:09:4b:45:f9:55:98:78:
        5c:f4:25:06:3b:1a:be:fe:15:39:85:a7:c7:50:90:88:65:c3:
        6a:8e:a5:d6:d2:3e:05:fb:83:3a:c1:60:68:a5:b6:aa:41:a2:
        c3:c4:45:6f:a1:6c:7a:67:48:89:5e:45:c6:72:a8:f8:bc:e2:
        d0:65:82:c5:73:2f:1d:c7:53:0f:9d:ef:ef:c1:15:58:05:1d:
        cc:a2:6d:b3:e1:28:f0:db:25:b8:d4:c1:0f:d6:5d:6e:35:e9:
        e4:44:e3:e3:f5:98:2d:9b:86:17:19:2b:85:b4:38:5d:ea:44:
        a8:85:5f:0b:de:5f:2d:ad:9e:c9:ba:28:4d:90:70:7f:47:c7:
        c7:2a:87:cf:4e:83:c5:f0:f1:f0:5f:a8:b0:64:b3:41:30:32:
        4f:d6:fa:25:e5:d4:80:2e:95:3b:2e:e0:62:5b:d9:2d:3a:3f:
        a4:37:7a:2f:53:7e:f6:1f:ad:0c:1b:3b:de:44:95:f3:5b:a4:
        11:77:13:67

(4) webapp이 catalog 서비스로 TLS 연결 후 인증서 출력

1
2
3
4
5
kubectl -n istioinaction exec deploy/webapp -c istio-proxy \
  -- openssl s_client -showcerts \
  -connect catalog.istioinaction.svc.cluster.local:80 \
  -CAfile /var/run/secrets/istio/root-cert.pem | \
  openssl x509 -in /dev/stdin -text -noout

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
depth=1 O = cluster.local
verify return:1
depth=0 
verify return:1
4007F03899790000:error:0A00045C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required:../ssl/record/rec_layer_s3.c:1584:SSL alert number 116
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            65:6b:dd:d5:c5:31:b2:b2:e5:80:ad:38:a2:e5:14:da
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O=cluster.local
        Validity
            Not Before: May 10 02:36:43 2025 GMT
            Not After : May 11 02:38:43 2025 GMT
        Subject: 
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ab:1d:64:59:19:99:f9:fc:58:66:c2:67:35:be:
                    32:df:ca:b7:8a:55:84:c4:37:a0:41:1e:3c:26:4a:
                    26:91:04:3d:c7:eb:9c:92:b7:ab:54:32:2a:7a:e5:
                    cd:4b:f8:28:cf:ec:8d:76:72:dd:1f:de:62:71:f2:
                    39:94:e6:2a:f7:cd:27:6e:c8:53:27:8c:bb:07:c9:
                    ba:79:d0:cd:53:0a:eb:82:82:be:81:98:37:4a:79:
                    27:b7:4e:4c:19:79:14:ca:97:c2:8d:2b:06:a1:7f:
                    58:94:dd:ff:d9:78:e6:90:ed:b7:f9:bd:e4:9e:93:
                    b4:8f:c8:da:d2:32:fd:7c:85:f6:7f:7f:6f:94:08:
                    2b:ac:c7:28:a1:12:6b:da:9d:41:58:22:6a:89:2a:
                    aa:6d:9a:a0:34:ba:ca:46:61:72:7e:6d:c7:c0:56:
                    5b:47:96:0f:61:7c:a0:cf:e8:de:5b:31:a6:a5:9f:
                    e5:10:13:39:8b:12:c9:0a:9b:88:07:c4:f7:c2:7c:
                    48:2d:18:e1:ab:96:7f:d7:62:2e:14:ae:24:fe:df:
                    37:3a:8e:6d:96:e2:2b:e7:42:b7:3c:c2:a9:09:d6:
                    f1:98:72:70:3c:18:02:a8:01:2f:3c:df:74:81:f5:
                    53:e0:ce:3c:27:10:6c:4d:3d:ef:60:6a:29:4a:19:
                    cc:d9
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication # 사용처 : 웹서버, 웹클라이언트
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Authority Key Identifier: 
                B8:AD:47:DC:3C:DA:7D:2B:3E:CB:16:A8:02:C3:FE:20:30:28:74:92
            X509v3 Subject Alternative Name: critical
                URI:spiffe://cluster.local/ns/istioinaction/sa/catalog # SPIFFE ID 확인
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        93:89:79:e2:d4:98:dc:65:0c:58:12:a8:b8:49:32:1b:62:82:
        01:60:0b:c8:f5:17:c3:da:ca:c5:d1:b6:f6:bc:d0:d9:2b:fc:
        fe:81:42:22:74:43:be:ce:25:1c:74:db:08:59:ca:25:a9:be:
        6b:31:5e:19:2c:55:cf:56:be:ed:45:3c:dd:e2:33:c7:b9:1e:
        26:64:2c:fa:0b:f3:6d:dc:48:6d:63:df:72:f9:89:13:ad:5d:
        b2:fe:01:57:94:05:6b:98:5c:ef:10:41:6e:54:c7:6e:c0:61:
        c6:fc:a2:4a:fe:bd:7b:96:63:ee:b8:67:7f:ef:a4:d9:88:75:
        3b:e2:39:ac:80:11:a4:5e:59:2b:75:30:bd:e2:ae:75:fd:db:
        ff:b7:59:1e:76:23:51:2c:aa:50:eb:82:75:4d:20:51:81:08:
        b8:e1:d7:7d:be:c5:43:e2:cf:6f:b3:bc:05:3b:0e:11:13:a6:
        df:d0:04:ba:b4:94:b5:cb:bf:4c:e2:a6:3e:fe:8d:0e:8d:2f:
        b3:8b:ef:ec:95:e2:b1:fc:e4:46:6e:e8:94:a6:4c:e1:44:17:
        75:c5:34:c1:3a:b3:9b:f8:d8:f9:28:c4:4a:a4:ba:7f:80:6c:
        86:aa:db:46:cc:10:2b:0d:16:69:96:eb:24:e6:c2:80:31:a8:
        5b:73:30:a2
command terminated with exit code 1

(5) catalog 파드의 서비스 어카운트 확인

1
kubectl describe pod -n istioinaction -l app=catalog | grep 'Service Account'

✅ 출력

1
Service Account:  catalog

(6) webapp 파드에서 istio-proxy 컨테이너 쉘 접속

1
2
3
kubectl -n istioinaction exec -it deploy/webapp -c istio-proxy -- /bin/bash

istio-proxy@webapp-7685bcb84-7grs9:/$

(7) Istio 루트 인증서를 사용해 catalog 인증서 검증

1
2
3
istio-proxy@webapp-7685bcb84-7grs9:/$ openssl verify -CAfile /var/run/secrets/istio/root-cert.pem \
  <(openssl s_client -connect \
  catalog.istioinaction.svc.cluster.local:80 -showcerts 2>/dev/null)

✅ 출력

1
/dev/fd/63: OK

(8) 검증 완료 후 istio-proxy 컨테이너 쉘 종료

1
2
istio-proxy@webapp-7685bcb84-7grs9:/$ exit
exit

🔑 워크로드 ID의 단계별 부트스트랩

1. 서비스 어카운트 토큰 파일 확인

1
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- ls -l /var/run/secrets/kubernetes.io/serviceaccount/

✅ 출력

1
2
3
4
total 0
lrwxrwxrwx 1 root root 13 May 10 02:38 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 May 10 02:38 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 May 10 02:38 token -> ..data/token

2. 서비스 어카운트 토큰 값 추출

1
2
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
TOKEN=$(kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- cat /var/run/secrets/kubernetes.io/serviceaccount/token)

✅ 출력

1
eyJhbGciOiJSUzI1NiIsImtpZCI6Im91bHpURE8zdXRqMmJLNFB4VHctU2FXYnh5aklCUE5tX0VDMGZFNmpxV1UifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzc4MzgzNjE4LCJpYXQiOjE3NDY4NDc2MTgsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJpc3Rpb2luYWN0aW9uIiwicG9kIjp7Im5hbWUiOiJ3ZWJhcHAtNzY4NWJjYjg0LTdncnM5IiwidWlkIjoiYWMzNzE5MDAtNmFjZS00ODkzLWIxMzQtZDNjZmUyZTRhYzRlIn0sInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJ3ZWJhcHAiLCJ1aWQiOiJlNjdiMGJiYy01YjlhLTRmYmQtYTMzYi05ODE5OGMwYzU5MWEifSwid2FybmFmdGVyIjoxNzQ2ODUxMjI1fSwibmJmIjoxNzQ2ODQ3NjE4LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6aXN0aW9pbmFjdGlvbjp3ZWJhcHAifQ.I_zBfSlmzZr3F1oQ6MEPv84H4jbPk-BrZr8AFc_GCl98QKQoRRcOq2MajM-ODZ_8p8tIoWGWmiX4MaOTGgC_vQZp_qkBI09y8fqGB-W9yLBEnfFR-IzbdiCmwTG3PDWlhtPCabYrBwlKd8oPkIXWQ_hgjlsK2RIAdIr975nKRB3FExcZW1qh8SQ6n0Fy7fUelUFUw2UWHwHYzhCrZ77tdWKfQKGdprzI88R6RrPF7PpK7pBi0ypDwLzanS5P5piPKMIRofJLvmNH3O9COmTGgh0jkgKIjvLsyl9o29E4gXZUk6eYahxU1-AGmXF645Xact7eYI9bJnNNVcDY8EEwSA

3. JWT 토큰 헤더 디코딩

1
echo $TOKEN | cut -d '.' -f1 | base64 --decode | sed 's/$/}/' | jq

✅ 출력

1
2
3
4
{
  "alg": "RS256",
  "kid": "oulzTDO3utj2bK4PxTw-SaWbxyjIBPNm_EC0fE6jqWU"
}

4. JWT 토큰 페이로드 디코딩

1
echo $TOKEN | cut -d '.' -f2 | base64 --decode | sed 's/$/}/' | jq

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "aud": [
    "https://kubernetes.default.svc.cluster.local"
  ],
  "exp": 1778383618,
  "iat": 1746847618,
  "iss": "https://kubernetes.default.svc.cluster.local",
  "kubernetes.io": {
    "namespace": "istioinaction",
    "pod": {
      "name": "webapp-7685bcb84-7grs9",
      "uid": "ac371900-6ace-4893-b134-d3cfe2e4ac4e"
    },
    "serviceaccount": {
      "name": "webapp",
      "uid": "e67b0bbc-5b9a-4fbd-a33b-98198c0c591a"
    },
    "warnafter": 1746851225
  },
  "nbf": 1746847618,
  "sub": "system:serviceaccount:istioinaction:webapp"
}

5. jwt-cli 설치 및 JWT 디코딩 테스트

1
yay -S jwt-cli

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Sync Explicit (1): jwt-cli-6.2.0-1
resolving dependencies...
looking for conflicting packages...

Packages (1) jwt-cli-6.2.0-1

Total Download Size:   1.17 MiB
Total Installed Size:  3.40 MiB

:: Proceed with installation? [Y/n] Y
:: Retrieving packages...
 jwt-cli-6.2.0-1-...  1193.5 KiB  6.27 MiB/s 00:00 [##############] 100%
(1/1) checking keys in keyring                     [##############] 100%
(1/1) checking package integrity                   [##############] 100%
(1/1) loading package files                        [##############] 100%
(1/1) checking for file conflicts                  [##############] 100%
(1/1) checking available disk space                [##############] 100%
:: Processing package changes...
(1/1) installing jwt-cli                           [##############] 100%
:: Running post-transaction hooks...
(1/1) Arming ConditionNeedsUpdate...
1
jwt decode $TOKEN

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Token header
------------
{
  "alg": "RS256",
  "kid": "oulzTDO3utj2bK4PxTw-SaWbxyjIBPNm_EC0fE6jqWU"
}

Token claims
------------
{
  "aud": [
    "https://kubernetes.default.svc.cluster.local"
  ],
  "exp": 1778383618,
  "iat": 1746847618,
  "iss": "https://kubernetes.default.svc.cluster.local",
  "kubernetes.io": {
    "namespace": "istioinaction",
    "pod": {
      "name": "webapp-7685bcb84-7grs9",
      "uid": "ac371900-6ace-4893-b134-d3cfe2e4ac4e"
    },
    "serviceaccount": {
      "name": "webapp",
      "uid": "e67b0bbc-5b9a-4fbd-a33b-98198c0c591a"
    },
    "warnafter": 1746851225
  },
  "nbf": 1746847618,
  "sub": "system:serviceaccount:istioinaction:webapp"
}

6. 서비스 어카운트 토큰 유효 시간 확인

1
kubectl get pod -n istioinaction -l app=webapp -o yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
    - name: kube-api-access-bhflf
      projected:
        defaultMode: 420
        sources:
        - serviceAccountToken:
            expirationSeconds: 3607
            path: token
        - configMap:
            items:
            - key: ca.crt
              path: ca.crt
            name: kube-root-ca.crt
        - downwardAPI:
            items:
            - fieldRef:
                apiVersion: v1
                fieldPath: metadata.namespace
              path: namespace
...

7. tokenreviews 리소스 확인

1
kubectl api-resources | grep -i token

✅ 출력

1
tokenreviews                                   authentication.k8s.io/v1               false        TokenReview
1
kubectl explain tokenreviews.authentication.k8s.io

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
KIND:     TokenReview
VERSION:  authentication.k8s.io/v1

DESCRIPTION:
     TokenReview attempts to authenticate a token to a known user. Note:
     TokenReview requests may be cached by the webhook token authenticator
     plugin in the kube-apiserver.

FIELDS:
   apiVersion	<string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind	<string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   spec	<Object> -required-
     Spec holds information about the request being evaluated

   status	<Object>
     Status is filled in by the server and indicates whether the request can be
     authenticated.

8. istiod 서비스 어카운트 권한 확인

1
kubectl rolesum istiod -n istio-system

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
ServiceAccount: istio-system/istiod
Secrets:
• */istiod-token-7jxvs

Policies:
• [RB] istio-system/istiod ⟶  [R] istio-system/istiod
  Resource                      Name  Exclude  Verbs  G L W C U P D DC  
  configmaps                    [*]     [-]     [-]   ✖ ✖ ✖ ✖ ✖ ✖ ✔ ✖   
  gateways.networking.istio.io  [*]     [-]     [-]   ✖ ✖ ✖ ✔ ✖ ✖ ✖ ✖   
  secrets                       [*]     [-]     [-]   ✔ ✔ ✔ ✔ ✔ ✖ ✔ ✖   

• [CRB] */istiod-clusterrole-istio-system ⟶  [CR] */istiod-clusterrole-istio-system
  Resource                                                                                                                                             Name               Exclude    Verbs    G L W C U P D DC  
  *.[config.istio.io,security.istio.io,networking.istio.io,authentication.istio.io,rbac.istio.io,telemetry.istio.io,extensions.istio.io]               [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  *.[networking.x-k8s.io,gateway.networking.k8s.io]                                                                                                    [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✔ ✔ ✖ ✖   
  certificatesigningrequests.certificates.k8s.io                                                                                                       [*]                  [-]       [-]     ✔ ✖ ✔ ✔ ✔ ✖ ✔ ✖   
  certificatesigningrequests.certificates.k8s.io/approval                                                                                              [*]                  [-]       [-]     ✔ ✖ ✔ ✔ ✔ ✖ ✔ ✖   
  certificatesigningrequests.certificates.k8s.io/status                                                                                                [*]                  [-]       [-]     ✔ ✖ ✔ ✔ ✔ ✖ ✔ ✖   
  configmaps                                                                                                                                           [*]                  [-]       [-]     ✔ ✔ ✔ ✔ ✔ ✖ ✖ ✖   
  customresourcedefinitions.apiextensions.k8s.io                                                                                                       [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  endpoints                                                                                                                                            [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  endpointslices.discovery.k8s.io                                                                                                                      [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  gatewayclasses.gateway.networking.k8s.io                                                                                                             [*]                  [-]       [-]     ✖ ✖ ✖ ✔ ✔ ✔ ✔ ✖   
  ingressclasses.networking.k8s.io                                                                                                                     [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  ingresses.networking.k8s.io                                                                                                                          [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  ingresses.networking.k8s.io/status                                                                                                                   [*]                  [-]       [-]     ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔   
  mutatingwebhookconfigurations.admissionregistration.k8s.io                                                                                           [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✔ ✔ ✖ ✖   
  namespaces                                                                                                                                           [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  nodes                                                                                                                                                [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  pods                                                                                                                                                 [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  secrets                                                                                                                                              [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  serviceexports.multicluster.x-k8s.io                                                                                                                 [*]                  [-]       [-]     ✔ ✔ ✔ ✔ ✖ ✖ ✔ ✖   
  serviceimports.multicluster.x-k8s.io                                                                                                                 [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  services                                                                                                                                             [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  signers.certificates.k8s.io                                                                                                             [kubernetes.io/legacy-unknown]    [-]    [approve]  ✖ ✖ ✖ ✖ ✖ ✖ ✖ ✖   
  subjectaccessreviews.authorization.k8s.io                                                                                                            [*]                  [-]       [-]     ✖ ✖ ✖ ✔ ✖ ✖ ✖ ✖   
  tokenreviews.authentication.k8s.io                                                                                                                   [*]                  [-]       [-]     ✖ ✖ ✖ ✔ ✖ ✖ ✖ ✖   
  validatingwebhookconfigurations.admissionregistration.k8s.io                                                                                         [*]                  [-]       [-]     ✔ ✔ ✔ ✖ ✔ ✖ ✖ ✖   
  workloadentries.networking.istio.io                                                                                                                  [*]                  [-]       [-]     ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖   
  workloadentries.networking.istio.io/status                                                                                                           [*]                  [-]       [-]     ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖   

• [CRB] */istiod-gateway-controller-istio-system ⟶  [CR] */istiod-gateway-controller-istio-system
  Resource          Name  Exclude  Verbs  G L W C U P D DC  
  deployments.apps  [*]     [-]     [-]   ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖   
  serviceaccounts   [*]     [-]     [-]   ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖   
  services          [*]     [-]     [-]   ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✖   

9. 유닉스 도메인 소켓 리슨 상태 확인

1
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- ss -xpl

✅ 출력

1
2
3
Netid State  Recv-Q Send-Q                                Local Address:Port         Peer Address:Port   Process                                
u_str LISTEN 0      4096                            etc/istio/proxy/XDS 292312                  * 0       users:(("pilot-agent",pid=1,fd=11))   
u_str LISTEN 0      4096   ./var/run/secrets/workload-spiffe-uds/socket 292311                  * 0       users:(("pilot-agent",pid=1,fd=10)) 

10. 유닉스 도메인 소켓 연결 상태 확인

1
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- ss -xp

✅ 출력

1
2
3
4
5
Netid State Recv-Q Send-Q                                Local Address:Port   Peer Address:Port  Process                             
u_str ESTAB 0      0                                                 * 886153            * 881658 users:(("envoy",pid=31,fd=21))     
u_str ESTAB 0      0      ./var/run/secrets/workload-spiffe-uds/socket 299120            * 296278 users:(("pilot-agent",pid=1,fd=16))
u_str ESTAB 0      0                                                 * 296278            * 299120 users:(("envoy",pid=31,fd=20))     
u_str ESTAB 0      0                               etc/istio/proxy/XDS 881658            * 886153 users:(("pilot-agent",pid=1,fd=9)) 

11. 유닉스 도메인 소켓 파일 확인

1
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- ls -l /var/run/secrets/workload-spiffe-uds/socket

✅ 출력

1
srw-rw-rw- 1 istio-proxy istio-proxy 0 May 10 02:38 /var/run/secrets/workload-spiffe-uds/socket

12. Istio 프록시 내 인증서 확인

1
docker exec -it myk8s-control-plane istioctl proxy-config secret deploy/webapp.istioinaction

✅ 출력

1
2
3
RESOURCE NAME     TYPE           STATUS     VALID CERT     SERIAL NUMBER                               NOT AFTER                NOT BEFORE
default           Cert Chain     ACTIVE     true           95203089389636103008735829400667113133      2025-05-11T02:38:50Z     2025-05-10T02:36:50Z
ROOTCA            CA             ACTIVE     true           263473522888112478359842578502703467671     2035-05-08T02:12:37Z     2025-05-10T02:12:37Z

13. Istio 프록시 인증서 상세 JSON 확인

1
docker exec -it myk8s-control-plane istioctl proxy-config secret deploy/webapp.istioinaction -o json

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
    "dynamicActiveSecrets": [
        {
            "name": "default",
            "lastUpdated": "2025-05-10T02:38:50.399Z",
            "secret": {
                "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret",
                "name": "default",
                "tlsCertificate": {
                    "certificateChain": {
                        "inlineBytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURSVENDQWkyZ0F3SUJBZ0lRUjU5eXRHbHoxMkFVQXJwaGk0MUdyVEFOQmdrcWhraUc5dzBCQVFzRkFEQVkKTVJZd0ZBWURWUVFLRXcxamJIVnpkR1Z5TG14dlkyRnNNQjRYRFRJMU1EVXhNREF5TXpZMU1Gb1hEVEkxTURVeApNVEF5TXpnMU1Gb3dBRENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNUkQrWmFqCjVzd3VPYzMwdUptcFVJbEU1bitsSE5TLzA5YWdSQXJqY2I5U05yMDEwNG9lUjAzYTgwVGIyN0IybTVFSnB3Y0cKZ2Mya3lpL3RjNDNBaEc5UlM1YUEzbGh3Q2JSYytweFdyQ2tHL2ZpOTdOenBRM2U4cjVReUZIMWV0K3pUdUlMVApQVXV2T2ZRQzdxSXY5ek9waUN2M2s2NFNLRDRSWk44aDlJa0lwYThIVEtXS0laZFZUaTdkNlVJeHdmamd3MVdFClRJVWg5dHFTL2RrTXFpdWJNdWttU3lrNkIxOVlId3F6YkZLSjI1c2xneGE1cDlzcVlsVVd2ckJVeTI4R1FJRksKUUZaVUlGWVVHZHVSaktpd3Q0K3lNWVNFWlFXVUZaT2RDNTlrRGMrcjNFQXRaYSt6OWlBd0hVZWMwZnVZQi9qaApncExLL09jbG9jMCtvVGNDQXdFQUFhT0JvakNCbnpBT0JnTlZIUThCQWY4RUJBTUNCYUF3SFFZRFZSMGxCQll3CkZBWUlLd1lCQlFVSEF3RUdDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVUKdUsxSDNEemFmU3MreXhhb0FzUCtJREFvZEpJd1B3WURWUjBSQVFIL0JEVXdNNFl4YzNCcFptWmxPaTh2WTJ4MQpjM1JsY2k1c2IyTmhiQzl1Y3k5cGMzUnBiMmx1WVdOMGFXOXVMM05oTDNkbFltRndjREFOQmdrcWhraUc5dzBCCkFRc0ZBQU9DQVFFQXNydUUyeW4xakZHMFNYeWRtOTgwVzVieDdiQ3A3ZUJ6QzQwNEloVW5MYmV1NlUvU2RsZEQKUXprTUxYZy9wbmQyRGwreFphMEJ1aUNzd1N4UmlmaDlSYVlHenNCM3dhSEVpSFBDTUExTzZYWFRSTE5nVFV4TgpWYnRzZXpid3Fzb2JRWUVRN1ZCcytzQVNqc3FHVkl3WDVRdjlEVnJxWXRmU2tQbHBzMmNqQjZYS0Q4UFBoMEluClhzbk9ESWNMUFVuSFlqeERkcHowdVlGODlab1NnNTJPUHZ1S0lidkc1NkdtV29RdkhCOTdrNDBVRmhqNmQza3AKcjBUQWhBWVY1MmN2RXFTSHdzZm9uYktLVDBrTG95N2xIeWp1TTAvcUZCYjBqU05CNWE5TThuT3R1YVZDNlQ3YgpvTlBRRFNWZmhSK1RSYzJXOEhKbVdMbEx2ajVqZFZpaWJnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJQy9UQ0NBZVdnQXdJQkFnSVJBTVkzSjV4R3pRbUJNSGxYNERrQlRKY3dEUVlKS29aSWh2Y05BUUVMQlFBdwpHREVXTUJRR0ExVUVDaE1OWTJ4MWMzUmxjaTVzYjJOaGJEQWVGdzB5TlRBMU1UQXdNakV5TXpkYUZ3MHpOVEExCk1EZ3dNakV5TXpkYU1CZ3hGakFVQmdOVkJBb1REV05zZFhOMFpYSXViRzlqWVd3d2dnRWlNQTBHQ1NxR1NJYjMKRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMmQ4anBKanZqZU9PdHZCWWVlRi9xOU5IN1NVWjUvR3hLV0ZBWApNdUF6V1g5RlVJeGhEeStnTkdzdElucHlVYTRDeXB1ZEtNR2hTOGE1S0lWN2tBeUI1Qm9OUzB6Q2pycHl3SHk2ClhYNWN4Q2c5UHBVZ1NsRTNIa2tObVAzbjlMRFg1WGUzQXpxVXdIenJVczRtS3dsblNCRkxKdjFiRDJVTUFvU24KN1lqNGlLZGtGRmxNOXRUOGxKc2hSdzFzRzAyeEh3V3VXbGVZekxXUDcrankzUVk3YlVTMitJZXU2UTZDSm5mWApFRi8zVEJIbTRUcFpreTdhTzNtYytkY2JSRnNtSWMvME9BZUNvZ0kyeW1vSmNHSUt4R1ZvRWNNRU9FUncwaERwCnZNQ0xhNTB6bnpVRGRCZkV4cmovSlpWS0JmUGcrb2lvSW1QWlA1N1NNLzJtYzJLMUFnTUJBQUdqUWpCQU1BNEcKQTFVZER3RUIvd1FFQXdJQ0JEQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUzRyVWZjUE5wOQpLejdMRnFnQ3cvNGdNQ2gwa2pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWl3d2JkczFiZytmeWZMcUN6Z3BsCnRsVDhIVjJ6L1lVakxTSHZOcTZGTGlFNnFNTXBTZkpPZG5zTnU4eURiM3d6M215U3ZvaDY2YWNKTFlCNDJyd20KNk9BSlMwWDVWWmg0WFBRbEJqc2F2djRWT1lXbngxQ1FpR1hEYW82bDF0SStCZnVET3NGZ2FLVzJxa0dpdzhSRgpiNkZzZW1kSWlWNUZ4bktvK0x6aTBHV0N4WE12SGNkVEQ1M3Y3OEVWV0FVZHpLSnRzK0VvOE5zbHVOVEJEOVpkCmJqWHA1RVRqNC9XWUxadUdGeGtyaGJRNFhlcEVxSVZmQzk1ZkxhMmV5Ym9vVFpCd2YwZkh4eXFIejA2RHhmRHgKOEYrb3NHU3pRVEF5VDliNkplWFVnQzZWT3k3Z1lsdlpMVG8vcERkNkwxTis5aCt0REJzNzNrU1Y4MXVrRVhjVApadz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
                    },
                    "privateKey": {
                        "inlineBytes": "W3JlZGFjdGVkXQ=="
                    }
                }
            }
        },
        {
            "name": "ROOTCA",
            "lastUpdated": "2025-05-10T02:38:50.403Z",
            "secret": {
                "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret",
                "name": "ROOTCA",
                "validationContext": {
                    "trustedCa": {
                        "inlineBytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvVENDQWVXZ0F3SUJBZ0lSQU1ZM0o1eEd6UW1CTUhsWDREa0JUSmN3RFFZSktvWklodmNOQVFFTEJRQXcKR0RFV01CUUdBMVVFQ2hNTlkyeDFjM1JsY2k1c2IyTmhiREFlRncweU5UQTFNVEF3TWpFeU16ZGFGdzB6TlRBMQpNRGd3TWpFeU16ZGFNQmd4RmpBVUJnTlZCQW9URFdOc2RYTjBaWEl1Ykc5allXd3dnZ0VpTUEwR0NTcUdTSWIzCkRRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQzJkOGpwSmp2amVPT3R2QlllZUYvcTlOSDdTVVo1L0d4S1dGQVgKTXVBeldYOUZVSXhoRHkrZ05Hc3RJbnB5VWE0Q3lwdWRLTUdoUzhhNUtJVjdrQXlCNUJvTlMwekNqcnB5d0h5NgpYWDVjeENnOVBwVWdTbEUzSGtrTm1QM245TERYNVhlM0F6cVV3SHpyVXM0bUt3bG5TQkZMSnYxYkQyVU1Bb1NuCjdZajRpS2RrRkZsTTl0VDhsSnNoUncxc0cwMnhId1d1V2xlWXpMV1A3K2p5M1FZN2JVUzIrSWV1NlE2Q0puZlgKRUYvM1RCSG00VHBaa3k3YU8zbWMrZGNiUkZzbUljLzBPQWVDb2dJMnltb0pjR0lLeEdWb0VjTUVPRVJ3MGhEcAp2TUNMYTUwem56VURkQmZFeHJqL0paVktCZlBnK29pb0ltUFpQNTdTTS8ybWMySzFBZ01CQUFHalFqQkFNQTRHCkExVWREd0VCL3dRRUF3SUNCREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlM0clVmY1BOcDkKS3o3TEZxZ0N3LzRnTUNoMGtqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFpd3diZHMxYmcrZnlmTHFDemdwbAp0bFQ4SFYyei9ZVWpMU0h2TnE2RkxpRTZxTU1wU2ZKT2Ruc051OHlEYjN3ejNteVN2b2g2NmFjSkxZQjQycndtCjZPQUpTMFg1VlpoNFhQUWxCanNhdnY0Vk9ZV254MUNRaUdYRGFvNmwxdEkrQmZ1RE9zRmdhS1cycWtHaXc4UkYKYjZGc2VtZElpVjVGeG5LbytMemkwR1dDeFhNdkhjZFRENTN2NzhFVldBVWR6S0p0cytFbzhOc2x1TlRCRDlaZApialhwNUVUajQvV1lMWnVHRnhrcmhiUTRYZXBFcUlWZkM5NWZMYTJleWJvb1RaQndmMGZIeHlxSHowNkR4ZkR4CjhGK29zR1N6UVRBeVQ5YjZKZVhVZ0M2Vk95N2dZbHZaTFRvL3BEZDZMMU4rOWgrdERCczcza1NWODF1a0VYY1QKWnc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t"
                    }
                }
            }
        }
    ]
}

14. Base64 인코딩된 인증서 디코딩 및 내용 출력

1
echo "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvVENDQWVXZ0F3SUJBZ0lSQU1ZM0o1eEd6UW1CTUhsWDREa0JUSmN3RFFZSktvWklodmNOQVFFTEJRQXcKR0RFV01CUUdBMVVFQ2hNTlkyeDFjM1JsY2k1c2IyTmhiREFlRncweU5UQTFNVEF3TWpFeU16ZGFGdzB6TlRBMQpNRGd3TWpFeU16ZGFNQmd4RmpBVUJnTlZCQW9URFdOc2RYTjBaWEl1Ykc5allXd3dnZ0VpTUEwR0NTcUdTSWIzCkRRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQzJkOGpwSmp2amVPT3R2QlllZUYvcTlOSDdTVVo1L0d4S1dGQVgKTXVBeldYOUZVSXhoRHkrZ05Hc3RJbnB5VWE0Q3lwdWRLTUdoUzhhNUtJVjdrQXlCNUJvTlMwekNqcnB5d0h5NgpYWDVjeENnOVBwVWdTbEUzSGtrTm1QM245TERYNVhlM0F6cVV3SHpyVXM0bUt3bG5TQkZMSnYxYkQyVU1Bb1NuCjdZajRpS2RrRkZsTTl0VDhsSnNoUncxc0cwMnhId1d1V2xlWXpMV1A3K2p5M1FZN2JVUzIrSWV1NlE2Q0puZlgKRUYvM1RCSG00VHBaa3k3YU8zbWMrZGNiUkZzbUljLzBPQWVDb2dJMnltb0pjR0lLeEdWb0VjTUVPRVJ3MGhEcAp2TUNMYTUwem56VURkQmZFeHJqL0paVktCZlBnK29pb0ltUFpQNTdTTS8ybWMySzFBZ01CQUFHalFqQkFNQTRHCkExVWREd0VCL3dRRUF3SUNCREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlM0clVmY1BOcDkKS3o3TEZxZ0N3LzRnTUNoMGtqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFpd3diZHMxYmcrZnlmTHFDemdwbAp0bFQ4SFYyei9ZVWpMU0h2TnE2RkxpRTZxTU1wU2ZKT2Ruc051OHlEYjN3ejNteVN2b2g2NmFjSkxZQjQycndtCjZPQUpTMFg1VlpoNFhQUWxCanNhdnY0Vk9ZV254MUNRaUdYRGFvNmwxdEkrQmZ1RE9zRmdhS1cycWtHaXc4UkYKYjZGc2VtZElpVjVGeG5LbytMemkwR1dDeFhNdkhjZFRENTN2NzhFVldBVWR6S0p0cytFbzhOc2x1TlRCRDlaZApialhwNUVUajQvV1lMWnVHRnhrcmhiUTRYZXBFcUlWZkM5NWZMYTJleWJvb1RaQndmMGZIeHlxSHowNkR4ZkR4CjhGK29zR1N6UVRBeVQ5YjZKZVhVZ0M2Vk95N2dZbHZaTFRvL3BEZDZMMU4rOWgrdERCczcza1NWODF1a0VYY1QKWnc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t" | base64 -d  | openssl x509 -in /dev/stdin -text -noout

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            c6:37:27:9c:46:cd:09:81:30:79:57:e0:39:01:4c:97
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O=cluster.local
        Validity
            Not Before: May 10 02:12:37 2025 GMT
            Not After : May  8 02:12:37 2035 GMT
        Subject: O=cluster.local
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:b6:77:c8:e9:26:3b:e3:78:e3:ad:bc:16:1e:78:
                    5f:ea:f4:d1:fb:49:46:79:fc:6c:4a:58:50:17:32:
                    e0:33:59:7f:45:50:8c:61:0f:2f:a0:34:6b:2d:22:
                    7a:72:51:ae:02:ca:9b:9d:28:c1:a1:4b:c6:b9:28:
                    85:7b:90:0c:81:e4:1a:0d:4b:4c:c2:8e:ba:72:c0:
                    7c:ba:5d:7e:5c:c4:28:3d:3e:95:20:4a:51:37:1e:
                    49:0d:98:fd:e7:f4:b0:d7:e5:77:b7:03:3a:94:c0:
                    7c:eb:52:ce:26:2b:09:67:48:11:4b:26:fd:5b:0f:
                    65:0c:02:84:a7:ed:88:f8:88:a7:64:14:59:4c:f6:
                    d4:fc:94:9b:21:47:0d:6c:1b:4d:b1:1f:05:ae:5a:
                    57:98:cc:b5:8f:ef:e8:f2:dd:06:3b:6d:44:b6:f8:
                    87:ae:e9:0e:82:26:77:d7:10:5f:f7:4c:11:e6:e1:
                    3a:59:93:2e:da:3b:79:9c:f9:d7:1b:44:5b:26:21:
                    cf:f4:38:07:82:a2:02:36:ca:6a:09:70:62:0a:c4:
                    65:68:11:c3:04:38:44:70:d2:10:e9:bc:c0:8b:6b:
                    9d:33:9f:35:03:74:17:c4:c6:b8:ff:25:95:4a:05:
                    f3:e0:fa:88:a8:22:63:d9:3f:9e:d2:33:fd:a6:73:
                    62:b5
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Certificate Sign
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Key Identifier: 
                B8:AD:47:DC:3C:DA:7D:2B:3E:CB:16:A8:02:C3:FE:20:30:28:74:92
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        8b:0c:1b:76:cd:5b:83:e7:f2:7c:ba:82:ce:0a:65:b6:54:fc:
        1d:5d:b3:fd:85:23:2d:21:ef:36:ae:85:2e:21:3a:a8:c3:29:
        49:f2:4e:76:7b:0d:bb:cc:83:6f:7c:33:de:6c:92:be:88:7a:
        e9:a7:09:2d:80:78:da:bc:26:e8:e0:09:4b:45:f9:55:98:78:
        5c:f4:25:06:3b:1a:be:fe:15:39:85:a7:c7:50:90:88:65:c3:
        6a:8e:a5:d6:d2:3e:05:fb:83:3a:c1:60:68:a5:b6:aa:41:a2:
        c3:c4:45:6f:a1:6c:7a:67:48:89:5e:45:c6:72:a8:f8:bc:e2:
        d0:65:82:c5:73:2f:1d:c7:53:0f:9d:ef:ef:c1:15:58:05:1d:
        cc:a2:6d:b3:e1:28:f0:db:25:b8:d4:c1:0f:d6:5d:6e:35:e9:
        e4:44:e3:e3:f5:98:2d:9b:86:17:19:2b:85:b4:38:5d:ea:44:
        a8:85:5f:0b:de:5f:2d:ad:9e:c9:ba:28:4d:90:70:7f:47:c7:
        c7:2a:87:cf:4e:83:c5:f0:f1:f0:5f:a8:b0:64:b3:41:30:32:
        4f:d6:fa:25:e5:d4:80:2e:95:3b:2e:e0:62:5b:d9:2d:3a:3f:
        a4:37:7a:2f:53:7e:f6:1f:ad:0c:1b:3b:de:44:95:f3:5b:a4:
        11:77:13:67

15. Istio 루트 인증서 파일 확인

1
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- ls -l /var/run/secrets/istio

✅ 출력

1
2
total 0
lrwxrwxrwx 1 root root 20 May 10 02:38 root-cert.pem -> ..data/root-cert.pem

16. Istio 토큰 파일 확인

1
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- ls -l /var/run/secrets/tokens

✅ 출력

1
2
total 0
lrwxrwxrwx 1 root root 18 May 10 02:38 istio-token -> ..data/istio-token

17. Istio 토큰 출력 및 환경변수 할당

1
2
kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- cat /var/run/secrets/tokens/istio-token
TOKEN=$(kubectl exec -it -n istioinaction deploy/webapp -c istio-proxy -- cat /var/run/secrets/tokens/istio-token)

✅ 출력

1
eyJhbGciOiJSUzI1NiIsImtpZCI6Im91bHpURE8zdXRqMmJLNFB4VHctU2FXYnh5aklCUE5tX0VDMGZFNmpxV1UifQ.eyJhdWQiOlsiaXN0aW8tY2EiXSwiZXhwIjoxNzQ2ODg3OTEyLCJpYXQiOjE3NDY4NDQ3MTIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJpc3Rpb2luYWN0aW9uIiwicG9kIjp7Im5hbWUiOiJ3ZWJhcHAtNzY4NWJjYjg0LTdncnM5IiwidWlkIjoiYWMzNzE5MDAtNmFjZS00ODkzLWIxMzQtZDNjZmUyZTRhYzRlIn0sInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJ3ZWJhcHAiLCJ1aWQiOiJlNjdiMGJiYy01YjlhLTRmYmQtYTMzYi05ODE5OGMwYzU5MWEifX0sIm5iZiI6MTc0Njg0NDcxMiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmlzdGlvaW5hY3Rpb246d2ViYXBwIn0.Tt2xGvgW96zL8zxIM2pKEzsxbwDkXEe_OX0Ar2YNWcDnzzAkhM7LDDSPJvqA0eQtc9FigCMxl-O5A56EjYN7BvxOvwngOZYYR85HB4zoLBvUMNsKddvPCJInAhGWlKHCfoZ7RORVehlwCdz86vXGXI8bqpBo79uGt9OJTRKrDnSk7OhsUEv4POUVuX6aIuBVFYORnFaFXzHvtAqjx8duK2exrgTkZiJcL7329Q22e9xBYYfKF484nak1fhx8Q1BTGK-5RCTJgRA1hTd8cx6gWwPuhZ7AQ3pavm4RyNuS_dFYvJ_viCkw8Y4VOoLpfqZvILijzHHQICYeBi1x19Bokw

18. JWT 토큰 디코딩하여 클레임 확인

1
jwt decode $TOKEN

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Token header
------------
{
  "alg": "RS256",
  "kid": "oulzTDO3utj2bK4PxTw-SaWbxyjIBPNm_EC0fE6jqWU"
}

Token claims
------------
{
  "aud": [
    "istio-ca"
  ],
  "exp": 1746887912,
  "iat": 1746844712,
  "iss": "https://kubernetes.default.svc.cluster.local",
  "kubernetes.io": {
    "namespace": "istioinaction",
    "pod": {
      "name": "webapp-7685bcb84-7grs9",
      "uid": "ac371900-6ace-4893-b134-d3cfe2e4ac4e"
    },
    "serviceaccount": {
      "name": "webapp",
      "uid": "e67b0bbc-5b9a-4fbd-a33b-98198c0c591a"
    }
  },
  "nbf": 1746844712,
  "sub": "system:serviceaccount:istioinaction:webapp"
}

🧾 RequestAuthentication 리소스로 수집한 메타데이터

1. Envoy RBAC 디버그 로그 활성화

1
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/istio-ingressgateway -n istio-system --level rbac:debug

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
istio-ingressgateway-6bb8fb6549-dq7gl.istio-system:
active loggers:
  admin: warning
  alternate_protocols_cache: warning
  aws: warning
  assert: warning
  backtrace: warning
  cache_filter: warning
  client: warning
  config: warning
  connection: warning
  conn_handler: warning
  decompression: warning
  dns: warning
  dubbo: warning
  envoy_bug: warning
  ext_authz: warning
  ext_proc: warning
  rocketmq: warning
  file: warning
  filter: warning
  forward_proxy: warning
  grpc: warning
  happy_eyeballs: warning
  hc: warning
  health_checker: warning
  http: warning
  http2: warning
  hystrix: warning
  init: warning
  io: warning
  jwt: warning
  kafka: warning
  key_value_store: warning
  lua: warning
  main: warning
  matcher: warning
  misc: error
  mongo: warning
  multi_connection: warning
  oauth2: warning
  quic: warning
  quic_stream: warning
  pool: warning
  rate_limit_quota: warning
  rbac: debug
  rds: warning
  redis: warning
  router: warning
  runtime: warning
  stats: warning
  secret: warning
  tap: warning
  testing: warning
  thrift: warning
  tracing: warning
  upstream: warning
  udp: warning
  wasm: warning
  websocket: warning

2. webapp과 catalog 서비스 및 게이트웨이 설정

1
2
3
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction
kubectl apply -f services/webapp/istio/webapp-catalog-gw-vs.yaml -n istioinaction

✅ 출력

1
2
3
4
5
6
7
8
serviceaccount/catalog unchanged
service/catalog unchanged
deployment.apps/catalog unchanged
serviceaccount/webapp unchanged
service/webapp unchanged
deployment.apps/webapp unchanged
gateway.networking.istio.io/coolstore-gateway unchanged
virtualservice.networking.istio.io/webapp-virtualservice unchanged

3. RequestAuthentication 및 AuthorizationPolicy 리소스 생성

1
2
3
4
5
6
kubectl apply -f ch9/enduser/jwt-token-request-authn.yaml
kubectl apply -f ch9/enduser/allow-all-with-jwt-to-webapp.yaml

# 결과
requestauthentication.security.istio.io/jwt-token-request-authn created
authorizationpolicy.security.istio.io/allow-all-with-jwt-to-webapp created

4. 생성된 RequestAuthentication 및 AuthorizationPolicy 리소스 확인

1
kubectl get requestauthentication,authorizationpolicy -A

✅ 출력

1
2
3
4
5
NAMESPACE      NAME                                                              AGE
istio-system   requestauthentication.security.istio.io/jwt-token-request-authn   2m33s

NAMESPACE      NAME                                                                 AGE
istio-system   authorizationpolicy.security.istio.io/allow-all-with-jwt-to-webapp   2m32s

5. Istio 인그레스 게이트웨이 로그 확인

1
kubectl logs -n istio-system -l app=istio-ingressgateway -f

✅ 출력

1
2
3
4
5
6
7
8
9
10
2025-05-10T02:12:48.407103Z	info	Envoy proxy is ready
2025-05-10T02:42:25.603179Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T03:11:38.257986Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T03:44:32.327476Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T04:14:17.344662Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T04:46:22.202545Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T05:15:58.920977Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T05:48:58.863785Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T06:18:16.636536Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T06:45:35.030836Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012

6. admin 토큰을 사용한 요청 전송 및 응답 코드 확인

1
2
3
4
ADMIN_TOKEN=$(< ch9/enduser/admin.jwt)

curl -H "Authorization: Bearer $ADMIN_TOKEN" \
     -sSl -o /dev/null -w "%{http_code}\n" webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
403

7. 필터 메타데이터를 통한 JWT 클레임 및 인증 정보 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
2025-05-10T07:09:50.570107Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:52228, directRemoteIP: 172.18.0.1:52228, remoteIP: 172.18.0.1:52228,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', '2e82093b-7096-9683-b861-34c01f811efe'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145071
            }
          }
          fields {
            key: "group"
            value {
              string_value: "admin"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545071
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "admin"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
[2025-05-10T07:09:50.569Z] "GET /api/catalog HTTP/1.1" 403 - rbac_access_denied_matched_policy[none] - "-" 0 19 0 - "172.18.0.1" "curl/8.13.0" "2e82093b-7096-9683-b861-34c01f811efe" "webapp.istioinaction.io:30000" "-" outbound|80||webapp.istioinaction.svc.cluster.local - 10.10.0.6:8080 172.18.0.1:52228 - -
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/218d3fb9-4628-4d20-943c-124281c80e7b"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"exp\":4745145071,\"sub\":\"218d3fb9-4628-4d20-943c-124281c80e7b\",\"group\":\"admin\",\"iss\":\"auth@istioinaction.io\",\"iat\":1591545071}"
      }
    }
  }
}
	thread=45
2025-05-10T07:09:50.570151Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:158	enforced denied, matched policy none	thread=45

8. RequestAuthentication 및 AuthorizationPolicy 리소스 삭제

1
2
3
4
5
6
kubectl delete -f ch9/enduser/jwt-token-request-authn.yaml
kubectl delete -f ch9/enduser/allow-all-with-jwt-to-webapp.yaml

# 결과
requestauthentication.security.istio.io "jwt-token-request-authn" deleted
authorizationpolicy.security.istio.io "allow-all-with-jwt-to-webapp" deleted

🔀 서비스 간 트래픽 인가하기

1. 실습 환경 구성 및 서비스 배포

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
kubectl -n istioinaction apply -f services/catalog/kubernetes/catalog.yaml
kubectl -n istioinaction apply -f services/webapp/kubernetes/webapp.yaml 
kubectl -n istioinaction apply -f services/webapp/istio/webapp-catalog-gw-vs.yaml
kubectl -n default apply -f ch9/sleep.yaml

# 결과
serviceaccount/catalog unchanged
service/catalog unchanged
deployment.apps/catalog unchanged
serviceaccount/webapp unchanged
service/webapp unchanged
deployment.apps/webapp unchanged
gateway.networking.istio.io/coolstore-gateway unchanged
virtualservice.networking.istio.io/webapp-virtualservice unchanged
serviceaccount/sleep unchanged
service/sleep unchanged
deployment.apps/sleep unchanged

2. 게이트웨이 및 가상 서비스 리소스 확인

1
kubectl -n istioinaction get gw,vs

✅ 출력

1
2
3
4
5
NAME                                            AGE
gateway.networking.istio.io/coolstore-gateway   4h39m

NAME                                                       GATEWAYS                HOSTS                         AGE
virtualservice.networking.istio.io/webapp-virtualservice   ["coolstore-gateway"]   ["webapp.istioinaction.io"]   4h39m

3. 메시 전역 PeerAuthentication 리소스 설정 (STRICT)

1
cat ch9/meshwide-strict-peer-authn.yaml

✅ 출력

1
2
3
4
5
6
7
8
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "default"
  namespace: "istio-system"
spec:
  mtls:
    mode: STRICT
1
2
3
4
kubectl -n istio-system apply -f ch9/meshwide-strict-peer-authn.yaml

# 결과
peerauthentication.security.istio.io/default unchanged

4. 메시 수준 PeerAuthentication 리소스 적용 여부 확인

1
kubectl get peerauthentication -n istio-system

✅ 출력

1
2
NAME      MODE     AGE
default   STRICT   4h16m

5. webapp 워크로드용 PeerAuthentication 리소스 정의 확인

1
cat ch9/workload-permissive-peer-authn.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "webapp"
  namespace: "istioinaction"
spec:
  selector:
    matchLabels:
      app: webapp 
  mtls:
    mode: PERMISSIVE

6. PeerAuthentication 재적용 및 STRICT 모드 유지 확인

1
2
kubectl -n istio-system apply -f ch9/meshwide-strict-peer-authn.yaml
kubectl get peerauthentication -n istio-system

✅ 출력

1
2
3
4
peerauthentication.security.istio.io/default unchanged

NAME      MODE     AGE
default   STRICT   4h17m

🔍 워크로드에 정책 적용 시 동작 확인

1. AuthorizationPolicy 리소스 정의 파일 확인

1
cat ch9/allow-catalog-requests-in-web-app.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "allow-catalog-requests-in-web-app"
  namespace: istioinaction
spec:
  selector:
    matchLabels:
      app: webapp
  rules:
  - to:
    - operation:
        paths: ["/api/catalog*"]
  action: ALLOW
  • webapp 으로의 요청 중 HTTP 경로에 /api/catalog* 가 포함된 것을 허용

2. webapp 사이드카 로그 확인

1
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f

✅ 출력

1
2
3
4
5
6
7
8
9
10
[2025-05-10T03:38:57.883Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 11 11 "-" "curl/8.5.0" "d7771cb6-c6f2-908f-8753-8e36ca80913d" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:38521 10.10.0.12:8080 10.10.0.14:50484 - default
[2025-05-10T03:41:56.344Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 2 2 "-" "beegoServer" "ca254d68-09c2-92fc-abf6-14c7a9e47dbf" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:60838 10.200.1.219:80 10.10.0.12:39424 - default
[2025-05-10T03:41:56.343Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 4 4 "-" "curl/8.5.0" "ca254d68-09c2-92fc-abf6-14c7a9e47dbf" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:57585 10.10.0.12:8080 10.10.0.14:45782 - default
2025-05-10T04:06:54.976916Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T04:38:18.224230Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T05:08:11.339775Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T05:37:45.692088Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T06:05:04.783910Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T06:35:53.880010Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
2025-05-10T07:04:39.794768Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012

3. 정책 적용 전 정상 접근 테스트 (/api/catalog)

1
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/api/catalog

✅ 출력

1
[{"id":1,"color":"amber","department":"Eyewear","name":"Elinor Glasses","price":"282.00"},{"id":2,"color":"cyan","department":"Clothing","name":"Atlas Shirt","price":"127.00"},{"id":3,"color":"teal","department":"Clothing","name":"Small Metal Shoes","price":"232.00"},{"id":4,"color":"red","department":"Watches","name":"Red Dragon Watch","price":"232.00"}]
1
2
[2025-05-10T07:25:25.587Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 3 2 "-" "beegoServer" "48bfdf72-1629-9880-a93a-59b7dfc2ca5d" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:57388 10.200.1.219:80 10.10.0.12:43878 - default
[2025-05-10T07:25:25.585Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 5 4 "-" "curl/8.5.0" "48bfdf72-1629-9880-a93a-59b7dfc2ca5d" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:48863 10.10.0.12:8080 10.10.0.14:50996 - default

4. 정책 적용 전 존재하지 않는 엔드포인트 요청 테스트 (/hello/world)

1
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/hello/world

✅ 출력

1
2
3
...
<h1>Not Found</h1>
...
1
[2025-05-10T07:26:46.829Z] "GET /hello/world HTTP/1.1" 404 - via_upstream - "-" 0 2000 0 0 "-" "curl/8.5.0" "1c4bff43-d66d-9967-b825-73462fdd8f9b" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:48863 10.10.0.12:8080 10.10.0.14:34686 - default

5. AuthorizationPolicy 리소스 적용

1
2
3
4
kubectl apply -f ch9/allow-catalog-requests-in-web-app.yaml

# 결과
authorizationpolicy.security.istio.io/allow-catalog-requests-in-web-app created

6. 적용된 AuthorizationPolicy 리소스 확인

1
kubectl get authorizationpolicy -n istioinaction

✅ 출력

1
2
NAME                                AGE
allow-catalog-requests-in-web-app   19s

7. 프록시 리스너 설정 확인 (포트 15006)

1
docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/webapp.istioinaction --port 15006

✅ 출력

1
2
3
4
5
6
7
8
9
ADDRESS PORT  MATCH                                                                                           DESTINATION
0.0.0.0 15006 Addr: *:15006                                                                                   Non-HTTP/Non-TCP
0.0.0.0 15006 Trans: tls; App: istio-http/1.0,istio-http/1.1,istio-h2; Addr: 0.0.0.0/0                        InboundPassthroughClusterIpv4
0.0.0.0 15006 Trans: raw_buffer; App: http/1.1,h2c; Addr: 0.0.0.0/0                                           InboundPassthroughClusterIpv4
0.0.0.0 15006 Trans: tls; App: TCP TLS; Addr: 0.0.0.0/0                                                       InboundPassthroughClusterIpv4
0.0.0.0 15006 Trans: raw_buffer; Addr: 0.0.0.0/0                                                              InboundPassthroughClusterIpv4
0.0.0.0 15006 Trans: tls; Addr: 0.0.0.0/0                                                                     InboundPassthroughClusterIpv4
0.0.0.0 15006 Trans: tls; App: istio,istio-peer-exchange,istio-http/1.0,istio-http/1.1,istio-h2; Addr: *:8080 Cluster: inbound|8080||
0.0.0.0 15006 Trans: raw_buffer; Addr: *:8080                                                                 Cluster: inbound|8080||

8. webapp 프록시의 RBAC 로그 레벨 디버그로 변경

1
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/webapp -n istioinaction --level rbac:debug

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
webapp-7685bcb84-7grs9.istioinaction:
active loggers:
  admin: warning
  alternate_protocols_cache: warning
  aws: warning
  assert: warning
  backtrace: warning
  cache_filter: warning
  client: warning
  config: warning
  connection: warning
  conn_handler: warning
  decompression: warning
  dns: warning
  dubbo: warning
  envoy_bug: warning
  ext_authz: warning
  ext_proc: warning
  rocketmq: warning
  file: warning
  filter: warning
  forward_proxy: warning
  grpc: warning
  happy_eyeballs: warning
  hc: warning
  health_checker: warning
  http: warning
  http2: warning
  hystrix: warning
  init: warning
  io: warning
  jwt: warning
  kafka: warning
  key_value_store: warning
  lua: warning
  main: warning
  matcher: warning
  misc: error
  mongo: warning
  multi_connection: warning
  oauth2: warning
  quic: warning
  quic_stream: warning
  pool: warning
  rate_limit_quota: warning
  rbac: debug
  rds: warning
  redis: warning
  router: warning
  runtime: warning
  stats: warning
  secret: warning
  tap: warning
  testing: warning
  thrift: warning
  tracing: warning
  upstream: warning
  udp: warning
  wasm: warning
  websocket: warning

9. 정책 적용 후 /api/catalog 요청 허용 확인

1
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/api/catalog

✅ 출력

1
[{"id":1,"color":"amber","department":"Eyewear","name":"Elinor Glasses","price":"282.00"},{"id":2,"color":"cyan","department":"Clothing","name":"Atlas Shirt","price":"127.00"},{"id":3,"color":"teal","department":"Clothing","name":"Small Metal Shoes","price":"232.00"},{"id":4,"color":"red","department":"Watches","name":"Red Dragon Watch","price":"232.00"}]
1
2
3
4
5
6
7
8
9
10
11
12
2025-05-10T07:33:01.365398Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 10.10.0.14:46444, directRemoteIP: 10.10.0.14:46444, remoteIP: 10.10.0.14:46444,localAddress: 10.10.0.12:8080, ssl: none, headers: ':authority', 'webapp.istioinaction'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', 'aef6a345-5c28-9282-a295-c99950178dd3'
, dynamicMetadata: 	thread=42
2025-05-10T07:33:01.365430Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy ns[istioinaction]-policy[allow-catalog-requests-in-web-app]-rule[0]	thread=42
[2025-05-10T07:33:01.366Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 2 1 "-" "beegoServer" "aef6a345-5c28-9282-a295-c99950178dd3" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:57388 10.200.1.219:80 10.10.0.12:45312 - default
[2025-05-10T07:33:01.365Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 4 3 "-" "curl/8.5.0" "aef6a345-5c28-9282-a295-c99950178dd3" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:45921 10.10.0.12:8080 10.10.0.14:46444 - default

10. 정책 적용 후 /hello/world 요청 차단(RBAC 403) 확인

1
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/hello/world

✅ 출력

1
RBAC: access denied
1
2
3
4
5
6
7
8
9
10
11
2025-05-10T07:35:24.075382Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 10.10.0.14:49910, directRemoteIP: 10.10.0.14:49910, remoteIP: 10.10.0.14:49910,localAddress: 10.10.0.12:8080, ssl: none, headers: ':authority', 'webapp.istioinaction'
':path', '/hello/world'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', 'bf652bcd-653f-90d5-a766-8bb240c31629'
, dynamicMetadata: 	thread=41
2025-05-10T07:35:24.075409Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:158	enforced denied, matched policy none	thread=41
[2025-05-10T07:35:24.075Z] "GET /hello/world HTTP/1.1" 403 - rbac_access_denied_matched_policy[none] - "-" 0 19 0 - "-" "curl/8.5.0" "bf652bcd-653f-90d5-a766-8bb240c31629" "webapp.istioinaction" "-" inbound|8080|| - 10.10.0.12:8080 10.10.0.14:49910 - -

11. 다음 실습을 위한 AuthorizationPolicy 리소스 삭제

1
2
3
4
kubectl delete -f ch9/allow-catalog-requests-in-web-app.yaml

# 결과
authorizationpolicy.security.istio.io "allow-catalog-requests-in-web-app" deleted

🚫 전체 정책으로 기본적으로 모든 요청 거부하기

1. 메시 전역 요청 차단을 위한 AuthorizationPolicy 정의 확인

1
cat ch9/policy-deny-all-mesh.yaml

✅ 출력

1
2
3
4
5
6
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: istio-system
spec: {}

2. 차단 정책 적용 전 서비스 정상 응답 확인 (내부 요청)

1
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/api/catalog

✅ 출력

1
2
[{"id":1,"color":"amber","department":"Eyewear","name":"Elinor Glasses","price":"282.00"},{"id":2,"color":"cyan","department":"Clothing","name":"Atlas Shirt","price":"127.00"},{"id":3,"color":"teal","department":"Clothing","name":"Small Metal Shoes","price":"232.00"},{"id":4,"color":"red","department":"Watches","name":"Red Dragon Watch","price":"232.00"}]

3. 차단 정책 적용 전 서비스 정상 응답 확인 (외부 요청)

1
curl -s http://webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
[{"id":1,"color":"amber","department":"Eyewear","name":"Elinor Glasses","price":"282.00"},{"id":2,"color":"cyan","department":"Clothing","name":"Atlas Shirt","price":"127.00"},{"id":3,"color":"teal","department":"Clothing","name":"Small Metal Shoes","price":"232.00"},{"id":4,"color":"red","department":"Watches","name":"Red Dragon Watch","price":"232.00"}]

4. 메시 전역 요청 차단 정책 적용

1
2
3
4
kubectl apply -f ch9/policy-deny-all-mesh.yaml

# 결과
authorizationpolicy.security.istio.io/deny-all created

5. 적용된 AuthorizationPolicy 리소스 목록 확인

1
kubectl get authorizationpolicy -A

✅ 출력

1
2
NAMESPACE       NAME                                AGE
istio-system    deny-all                            0s

6. 정책 적용 후 내부 요청 차단(RBAC 403) 확인

1
2
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/api/catalog

✅ 출력

1
RBAC: access denied
1
2
3
4
5
6
7
8
9
10
11
2025-05-10T07:46:57.684937Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 10.10.0.14:39862, directRemoteIP: 10.10.0.14:39862, remoteIP: 10.10.0.14:39862,localAddress: 10.10.0.12:8080, ssl: none, headers: ':authority', 'webapp.istioinaction'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', 'cb5d2686-d454-94e7-ae5a-2390e952d00e'
, dynamicMetadata: 	thread=41
2025-05-10T07:46:57.684959Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:158	enforced denied, matched policy none	thread=41
[2025-05-10T07:46:57.684Z] "GET /api/catalog HTTP/1.1" 403 - rbac_access_denied_matched_policy[none] - "-" 0 19 0 - "-" "curl/8.5.0" "cb5d2686-d454-94e7-ae5a-2390e952d00e" "webapp.istioinaction" "-" inbound|8080|| - 10.10.0.12:8080 10.10.0.14:39862 - -

7. 정책 적용 후 외부 요청 차단(RBAC 403) 확인

1
2
kubectl logs -n istio-system -l app=istio-ingressgateway -f
curl -s http://webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
RBAC: access denied
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2025-05-10T07:48:48.001798Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:36992, directRemoteIP: 172.18.0.1:36992, remoteIP: 172.18.0.1:36992,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', '33a4ad7a-d81a-9a01-91a2-15c8bd34fb4b'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: 	thread=41
2025-05-10T07:48:48.001826Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:158	enforced denied, matched policy none	thread=41
[2025-05-10T07:48:48.001Z] "GET /api/catalog HTTP/1.1" 403 - rbac_access_denied_matched_policy[none] - "-" 0 19 0 - "172.18.0.1" "curl/8.13.0" "33a4ad7a-d81a-9a01-91a2-15c8bd34fb4b" "webapp.istioinaction.io:30000" "-" outbound|80||webapp.istioinaction.svc.cluster.local - 10.10.0.6:8080 172.18.0.1:36992 - -

🎯 특정 네임스페이스에서 온 요청 허용하기

1. 특정 네임스페이스 요청 허용을 위한 AuthorizationPolicy 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cat << EOF | kubectl apply -f -
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "webapp-allow-view-default-ns"
  namespace: istioinaction # istioinaction의 워크로드
spec:
  rules:
  - from: # default 네임스페이스에서 시작한
    - source:
        namespaces: ["default"]
    to:   # HTTP GET 요청에만 적용 
    - operation:
        methods: ["GET"]
EOF

# 결과
authorizationpolicy.security.istio.io/webapp-allow-view-default-ns created

2. AuthorizationPolicy 리소스 생성 여부 확인

1
kubectl get AuthorizationPolicy -A

✅ 출력

1
2
3
NAMESPACE       NAME                           AGE
istio-system    deny-all                       8m52s
istioinaction   webapp-allow-view-default-ns   0s

3. 기존 sleep 파드에서 /api/catalog 호출 (허용되지 않음)

1
2
3
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f

kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/api/catalog

✅ 출력

1
RBAC: access denied
1
2
3
4
5
6
7
8
9
10
11
2025-05-10T07:54:26.684502Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 10.10.0.14:36902, directRemoteIP: 10.10.0.14:36902, remoteIP: 10.10.0.14:36902,localAddress: 10.10.0.12:8080, ssl: none, headers: ':authority', 'webapp.istioinaction'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', 'f8e96c29-5be5-9a8e-9b0e-0af4e56e2b11'
, dynamicMetadata: 	thread=41
2025-05-10T07:54:26.684529Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:158	enforced denied, matched policy none	thread=41
[2025-05-10T07:54:26.684Z] "GET /api/catalog HTTP/1.1" 403 - rbac_access_denied_matched_policy[none] - "-" 0 19 0 - "-" "curl/8.5.0" "f8e96c29-5be5-9a8e-9b0e-0af4e56e2b11" "webapp.istioinaction" "-" inbound|8080|| - 10.10.0.12:8080 10.10.0.14:36902 - -

4. sleep 파드 재배포 전 default 네임스페이스에 사이드카 자동 주입 활성화

1
2
3
4
5
6
kubectl label ns default istio-injection=enabled
kubectl delete pod -l app=sleep

# 결과
namespace/default labeled
pod "sleep-6f8cfb8c8f-ckxzx" deleted

5. 프록시 상태 확인 (sleep 포함)

1
docker exec -it myk8s-control-plane istioctl proxy-status

✅ 출력

1
2
3
4
5
6
NAME                                                   CLUSTER        CDS        LDS        EDS        RDS          ECDS         ISTIOD                    VERSION
catalog-6cf4b97d-bj4lh.istioinaction                   Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-5cxpq     1.17.8
istio-egressgateway-85df6b84b7-fvmpz.istio-system      Kubernetes     SYNCED     SYNCED     SYNCED     NOT SENT     NOT SENT     istiod-8d74787f-5cxpq     1.17.8
istio-ingressgateway-6bb8fb6549-dq7gl.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-5cxpq     1.17.8
sleep-6f8cfb8c8f-gmlsm.default                         Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-5cxpq     1.17.8
webapp-7685bcb84-7grs9.istioinaction                   Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-5cxpq     1.17.8

6. sleep 파드 재생성 확인

1
k get pod

✅ 출력

1
2
NAME                     READY   STATUS    RESTARTS   AGE
sleep-6f8cfb8c8f-gmlsm   2/2     Running   0          82s

7. default 네임스페이스에서 webapp 루트 호출 성공 확인

1
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
<div class="content-wrapper wrapper">
  <section class="hero is-landing is-large">
    <div class="hero-head">
      <nav class="navbar">
        <div class  ="container">
          <div class="navbar-brand">
            <a class="navbar-item">
              Istio in Action
            </a>
          </div>
        </div>
      </nav>
    </div>
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2025-05-10T08:02:32.269242Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: outbound_.80_._.webapp.istioinaction.svc.cluster.local, sourceIP: 10.10.0.15:59486, directRemoteIP: 10.10.0.15:59486, remoteIP: 10.10.0.15:59486,localAddress: 10.10.0.12:8080, ssl: uriSanPeerCertificate: spiffe://cluster.local/ns/default/sa/sleep, dnsSanPeerCertificate: , subjectPeerCertificate: , headers: ':authority', 'webapp.istioinaction'
':path', '/'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', '92f47e8b-7a89-9725-b51f-b56ffb78df45'
'x-envoy-attempt-count', '1'
'x-b3-traceid', '0764967d60d276de2a2adb593af33fd6'
'x-b3-spanid', '2a2adb593af33fd6'
'x-b3-sampled', '1'
'x-forwarded-client-cert', 'By=spiffe://cluster.local/ns/istioinaction/sa/webapp;Hash=1cf61144706e9f657691938946a7a44048b7db487c1db0210e6aaad6a7f7226c;Subject="";URI=spiffe://cluster.local/ns/default/sa/sleep'
, dynamicMetadata: 	thread=42
2025-05-10T08:02:32.269273Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy ns[istioinaction]-policy[webapp-allow-view-default-ns]-rule[0]	thread=42
[2025-05-10T08:02:32.270Z] "GET /items HTTP/1.1" 403 - via_upstream - "-" 0 19 0 0 "-" "beegoServer" "92f47e8b-7a89-9725-b51f-b56ffb78df45" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:54610 10.200.1.219:80 10.10.0.12:48822 - default
[2025-05-10T08:02:32.269Z] "GET / HTTP/1.1" 200 - via_upstream - "-" 0 4527 24 24 "-" "curl/8.5.0" "92f47e8b-7a89-9725-b51f-b56ffb78df45" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:45921 10.10.0.12:8080 10.10.0.15:59486 outbound_.80_._.webapp.istioinaction.svc.cluster.local default

8. /api/catalog 호출 시 내부적으로 catalog 서비스 차단 확인 (500 응답)

1
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/api/catalog

✅ 출력

1
error calling Catalog service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2025-05-10T08:04:00.365589Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: outbound_.80_._.webapp.istioinaction.svc.cluster.local, sourceIP: 10.10.0.15:49234, directRemoteIP: 10.10.0.15:49234, remoteIP: 10.10.0.15:49234,localAddress: 10.10.0.12:8080, ssl: uriSanPeerCertificate: spiffe://cluster.local/ns/default/sa/sleep, dnsSanPeerCertificate: , subjectPeerCertificate: , headers: ':authority', 'webapp.istioinaction'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', '42747aca-8e80-97e3-90dc-8f97c935550c'
'x-envoy-attempt-count', '1'
'x-b3-traceid', '767c3b449ffc9381dc4c7aac76967cd1'
'x-b3-spanid', 'dc4c7aac76967cd1'
'x-b3-sampled', '1'
'x-forwarded-client-cert', 'By=spiffe://cluster.local/ns/istioinaction/sa/webapp;Hash=1cf61144706e9f657691938946a7a44048b7db487c1db0210e6aaad6a7f7226c;Subject="";URI=spiffe://cluster.local/ns/default/sa/sleep'
, dynamicMetadata: 	thread=41
2025-05-10T08:04:00.365625Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy ns[istioinaction]-policy[webapp-allow-view-default-ns]-rule[0]	thread=41
[2025-05-10T08:04:00.366Z] "GET /items HTTP/1.1" 403 - via_upstream - "-" 0 19 0 0 "-" "beegoServer" "42747aca-8e80-97e3-90dc-8f97c935550c" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:51000 10.200.1.219:80 10.10.0.12:43946 - default
[2025-05-10T08:04:00.365Z] "GET /api/catalog HTTP/1.1" 500 - via_upstream - "-" 0 29 2 2 "-" "curl/8.5.0" "42747aca-8e80-97e3-90dc-8f97c935550c" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:48863 10.10.0.12:8080 10.10.0.15:49234 outbound_.80_._.webapp.istioinaction.svc.cluster.local default

9. catalog 서비스 직접 호출 성공 여부 확인

1
2
kubectl logs -n istioinaction -l app=catalog -c istio-proxy -f
kubectl exec deploy/sleep -- curl -sSL catalog.istioinaction/items

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]
1
[2025-05-10T08:05:37.740Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 2 2 "-" "curl/8.5.0" "b2813c80-e8ff-931c-8185-20b63537b963" "catalog.istioinaction" "10.10.0.13:3000" inbound|3000|| 127.0.0.6:50545 10.10.0.13:3000 10.10.0.15:46848 outbound_.80_._.catalog.istioinaction.svc.cluster.local default

10. 다음 실습을 위한 default 네임스페이스 사이드카 설정 원복

1
2
3
4
5
6
kubectl label ns default istio-injection-
kubectl rollout restart deploy/sleep

# 결과
namespace/default unlabeled
deployment.apps/sleep restarted

11. sleep 파드 사이드카 제거 후 RBAC 정책에 의해 다시 차단됨 확인

1
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction

✅ 출력

1
RBAC: access denied

🧯 미인증 레거시 워크로드에서 온 요청 허용하기

1. 미인증 요청 허용을 위한 AuthorizationPolicy 리소스 정의

1
cat ch9/allow-unauthenticated-view-default-ns.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "webapp-allow-unauthenticated-view-default-ns"
  namespace: istioinaction
spec:
  selector:
    matchLabels:
      app: webapp
  rules:
    - to:
      - operation:
          methods: ["GET"]

2. AuthorizationPolicy 리소스 적용 및 전체 목록 확인

1
2
kubectl apply -f ch9/allow-unauthenticated-view-default-ns.yaml
kubectl get AuthorizationPolicy -A

✅ 출력

1
2
3
4
5
6
authorizationpolicy.security.istio.io/webapp-allow-unauthenticated-view-default-ns created

NAMESPACE       NAME                                           AGE
istio-system    deny-all                                       27m
istioinaction   webapp-allow-unauthenticated-view-default-ns   0s
istioinaction   webapp-allow-view-default-ns                   18m

3. default 네임스페이스 → webapp 호출 성공 확인

1
2
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Web App - Istio in Action</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
  <link rel="stylesheet" href="/static/css/main.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.19.0/cytoscape.min.js" integrity="sha512-TOWs340KHbJjY/a2SCtsUcXYBg7/xPX72NKpJ3VITogkHJTy2yMyoJE0pxJjumMGHCg46ud89KO5q1Toe3Aeaw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>

<div class="content-wrapper wrapper">
  <section class="hero is-landing is-large">
    <div class="hero-head">
      <nav class="navbar">
        <div class  ="container">
          <div class="navbar-brand">
            <a class="navbar-item">
              Istio in Action
            </a>
          </div>
        </div>
      </nav>
    </div>

    <div class="hero-body">
      <div class="container ">

        <div class="columns has-text-centered">
          <div class="column is-6 is-offset-3">
            <h1 class="title is-1">
              Service Graph
            </h1>
          </div>
        </div>
        <div class="columns">
          <div class="column is-full">
            <div id="cy"></div>
          </div>
        </div>
      </div>
    </div>
  </section>

  <section class="bg-light">
    <div class="container section">
      <div class="content has-text-centered">
        <h1>Service data</h1>
      </div>

      <div class="columns">
        <div class="column">
          <div class="card">
            <header class="card-header">
              <p class="card-header-title">
                Data from the Catalog service
              </p>
            </header>
            <div class="card-content">
              <div class="content">
                
                  <p>The catalog service is currently not available.</p>
                
              </div>
            </div>
          </div>

        </div>

        <div class="column">
          <div class="card">
            <header class="card-header">
              <p class="card-header-title">
                Data from the Forum service
              </p>
            </header>
            <div class="card-content">
              <div class="content">
                
                <p>The forum service is currently not available.</p>
                
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </section>

</div>

<footer class="footer">
  <div class="container">
    <div class="content has-text-centered">
      <p>
        Sample application for Istio in Action (<a href="https://istioinaction.io">istioinaction.io</a>)
      </p>
    </div>
  </div>
</footer>

<script>
  var cy = cytoscape({

    container: document.getElementById('cy'), 

    elements: [ 
      { 
        data: { id: 'client' },
        position: { x: -120, y: 50},
        style: { 
          'opacity': 0
        }
      },
      { 
        data: { id: 'Web App' },
        position: { x: 0, y: 50},
      },
      { 
        data: { id: 'Catalog' },
        position: { x: 200, y: 100},
        style: { 
          'background-color': '#AD0505'
        }
      },
      { 
        data: { id: 'Forum' },
        position: { x: 200, y: 0},
        style: { 
          'background-color': '#AD0505'
        }
      },
      { 
        data: { id: 'client-call', source: 'client', target: 'Web App',}
      },
      { 
        data: { id: 'web-to-catalog', source: 'Web App', target: 'Catalog',}
      },
      { 
        data: { id: 'web-to-forum', source: 'Web App', target: 'Forum' }
      }
    ],

    style: [ 
      {
        selector: 'node',
        style: {
          'background-color': '#99D568',
          'label': 'data(id)',
          "text-valign" : "center",
          "text-halign" : "center",
          "width": "80px",
          'color': '#fefefe',
          'shape': 'square',
        }
      },

      {
        selector: 'edge',
        style: {
          'width': 3,
          'line-color': '#000',
          'target-arrow-color': '#000',
          'target-arrow-shape': 'triangle',
          'curve-style': 'bezier'
        }
      }
    ],

    layout: {
      name: 'preset',
      padding: 10
    }
  });

</script>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
2025-05-10T08:12:33.144890Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 10.10.0.16:36914, directRemoteIP: 10.10.0.16:36914, remoteIP: 10.10.0.16:36914,localAddress: 10.10.0.12:8080, ssl: none, headers: ':authority', 'webapp.istioinaction'
':path', '/'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', 'e267a7a2-dfdb-9dcd-817b-790db2232622'
, dynamicMetadata: 	thread=41
2025-05-10T08:12:33.144916Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy ns[istioinaction]-policy[webapp-allow-unauthenticated-view-default-ns]-rule[0]	thread=41
[2025-05-10T08:12:33.146Z] "GET /items HTTP/1.1" 403 - via_upstream - "-" 0 19 0 0 "-" "beegoServer" "e267a7a2-dfdb-9dcd-817b-790db2232622" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:51000 10.200.1.219:80 10.10.0.12:50890 - default
[2025-05-10T08:12:33.144Z] "GET / HTTP/1.1" 200 - via_upstream - "-" 0 4527 28 28 "-" "curl/8.5.0" "e267a7a2-dfdb-9dcd-817b-790db2232622" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:48863 10.10.0.12:8080 10.10.0.16:36914 - default

4. webapp → catalog 서비스 접근 시 deny-all 로 차단 확인

1
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/api/catalog

✅ 출력

1
error calling Catalog service
1
2
3
4
5
6
7
8
9
10
11
12
2025-05-10T08:14:25.886312Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 10.10.0.16:47730, directRemoteIP: 10.10.0.16:47730, remoteIP: 10.10.0.16:47730,localAddress: 10.10.0.12:8080, ssl: none, headers: ':authority', 'webapp.istioinaction'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', '4600c35d-661c-9448-aad0-6ceb3cfa946d'
, dynamicMetadata: 	thread=41
2025-05-10T08:14:25.886338Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy ns[istioinaction]-policy[webapp-allow-unauthenticated-view-default-ns]-rule[0]	thread=41
[2025-05-10T08:14:25.887Z] "GET /items HTTP/1.1" 403 - via_upstream - "-" 0 19 0 0 "-" "beegoServer" "4600c35d-661c-9448-aad0-6ceb3cfa946d" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:54610 10.200.1.219:80 10.10.0.12:43288 - default
[2025-05-10T08:14:25.886Z] "GET /api/catalog HTTP/1.1" 500 - via_upstream - "-" 0 29 2 2 "-" "curl/8.5.0" "4600c35d-661c-9448-aad0-6ceb3cfa946d" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:48863 10.10.0.12:8080 10.10.0.16:47730 - default

5. catalog 서비스 직접 호출 시 연결 실패 (리셋) 확인

1
2
kubectl logs -n istioinaction -l app=catalog -c istio-proxy -f
kubectl exec deploy/sleep -- curl -sSL catalog.istioinaction/items

✅ 출력

1
2
curl: (56) Recv failure: Connection reset by peer
command terminated with exit code 56
1
[2025-05-10T08:16:38.021Z] "- - -" 0 NR filter_chain_not_found - "-" 0 0 0 - "-" "-" "-" "-" "-" - - 10.10.0.13:3000 10.10.0.16:49788 - -

👤 특정 서비스 어카운트에서 온 요청 허용하기

1. 서비스 어카운트 기반 AuthorizationPolicy 리소스 정의

1
cat ch9/catalog-viewer-policy.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "catalog-viewer"
  namespace: istioinaction
spec:
  selector:
    matchLabels:
      app: catalog
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/istioinaction/sa/webapp"]
    to:
    - operation:
        methods: ["GET"]

2. 서비스 어카운트 기반 정책 적용 및 전체 정책 목록 확인

1
2
kubectl apply -f ch9/catalog-viewer-policy.yaml
kubectl get AuthorizationPolicy -A

✅ 출력

1
2
3
4
5
6
7
authorizationpolicy.security.istio.io/catalog-viewer created

NAMESPACE       NAME                                           AGE
istio-system    deny-all                                       36m
istioinaction   catalog-viewer                                 1s
istioinaction   webapp-allow-unauthenticated-view-default-ns   9m1s
istioinaction   webapp-allow-view-default-ns                   27m

3. 미인증 레거시 파드 → webapp → catalog 요청 흐름 확인

1
2
3
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f
kubectl logs -n istioinaction -l app=catalog -c istio-proxy -f
kubectl exec deploy/sleep -- curl -sSL webapp.istioinaction/api/catalog 

✅ 출력

1
[{"id":1,"color":"amber","department":"Eyewear","name":"Elinor Glasses","price":"282.00"},{"id":2,"color":"cyan","department":"Clothing","name":"Atlas Shirt","price":"127.00"},{"id":3,"color":"teal","department":"Clothing","name":"Small Metal Shoes","price":"232.00"},{"id":4,"color":"red","department":"Watches","name":"Red Dragon Watch","price":"232.00"}]
1
2
3
4
5
6
7
8
9
10
11
12
2025-05-10T08:21:22.714478Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 10.10.0.16:53088, directRemoteIP: 10.10.0.16:53088, remoteIP: 10.10.0.16:53088,localAddress: 10.10.0.12:8080, ssl: none, headers: ':authority', 'webapp.istioinaction'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', 'e24cb368-c501-9383-b459-a833e997e663'
, dynamicMetadata: 	thread=41
2025-05-10T08:21:22.714504Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy ns[istioinaction]-policy[webapp-allow-unauthenticated-view-default-ns]-rule[0]	thread=41
[2025-05-10T08:21:22.715Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 13 13 "-" "beegoServer" "e24cb368-c501-9383-b459-a833e997e663" "catalog.istioinaction:80" "10.10.0.13:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.12:57624 10.200.1.219:80 10.10.0.12:37020 - default
[2025-05-10T08:21:22.714Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 15 15 "-" "curl/8.5.0" "e24cb368-c501-9383-b459-a833e997e663" "webapp.istioinaction" "10.10.0.12:8080" inbound|8080|| 127.0.0.6:48863 10.10.0.12:8080 10.10.0.16:53088 - default
1
[2025-05-10T08:21:22.721Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 1 1 "-" "beegoServer" "e24cb368-c501-9383-b459-a833e997e663" "catalog.istioinaction:80" "10.10.0.13:3000" inbound|3000|| 127.0.0.6:56289 10.10.0.13:3000 10.10.0.12:57624 outbound_.80_._.catalog.istioinaction.svc.cluster.local default

📚 JSON 웹 토큰이란 무엇인가?

1. JWT 토큰 내용 확인을 위한 파일 출력

1
cat ./ch9/enduser/user.jwt

✅ 출력

1
eyJhbGciOiJSUzI1NiIsImtpZCI6IkNVLUFESkpFYkg5YlhsMHRwc1FXWXVvNEV3bGt4RlVIYmVKNGNra2FrQ00iLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ3NDUxNDUwMzgsImdyb3VwIjoidXNlciIsImlhdCI6MTU5MTU0NTAzOCwiaXNzIjoiYXV0aEBpc3Rpb2luYWN0aW9uLmlvIiwic3ViIjoiOWI3OTJiNTYtN2RmYS00ZTRiLWE4M2YtZTIwNjc5MTE1ZDc5In0.jNDoRx7SNm8b1xMmPaOEMVgwdnTmXJwD5jjCH9wcGsLisbZGcR6chkirWy1BVzYEQDTf8pDJpY2C3H-aXN3IlAcQ1UqVe5lShIjCMIFTthat3OuNgu-a91csGz6qtQITxsOpMcBinlTYRsUOICcD7UZcLugxK4bpOECohHoEhuASHzlH-FYESDB-JYrxmwXj4xoZ_jIsdpuqz_VYhWp8e0phDNJbB6AHOI3m7OHCsGNcw9Z0cks1cJrgB8JNjRApr9XTNBoEC564PX2ZdzciI9BHoOFAKx4mWWEqW08LDMSZIN5Ui9ppwReSV2ncQOazdStS65T43bZJwgJiIocSCg

2. JWT 토큰 디코딩하여 Header 및 Claims 정보 확인

1
jwt decode $(cat ./ch9/enduser/user.jwt)

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Token header
------------
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM"
}

Token claims
------------
{
  "exp": 4745145038, # 만료 시간 Expiration time
  "group": "user",   # 'group' 클레임
  "iat": 1591545038, # 발행 시각 Issue time
  "iss": "auth@istioinaction.io", # 토큰 발행자 Token issuer
  "sub": "9b792b56-7dfa-4e4b-a83f-e20679115d79" # 토큰의 주체 Subject or principal of the token
}

🧭 인그레스 게이트웨이에서의 최종 사용자 인증 및 인가

1. 이전 실습 환경 삭제

1
2
3
4
kubectl delete virtualservice,deployment,service,\
destinationrule,gateway,peerauthentication,authorizationpolicy --all -n istioinaction

kubectl delete peerauthentication,authorizationpolicy -n istio-system --all

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
virtualservice.networking.istio.io "webapp-virtualservice" deleted
deployment.apps "catalog" deleted
deployment.apps "webapp" deleted
service "catalog" deleted
service "webapp" deleted
gateway.networking.istio.io "coolstore-gateway" deleted
peerauthentication.security.istio.io "webapp" deleted
authorizationpolicy.security.istio.io "catalog-viewer" deleted
authorizationpolicy.security.istio.io "webapp-allow-unauthenticated-view-default-ns" deleted
authorizationpolicy.security.istio.io "webapp-allow-view-default-ns" deleted
peerauthentication.security.istio.io "default" deleted
authorizationpolicy.security.istio.io "deny-all" deleted

2. webapp 및 catalog 서비스 재배포

1
2
3
4
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction
cat ch9/enduser/ingress-gw-for-webapp.yaml
kubectl apply -f ch9/enduser/ingress-gw-for-webapp.yaml -n istioinaction

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
serviceaccount/catalog unchanged
service/catalog created
deployment.apps/catalog created
serviceaccount/webapp unchanged
service/webapp created
deployment.apps/webapp created

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: webapp-gateway
  namespace: istioinaction
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "webapp.istioinaction.io"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: webapp-virtualservice
  namespace: istioinaction
spec:
  hosts:
  - "webapp.istioinaction.io"
  gateways:
  - webapp-gateway
  http:
  - route:
    - destination:
        host: webapp
        port:
          number: 80
          
gateway.networking.istio.io/webapp-gateway created
virtualservice.networking.istio.io/webapp-virtualservice created

📜 RequestAuthentication으로 JWT 검증하기

1. JWT 검증을 위한 RequestAuthentication 리소스 정의

1
cat ch9/enduser/jwt-token-request-authn.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
  name: "jwt-token-request-authn"
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  jwtRules:
  - issuer: "auth@istioinaction.io"
    jwks: |
      { "keys":[ {"e":"AQAB","kid":"CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM","kty":"RSA","n":"zl9VRDbmVvyXNdyoGJ5uhuTSRA2653KHEi3XqITfJISvedYHVNGoZZxUCoiSEumxqrPY_Du7IMKzmT4bAuPnEalbY8rafuJNXnxVmqjTrQovPIerkGW5h59iUXIz6vCznO7F61RvJsUEyw5X291-3Z3r-9RcQD9sYy7-8fTNmcXcdG_nNgYCnduZUJ3vFVhmQCwHFG1idwni8PJo9NH6aTZ3mN730S6Y1g_lJfObju7lwYWT8j2Sjrwt6EES55oGimkZHzktKjDYjRx1rN4dJ5PR5zhlQ4kORWg1PtllWy1s5TSpOUv84OPjEohEoOWH0-g238zIOYA83gozgbJfmQ"}]}

2. RequestAuthentication 리소스 적용 및 생성 확인

1
2
kubectl apply -f ch9/enduser/jwt-token-request-authn.yaml
kubectl get requestauthentication -A

✅ 출력

1
2
3
4
requestauthentication.security.istio.io/jwt-token-request-authn created

NAMESPACE      NAME                      AGE
istio-system   jwt-token-request-authn   0s

3. Istio IngressGateway에 JWT 필터가 반영되었는지 확인

1
docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/istio-ingressgateway.istio-system --port 8080 -o json

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
                            "httpFilters": [
                                {
                                    "name": "istio.metadata_exchange",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm",
                                        "config": {
                                            "vmConfig": {
                                                "runtime": "envoy.wasm.runtime.null",
                                                "code": {
                                                    "local": {
                                                        "inlineString": "envoy.wasm.metadata_exchange"
                                                    }
                                                }
                                            },
                                            "configuration": {
                                                "@type": "type.googleapis.com/envoy.tcp.metadataexchange.config.MetadataExchange"
                                            }
                                        }
                                    }
                                },
                                {
                                    "name": "envoy.filters.http.jwt_authn",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication",
                                        "providers": {
                                            "origins-0": {
                                                "issuer": "auth@istioinaction.io",
                                                "localJwks": {
                                                    "inlineString": "{ \"keys\":[ {\"e\":\"AQAB\",\"kid\":\"CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM\",\"kty\":\"RSA\",\"n\":\"zl9VRDbmVvyXNdyoGJ5uhuTSRA2653KHEi3XqITfJISvedYHVNGoZZxUCoiSEumxqrPY_Du7IMKzmT4bAuPnEalbY8rafuJNXnxVmqjTrQovPIerkGW5h59iUXIz6vCznO7F61RvJsUEyw5X291-3Z3r-9RcQD9sYy7-8fTNmcXcdG_nNgYCnduZUJ3vFVhmQCwHFG1idwni8PJo9NH6aTZ3mN730S6Y1g_lJfObju7lwYWT8j2Sjrwt6EES55oGimkZHzktKjDYjRx1rN4dJ5PR5zhlQ4kORWg1PtllWy1s5TSpOUv84OPjEohEoOWH0-g238zIOYA83gozgbJfmQ\"}]}\n"
                                                },
                                                "payloadInMetadata": "auth@istioinaction.io"
                                            }
                                        },
                                        "rules": [
                                            {
                                                "match": {
                                                    "prefix": "/"
                                                },
                                                "requires": {
                                                    "requiresAny": {
                                                        "requirements": [
                                                            {
                                                                "providerName": "origins-0"
                                                            },
                                                            {
                                                                "allowMissing": {}
                                                            }
                                                        ]
                                                    }
                                                }
                                            }
                                        ],
                                        "bypassCorsPreflight": true
                                    }
                                },
                                {
                                    "name": "istio_authn",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/istio.envoy.config.filter.http.authn.v2alpha1.FilterConfig",
                                        "policy": {
                                            "origins": [
                                                {
                                                    "jwt": {
                                                        "issuer": "auth@istioinaction.io"
                                                    }
                                                }
                                            ],
                                            "originIsOptional": true,
                                            "principalBinding": "USE_ORIGIN"
                                        },
                                        "skipValidateTrustDomain": true
                                    }
                                },
                                {
                                    "name": "envoy.filters.http.grpc_stats",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig",
                                        "emitFilterState": true,
                                        "statsForAllMethods": false
                                    }
                                },
                                {
                                    "name": "istio.alpn",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/istio.envoy.config.filter.http.alpn.v2alpha1.FilterConfig",
                                        "alpnOverride": [
                                            {
                                                "alpnOverride": [
                                                    "istio-http/1.0",
                                                    "istio",
                                                    "http/1.0"
                                                ]
                                            },
                                            {
                                                "upstreamProtocol": "HTTP11",
                                                "alpnOverride": [
                                                    "istio-http/1.1",
                                                    "istio",
                                                    "http/1.1"
                                                ]
                                            },
                                            {
                                                "upstreamProtocol": "HTTP2",
                                                "alpnOverride": [
                                                    "istio-h2",
                                                    "istio",
                                                    "h2"
                                                ]
                                            }
                                        ]
                                    }
                                },
                                {
                                    "name": "envoy.filters.http.fault",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault"
                                    }
                                },
                                {
                                    "name": "envoy.filters.http.cors",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors"
                                    }
                                },
                                {
                                    "name": "istio.stats",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
                                        "typeUrl": "type.googleapis.com/stats.PluginConfig",
                                        "value": {
                                            "disable_host_header_fallback": true
                                        }
                                    }
                                },
                                {
                                    "name": "envoy.filters.http.router",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router"
                                    }
                                }
                            ],
...                            

🟢 유효한 발행자의 토큰이 있는 요청은 받아들여진다

1. 유효한 발행자의 JWT 디코딩 및 내용 확인

1
2
3
cat ch9/enduser/user.jwt
USER_TOKEN=$(< ch9/enduser/user.jwt)
jwt decode $USER_TOKEN

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
eyJhbGciOiJSUzI1NiIsImtpZCI6IkNVLUFESkpFYkg5YlhsMHRwc1FXWXVvNEV3bGt4RlVIYmVKNGNra2FrQ00iLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ3NDUxNDUwMzgsImdyb3VwIjoidXNlciIsImlhdCI6MTU5MTU0NTAzOCwiaXNzIjoiYXV0aEBpc3Rpb2luYWN0aW9uLmlvIiwic3ViIjoiOWI3OTJiNTYtN2RmYS00ZTRiLWE4M2YtZTIwNjc5MTE1ZDc5In0.jNDoRx7SNm8b1xMmPaOEMVgwdnTmXJwD5jjCH9wcGsLisbZGcR6chkirWy1BVzYEQDTf8pDJpY2C3H-aXN3IlAcQ1UqVe5lShIjCMIFTthat3OuNgu-a91csGz6qtQITxsOpMcBinlTYRsUOICcD7UZcLugxK4bpOECohHoEhuASHzlH-FYESDB-JYrxmwXj4xoZ_jIsdpuqz_VYhWp8e0phDNJbB6AHOI3m7OHCsGNcw9Z0cks1cJrgB8JNjRApr9XTNBoEC564PX2ZdzciI9BHoOFAKx4mWWEqW08LDMSZIN5Ui9ppwReSV2ncQOazdStS65T43bZJwgJiIocSCg

Token header
------------
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM"
}

Token claims
------------
{
  "exp": 4745145038,
  "group": "user",
  "iat": 1591545038,
  "iss": "auth@istioinaction.io",
  "sub": "9b792b56-7dfa-4e4b-a83f-e20679115d79"
}

2. IngressGateway 디버깅 로그 레벨을 RBAC:debug로 설정

1
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/istio-ingressgateway -n istio-system --level rbac:debug

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
istio-ingressgateway-6bb8fb6549-dq7gl.istio-system:
active loggers:
  admin: warning
  alternate_protocols_cache: warning
  aws: warning
  assert: warning
  backtrace: warning
  cache_filter: warning
  client: warning
  config: warning
  connection: warning
  conn_handler: warning
  decompression: warning
  dns: warning
  dubbo: warning
  envoy_bug: warning
  ext_authz: warning
  ext_proc: warning
  rocketmq: warning
  file: warning
  filter: warning
  forward_proxy: warning
  grpc: warning
  happy_eyeballs: warning
  hc: warning
  health_checker: warning
  http: warning
  http2: warning
  hystrix: warning
  init: warning
  io: warning
  jwt: warning
  kafka: warning
  key_value_store: warning
  lua: warning
  main: warning
  matcher: warning
  misc: error
  mongo: warning
  multi_connection: warning
  oauth2: warning
  quic: warning
  quic_stream: warning
  pool: warning
  rate_limit_quota: warning
  rbac: debug
  rds: warning
  redis: warning
  router: warning
  runtime: warning
  stats: warning
  secret: warning
  tap: warning
  testing: warning
  thrift: warning
  tracing: warning
  upstream: warning
  udp: warning
  wasm: warning
  websocket: warning

3. 유효한 JWT를 포함한 요청 전송 및 허용 확인

1
2
3
4
kubectl logs -n istio-system -l app=istio-ingressgateway -f 

curl -H "Authorization: Bearer $USER_TOKEN" \
     -sSl -o /dev/null -w "%{http_code}" webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
200
1
[2025-05-10T09:47:47.949Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 12 11 "172.18.0.1" "curl/8.13.0" "9c3878df-07a0-9d0a-85a2-f8fa719b703e" "webapp.istioinaction.io:30000" "10.10.0.18:8080" outbound|80||webapp.istioinaction.svc.cluster.local 10.10.0.6:59778 10.10.0.6:8080 172.18.0.1:55898 - -

🛑 유효하지 않은 발행자의 토큰이 있는 요청은 거부된다

1. 잘못된 발행자의 JWT 파일 확인 및 디코딩

1
2
3
cat ch9/enduser/not-configured-issuer.jwt
WRONG_ISSUER=$(< ch9/enduser/not-configured-issuer.jwt)
jwt decode $WRONG_ISSUER

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
eyJhbGciOiJSUzI1NiIsImtpZCI6IkNVLUFESkpFYkg5YlhsMHRwc1FXWXVvNEV3bGt4RlVIYmVKNGNra2FrQ00iLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ3NDUxNTE1NDgsImdyb3VwIjoidXNlciIsImlhdCI6MTU5MTU1MTU0OCwiaXNzIjoib2xkLWF1dGhAaXN0aW9pbmFjdGlvbi5pbyIsInN1YiI6Ijc5ZDc1MDZjLWI2MTctNDZkMS1iYzFmLWY1MTFiNWQzMGFiMCJ9.eUEbrJ3Gr4F5eViMlLsIGcD6UIId6tH6u5vLN_IzPnwpSSp6vy6knVgC1GHsWPWwnEhcPHz1TlQz8E3O6F7oVyNhMTJyniaXtVyByvgAVCbeaOYVRnm1aSWwjFt5IfJJcbk21BWbPfE12Hfbo03sRq1hI1iEcn4nbtoh8tjj_G4r8gwiKVlkA3g5bFkwiSEmZQe2cumzgdtNu4XzU5ghl6cdFyzYD5x3750uy_bfduaQokCVymQq3P-dUPnz7_5-ZOj-3SRb3yHbmvlAnyQgTgIlQc3J-anGnsqec33lhVh5RdNuxKj9J14a-ub9ysjzUvcXh1expDqNxR33BaQnpQ

Token header
------------
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM"
}

Token claims
------------
{
  "exp": 4745151548,
  "group": "user",
  "iat": 1591551548,
  "iss": "old-auth@istioinaction.io", # 현재 설정한 정책의 발급자와 다름 issuer: "auth@istioinaction.io" 
  "sub": "79d7506c-b617-46d1-bc1f-f511b5d30ab0"
}

2. 잘못된 issuer 토큰을 포함한 요청 시도

JWT 발급자 불일치로 인한 요청 거부 확인

1
2
3
4
kubectl logs -n istio-system -l app=istio-ingressgateway -f

curl -H "Authorization: Bearer $WRONG_ISSUER" \
     -sSl -o /dev/null -w "%{http_code}" webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
401
1
[2025-05-10T09:50:35.469Z] "GET /api/catalog HTTP/1.1" 401 - jwt_authn_access_denied{Jwt_issuer_is_not_configured} - "-" 0 28 0 - "172.18.0.1" "curl/8.13.0" "4dab4af8-fc59-9f91-9392-377a3cdeef14" "webapp.istioinaction.io:30000" "-" outbound|80||webapp.istioinaction.svc.cluster.local - 10.10.0.6:8080 172.18.0.1:54604 - -

🔓 토큰이 없는 요청은 클러스터로 받아들여진다

1
2
3
kubectl logs -n istio-system -l app=istio-ingressgateway -f

curl -sSl -o /dev/null -w "%{http_code}" webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
200
1
[2025-05-10T09:52:01.421Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 25 24 "172.18.0.1" "curl/8.13.0" "aa4adb07-aefc-972f-9a3c-301097158ffc" "webapp.istioinaction.io:30000" "10.10.0.18:8080" outbound|80||webapp.istioinaction.svc.cluster.local 10.10.0.6:56952 10.10.0.6:8080 172.18.0.1:41688 - -

🚫 JWT가 없는 요청 거부하기

1. AuthorizationPolicy로 토큰 없는 요청 거부 정책 정의

1
2
vi ch9/enduser/app-gw-requires-jwt.yaml
cat ch9/enduser/app-gw-requires-jwt.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: app-gw-requires-jwt
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: DENY
  rules:
  - from:
    - source:
        notRequestPrincipals: ["*"]
    to:
    - operation:
          hosts: ["webapp.istioinaction.io:30000"] # 30000 추가!
1
2
kubectl apply -f ch9/enduser/app-gw-requires-jwt.yaml
kubectl get AuthorizationPolicy -A

✅ 출력

1
2
3
4
5
Warning: configured AuthorizationPolicy will deny all traffic to TCP ports under its scope due to the use of only HTTP attributes in a DENY rule; it is recommended to explicitly specify the port
authorizationpolicy.security.istio.io/app-gw-requires-jwt created

NAMESPACE      NAME                  AGE
istio-system   app-gw-requires-jwt   22s

2. 토큰 없이 요청 시도 → 거부

1
2
3
kubectl logs -n istio-system -l app=istio-ingressgateway -f

curl -sSl -o /dev/null -w "%{http_code}" webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
403
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2025-05-10T09:59:41.751184Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:60752, directRemoteIP: 172.18.0.1:60752, remoteIP: 172.18.0.1:60752,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', '15e5fbad-eac3-97e7-8e45-313f993fac3d'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "istio_authn"
  value {
  }
}
	thread=56
2025-05-10T09:59:41.751218Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:158	enforced denied, matched policy ns[istio-system]-policy[app-gw-requires-jwt]-rule[0]	thread=56
[2025-05-10T09:59:41.750Z] "GET /api/catalog HTTP/1.1" 403 - rbac_access_denied_matched_policy[ns[istio-system]-policy[app-gw-requires-jwt]-rule[0]] - "-" 0 19 0 - "172.18.0.1" "curl/8.13.0" "15e5fbad-eac3-97e7-8e45-313f993fac3d" "webapp.istioinaction.io:30000" "-" outbound|80||webapp.istioinaction.svc.cluster.local - 10.10.0.6:8080 172.18.0.1:60752 - -

3. JWT 토큰 포함 요청 시도 → 허용

1
2
3
4
kubectl logs -n istio-system -l app=istio-ingressgateway -f

curl -H "Authorization: Bearer $USER_TOKEN" \
     -sSl -o /dev/null -w "%{http_code}" webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
200
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
2025-05-10T10:00:57.541372Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:55852, directRemoteIP: 172.18.0.1:55852, remoteIP: 172.18.0.1:55852,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', 'd8d2e1b3-1872-904d-abe9-423e41f780fa'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145038
            }
          }
          fields {
            key: "group"
            value {
              string_value: "user"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545038
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "user"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/9b792b56-7dfa-4e4b-a83f-e20679115d79"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"group\":\"user\",\"iss\":\"auth@istioinaction.io\",\"exp\":4745145038,\"sub\":\"9b792b56-7dfa-4e4b-a83f-e20679115d79\",\"iat\":1591545038}"
      }
    }
  }
}
	thread=41
2025-05-10T10:00:57.541421Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy none	thread=41
[2025-05-10T10:00:57.540Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 5 4 "172.18.0.1" "curl/8.13.0" "d8d2e1b3-1872-904d-abe9-423e41f780fa" "webapp.istioinaction.io:30000" "10.10.0.18:8080" outbound|80||webapp.istioinaction.svc.cluster.local 10.10.0.6:56952 10.10.0.6:8080 172.18.0.1:55852 - -

🛂 JWT 클레임에 기반한 다양한 접근 수준

1. 일반 사용자 토큰 디코딩 (group: user)

1
jwt decode $(cat ch9/enduser/user.jwt)

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Token header
------------
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM"
}

Token claims
------------
{
  "exp": 4745145038,
  "group": "user",
  "iat": 1591545038,
  "iss": "auth@istioinaction.io",
  "sub": "9b792b56-7dfa-4e4b-a83f-e20679115d79"
}

2. 관리자 토큰 디코딩 (group: admin)

1
jwt decode $(cat ch9/enduser/admin.jwt)

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Token header
------------
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM"
}

Token claims
------------
{
  "exp": 4745145071,
  "group": "admin",
  "iat": 1591545071,
  "iss": "auth@istioinaction.io",
  "sub": "218d3fb9-4628-4d20-943c-124281c80e7b"
}

3. 일반 사용자에게 webapp의 GET 요청 허용하는 AuthorizationPolicy 설정

1
cat ch9/enduser/allow-all-with-jwt-to-webapp.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-all-with-jwt-to-webapp
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: ALLOW
  rules:
  - from:
    - source:
        requestPrincipals: ["auth@istioinaction.io/*"]
    to:
    - operation:
        hosts: ["webapp.istioinaction.io"]
        methods: ["GET"]

4. 관리자에게 모든 작업 허용하는 AuthorizationPolicy 설정

1
cat ch9/enduser/allow-mesh-all-ops-admin.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "allow-mesh-all-ops-admin"
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: ALLOW
  rules:
  - from:
    - source:
        requestPrincipals: ["auth@istioinaction.io/*"]
    when:
    - key: request.auth.claims[group]
      values: ["admin"]

5. AuthorizationPolicy 적용 및 확인

1
2
3
4
kubectl apply -f ch9/enduser/allow-all-with-jwt-to-webapp.yaml
kubectl apply -f ch9/enduser/allow-mesh-all-ops-admin.yaml

kubectl get authorizationpolicy -A

✅ 출력

1
2
3
4
5
6
7
authorizationpolicy.security.istio.io/allow-all-with-jwt-to-webapp created
authorizationpolicy.security.istio.io/allow-mesh-all-ops-admin created

NAMESPACE      NAME                           AGE
istio-system   allow-all-with-jwt-to-webapp   0s
istio-system   allow-mesh-all-ops-admin       0s
istio-system   app-gw-requires-jwt            8m47s

6. istio-ingressgateway 로깅 레벨을 rbac:debug 로 설정

1
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/istio-ingressgateway -n istio-system --level rbac:debug

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
istio-ingressgateway-6bb8fb6549-dq7gl.istio-system:
active loggers:
  admin: warning
  alternate_protocols_cache: warning
  aws: warning
  assert: warning
  backtrace: warning
  cache_filter: warning
  client: warning
  config: warning
  connection: warning
  conn_handler: warning
  decompression: warning
  dns: warning
  dubbo: warning
  envoy_bug: warning
  ext_authz: warning
  ext_proc: warning
  rocketmq: warning
  file: warning
  filter: warning
  forward_proxy: warning
  grpc: warning
  happy_eyeballs: warning
  hc: warning
  health_checker: warning
  http: warning
  http2: warning
  hystrix: warning
  init: warning
  io: warning
  jwt: warning
  kafka: warning
  key_value_store: warning
  lua: warning
  main: warning
  matcher: warning
  misc: error
  mongo: warning
  multi_connection: warning
  oauth2: warning
  quic: warning
  quic_stream: warning
  pool: warning
  rate_limit_quota: warning
  rbac: debug
  rds: warning
  redis: warning
  router: warning
  runtime: warning
  stats: warning
  secret: warning
  tap: warning
  testing: warning
  thrift: warning
  tracing: warning
  upstream: warning
  udp: warning
  wasm: warning
  websocket: warning

7. 일반 사용자 토큰으로 GET 요청 (거부됨)

1
kubectl logs -n istio-system -l app=istio-ingressgateway -f
1
2
3
4
USER_TOKEN=$(< ch9/enduser/user.jwt)

curl -H "Authorization: Bearer $USER_TOKEN" \
     -sSl -o /dev/null -w "%{http_code}\n" webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
403
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
2025-05-10T10:09:27.420128Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:33476, directRemoteIP: 172.18.0.1:33476, remoteIP: 172.18.0.1:33476,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', '30c76cac-57bd-9ebf-b16f-d81954a084ee'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145038
            }
          }
          fields {
            key: "group"
            value {
              string_value: "user"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545038
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "user"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/9b792b56-7dfa-4e4b-a83f-e20679115d79"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"group\":\"user\",\"sub\":\"9b792b56-7dfa-4e4b-a83f-e20679115d79\",\"iss\":\"auth@istioinaction.io\",\"iat\":1591545038,\"exp\":4745145038}"
      }
    }
  }
}
	thread=50
2025-05-10T10:09:27.420164Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy none	thread=50
2025-05-10T10:09:27.420187Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:33476, directRemoteIP: 172.18.0.1:33476, remoteIP: 172.18.0.1:33476,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', '30c76cac-57bd-9ebf-b16f-d81954a084ee'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145038
            }
          }
          fields {
            key: "group"
            value {
              string_value: "user"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545038
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "user"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/9b792b56-7dfa-4e4b-a83f-e20679115d79"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"group\":\"user\",\"sub\":\"9b792b56-7dfa-4e4b-a83f-e20679115d79\",\"iss\":\"auth@istioinaction.io\",\"iat\":1591545038,\"exp\":4745145038}"
      }
    }
  }
}
	thread=50
2025-05-10T10:09:27.420194Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:158	enforced denied, matched policy none	thread=50
[2025-05-10T10:09:27.419Z] "GET /api/catalog HTTP/1.1" 403 - rbac_access_denied_matched_policy[none] - "-" 0 19 0 - "172.18.0.1" "curl/8.13.0" "30c76cac-57bd-9ebf-b16f-d81954a084ee" "webapp.istioinaction.io:30000" "-" outbound|80||webapp.istioinaction.svc.cluster.local - 10.10.0.6:8080 172.18.0.1:33476 - -

8. 일반 사용자 토큰으로 POST 요청 (거부됨)

1
2
3
curl -H "Authorization: Bearer $USER_TOKEN" \
     -XPOST webapp.istioinaction.io:30000/api/catalog \
     --data '{"id": 2, "name": "Shoes", "price": "84.00"}'

✅ 출력

1
RBAC: access denied
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
2025-05-10T10:10:41.840953Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:35532, directRemoteIP: 172.18.0.1:35532, remoteIP: 172.18.0.1:35532,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'POST'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'content-length', '44'
'content-type', 'application/x-www-form-urlencoded'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', '33936282-0055-9a0e-9ed9-8a128b4c066f'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145038
            }
          }
          fields {
            key: "group"
            value {
              string_value: "user"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545038
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "user"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/9b792b56-7dfa-4e4b-a83f-e20679115d79"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"iss\":\"auth@istioinaction.io\",\"sub\":\"9b792b56-7dfa-4e4b-a83f-e20679115d79\",\"iat\":1591545038,\"group\":\"user\",\"exp\":4745145038}"
      }
    }
  }
}
	thread=65
2025-05-10T10:10:41.840999Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy none	thread=65
2025-05-10T10:10:41.841054Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:35532, directRemoteIP: 172.18.0.1:35532, remoteIP: 172.18.0.1:35532,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'POST'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'content-length', '44'
'content-type', 'application/x-www-form-urlencoded'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', '33936282-0055-9a0e-9ed9-8a128b4c066f'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145038
            }
          }
          fields {
            key: "group"
            value {
              string_value: "user"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545038
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "user"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "9b792b56-7dfa-4e4b-a83f-e20679115d79"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/9b792b56-7dfa-4e4b-a83f-e20679115d79"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"iss\":\"auth@istioinaction.io\",\"sub\":\"9b792b56-7dfa-4e4b-a83f-e20679115d79\",\"iat\":1591545038,\"group\":\"user\",\"exp\":4745145038}"
      }
    }
  }
}
	thread=65
2025-05-10T10:10:41.841075Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:158	enforced denied, matched policy none	thread=65
[2025-05-10T10:10:41.840Z] "POST /api/catalog HTTP/1.1" 403 - rbac_access_denied_matched_policy[none] - "-" 0 19 0 - "172.18.0.1" "curl/8.13.0" "33936282-0055-9a0e-9ed9-8a128b4c066f" "webapp.istioinaction.io:30000" "-" outbound|80||webapp.istioinaction.svc.cluster.local - 10.10.0.6:8080 172.18.0.1:35532 - -

9. 관리자 토큰으로 GET 요청 (허용됨)

1
2
3
4
ADMIN_TOKEN=$(< ch9/enduser/admin.jwt)

curl -H "Authorization: Bearer $ADMIN_TOKEN" \
     -sSl -o /dev/null -w "%{http_code}\n" webapp.istioinaction.io:30000/api/catalog

✅ 출력

1
200
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
2025-05-10T10:12:56.415968Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:59606, directRemoteIP: 172.18.0.1:59606, remoteIP: 172.18.0.1:59606,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', 'b81d54c1-dcbb-9419-bf3e-1ffa35e0aa72'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145071
            }
          }
          fields {
            key: "group"
            value {
              string_value: "admin"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545071
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "admin"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/218d3fb9-4628-4d20-943c-124281c80e7b"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"sub\":\"218d3fb9-4628-4d20-943c-124281c80e7b\",\"group\":\"admin\",\"iat\":1591545071,\"exp\":4745145071,\"iss\":\"auth@istioinaction.io\"}"
      }
    }
  }
}
	thread=65
2025-05-10T10:12:56.416021Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy none	thread=65
2025-05-10T10:12:56.416082Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:59606, directRemoteIP: 172.18.0.1:59606, remoteIP: 172.18.0.1:59606,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', 'b81d54c1-dcbb-9419-bf3e-1ffa35e0aa72'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145071
            }
          }
          fields {
            key: "group"
            value {
              string_value: "admin"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545071
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "admin"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/218d3fb9-4628-4d20-943c-124281c80e7b"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"sub\":\"218d3fb9-4628-4d20-943c-124281c80e7b\",\"group\":\"admin\",\"iat\":1591545071,\"exp\":4745145071,\"iss\":\"auth@istioinaction.io\"}"
      }
    }
  }
}
	thread=65
2025-05-10T10:12:56.416096Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy ns[istio-system]-policy[allow-mesh-all-ops-admin]-rule[0]	thread=65
[2025-05-10T10:12:56.415Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 6 5 "172.18.0.1" "curl/8.13.0" "b81d54c1-dcbb-9419-bf3e-1ffa35e0aa72" "webapp.istioinaction.io:30000" "10.10.0.18:8080" outbound|80||webapp.istioinaction.svc.cluster.local 10.10.0.6:40298 10.10.0.6:8080 172.18.0.1:59606 - -

10. 관리자 토큰으로 POST 요청 (허용됨)

1
kubectl logs -n istio-system -l app=istio-ingressgateway -f
1
2
3
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
     -XPOST webapp.istioinaction.io:30000/api/catalog \
     --data '{"id": 2, "name": "Shoes", "price": "84.00"}'

✅ 출력

1
[{"id":1,"color":"amber","department":"Eyewear","name":"Elinor Glasses","price":"282.00"},{"id":2,"color":"cyan","department":"Clothing","name":"Atlas Shirt","price":"127.00"},{"id":3,"color":"teal","department":"Clothing","name":"Small Metal Shoes","price":"232.00"},{"id":4,"color":"red","department":"Watches","name":"Red Dragon Watch","price":"232.00"}]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
2025-05-10T10:13:54.907999Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:53972, directRemoteIP: 172.18.0.1:53972, remoteIP: 172.18.0.1:53972,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'POST'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'content-length', '44'
'content-type', 'application/x-www-form-urlencoded'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', 'ebbeded3-425e-9e3b-a5e3-35b565dd0d57'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145071
            }
          }
          fields {
            key: "group"
            value {
              string_value: "admin"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545071
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "admin"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/218d3fb9-4628-4d20-943c-124281c80e7b"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"exp\":4745145071,\"sub\":\"218d3fb9-4628-4d20-943c-124281c80e7b\",\"group\":\"admin\",\"iat\":1591545071,\"iss\":\"auth@istioinaction.io\"}"
      }
    }
  }
}
	thread=68
2025-05-10T10:13:54.908042Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy none	thread=68
2025-05-10T10:13:54.908108Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 172.18.0.1:53972, directRemoteIP: 172.18.0.1:53972, remoteIP: 172.18.0.1:53972,localAddress: 10.10.0.6:8080, ssl: none, headers: ':authority', 'webapp.istioinaction.io:30000'
':path', '/api/catalog'
':method', 'POST'
':scheme', 'http'
'user-agent', 'curl/8.13.0'
'accept', '*/*'
'content-length', '44'
'content-type', 'application/x-www-form-urlencoded'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', 'ebbeded3-425e-9e3b-a5e3-35b565dd0d57'
'x-envoy-decorator-operation', 'webapp.istioinaction.svc.cluster.local:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNgoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1kcTdnbAobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.6~istio-ingressgateway-6bb8fb6549-dq7gl.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: filter_metadata {
  key: "envoy.filters.http.jwt_authn"
  value {
    fields {
      key: "auth@istioinaction.io"
      value {
        struct_value {
          fields {
            key: "exp"
            value {
              number_value: 4745145071
            }
          }
          fields {
            key: "group"
            value {
              string_value: "admin"
            }
          }
          fields {
            key: "iat"
            value {
              number_value: 1591545071
            }
          }
          fields {
            key: "iss"
            value {
              string_value: "auth@istioinaction.io"
            }
          }
          fields {
            key: "sub"
            value {
              string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
            }
          }
        }
      }
    }
  }
}
filter_metadata {
  key: "istio_authn"
  value {
    fields {
      key: "request.auth.claims"
      value {
        struct_value {
          fields {
            key: "group"
            value {
              list_value {
                values {
                  string_value: "admin"
                }
              }
            }
          }
          fields {
            key: "iss"
            value {
              list_value {
                values {
                  string_value: "auth@istioinaction.io"
                }
              }
            }
          }
          fields {
            key: "sub"
            value {
              list_value {
                values {
                  string_value: "218d3fb9-4628-4d20-943c-124281c80e7b"
                }
              }
            }
          }
        }
      }
    }
    fields {
      key: "request.auth.principal"
      value {
        string_value: "auth@istioinaction.io/218d3fb9-4628-4d20-943c-124281c80e7b"
      }
    }
    fields {
      key: "request.auth.raw_claims"
      value {
        string_value: "{\"exp\":4745145071,\"sub\":\"218d3fb9-4628-4d20-943c-124281c80e7b\",\"group\":\"admin\",\"iat\":1591545071,\"iss\":\"auth@istioinaction.io\"}"
      }
    }
  }
}
	thread=68
2025-05-10T10:13:54.908120Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:154	enforced allowed, matched policy ns[istio-system]-policy[allow-mesh-all-ops-admin]-rule[0]	thread=68
[2025-05-10T10:13:54.907Z] "POST /api/catalog HTTP/1.1" 200 - via_upstream - "-" 44 357 6 5 "172.18.0.1" "curl/8.13.0" "ebbeded3-425e-9e3b-a5e3-35b565dd0d57" "webapp.istioinaction.io:30000" "10.10.0.18:8080" outbound|80||webapp.istioinaction.svc.cluster.local 10.10.0.6:34258 10.10.0.6:8080 172.18.0.1:53972 - -

🤝 커스텀 외부 인가 서비스와 통합하기

1. 기존 인증/인가 정책 삭제 및 실습 앱 재배포

1
2
3
4
5
6
7
8
# 기존 인증/인가 정책 모두 삭제
kubectl delete authorizationpolicy,peerauthentication,requestauthentication --all -n istio-system

# 실습 애플리케이션 배포
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction
kubectl apply -f services/webapp/istio/webapp-catalog-gw-vs.yaml -n istioinaction
kubectl apply -f ch9/sleep.yaml -n default

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
authorizationpolicy.security.istio.io "allow-all-with-jwt-to-webapp" deleted
authorizationpolicy.security.istio.io "allow-mesh-all-ops-admin" deleted
authorizationpolicy.security.istio.io "app-gw-requires-jwt" deleted
requestauthentication.security.istio.io "jwt-token-request-authn" deleted
serviceaccount/catalog unchanged
service/catalog unchanged
deployment.apps/catalog unchanged
serviceaccount/webapp unchanged
service/webapp unchanged
deployment.apps/webapp unchanged
gateway.networking.istio.io/coolstore-gateway created
virtualservice.networking.istio.io/webapp-virtualservice configured
serviceaccount/sleep unchanged
service/sleep unchanged
deployment.apps/sleep unchanged

2. 외부 인가 샘플 파일 목록 확인

1
2
docker exec -it myk8s-control-plane bash
root@myk8s-control-plane:/# ls -l istio-$ISTIOV/samples/extauthz/

✅ 출력

1
2
3
4
5
6
total 24
-rw-r--r-- 1 root root 4238 Oct 11  2023 README.md
drwxr-xr-x 3 root root 4096 Oct 11  2023 cmd
drwxr-xr-x 2 root root 4096 Oct 11  2023 docker
-rw-r--r-- 1 root root 1330 Oct 11  2023 ext-authz.yaml
-rw-r--r-- 1 root root 2369 Oct 11  2023 local-ext-authz.yaml

3. 외부 인가 샘플 배포 YAML 내용 확인

1
root@myk8s-control-plane:/# cat istio-$ISTIOV/samples/extauthz/ext-authz.yaml

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: v1
kind: Service
metadata:
  name: ext-authz
  labels:
    app: ext-authz
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 8000
  - name: grpc
    port: 9000
    targetPort: 9000
  selector:
    app: ext-authz
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ext-authz
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ext-authz
  template:
    metadata:
      labels:
        app: ext-authz
    spec:
      containers:
      - image: gcr.io/istio-testing/ext-authz:latest
        imagePullPolicy: IfNotPresent
        name: ext-authz
        ports:
        - containerPort: 8000
        - containerPort: 9000
---

4. 외부 인가 샘플 서비스 및 디플로이 배포

1
2
3
4
5
root@myk8s-control-plane:/# kubectl apply -f istio-$ISTIOV/samples/extauthz/ext-authz.yaml -n istioinaction

# 결과
service/ext-authz created
deployment.apps/ext-authz created

5. 외부 인가 서비스 설치 완료 후 상태 확인

1
2
3
root@myk8s-control-plane:/# exit

kubectl get deploy,svc ext-authz -n istioinaction

✅ 출력

1
2
3
4
5
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ext-authz   1/1     1            1           57s

NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE
service/ext-authz   ClusterIP   10.200.1.158   <none>        8000/TCP,9000/TCP   57s

6. 외부 인가 서비스 로그 실시간 보기

1
kubectl logs -n istioinaction -l app=ext-authz -c ext-authz -f

🔧 이스티오에 외부 인가 설정하기

1. Istio ConfigMap에 외부 인가 설정 추가

1
kubectl edit -n istio-system cm istio

아래 내용 추가

1
2
3
4
5
6
7
8
...
    extensionProviders:
    - name: "sample-ext-authz-http"
      envoyExtAuthzHttp:
        service: "ext-authz.istioinaction.svc.cluster.local"
        port: "8000"
        includeRequestHeadersInCheck: ["x-ext-authz"]
...

1
configmap/istio edited

2. ConfigMap 변경 내용 확인

1
kubectl describe -n istio-system cm istio

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Name:         istio
Namespace:    istio-system
Labels:       install.operator.istio.io/owning-resource=unknown
              install.operator.istio.io/owning-resource-namespace=istio-system
              istio.io/rev=default
              operator.istio.io/component=Pilot
              operator.istio.io/managed=Reconcile
              operator.istio.io/version=1.17.8
              release=istio
Annotations:  <none>

Data
====
mesh:
----
accessLogFile: /dev/stdout
defaultConfig:
  discoveryAddress: istiod.istio-system.svc:15012
  proxyMetadata: {}
  tracing:
    zipkin:
      address: zipkin.istio-system:9411
enablePrometheusMerge: true
extensionProviders:
- name: "sample-ext-authz-http"
  envoyExtAuthzHttp:
    service: "ext-authz.istioinaction.svc.cluster.local"
    port: "8000"
    includeRequestHeadersInCheck: ["x-ext-authz"]
- envoyOtelAls:
    port: 4317
    service: opentelemetry-collector.istio-system.svc.cluster.local
  name: otel
- name: skywalking
  skywalking:
    port: 11800
    service: tracing.istio-system.svc.cluster.local
rootNamespace: istio-system
trustDomain: cluster.local

meshNetworks:
----
networks: {}

BinaryData
====

Events:  <none>

⚙️ 커스텀 AuthorizationPolicy 리소스 사용하기

1. 커스텀 AuthorizationPolicy 리소스 생성 (action: CUSTOM 설정)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat << EOF | kubectl apply -f -
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: ext-authz
  namespace: istioinaction
spec:
  selector:
    matchLabels:
      app: webapp
  action: CUSTOM    # custom action 사용
  provider:
    name: sample-ext-authz-http  # meshconfig 이름과 동일해야 한다
  rules:
  - to:
    - operation:
        paths: ["/*"]  # 인가 정책을 적용할 경로
EOF

kubectl get AuthorizationPolicy -A

✅ 출력

1
2
3
4
authorizationpolicy.security.istio.io/ext-authz created

NAMESPACE       NAME        AGE
istioinaction   ext-authz   0s

2. webapp 프록시의 로그 레벨을 디버그로 설정

1
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/webapp -n istioinaction --level rbac:debug

✅ 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
webapp-7685bcb84-l89bs.istioinaction:
active loggers:
  admin: warning
  alternate_protocols_cache: warning
  aws: warning
  assert: warning
  backtrace: warning
  cache_filter: warning
  client: warning
  config: warning
  connection: warning
  conn_handler: warning
  decompression: warning
  dns: warning
  dubbo: warning
  envoy_bug: warning
  ext_authz: warning
  ext_proc: warning
  rocketmq: warning
  file: warning
  filter: warning
  forward_proxy: warning
  grpc: warning
  happy_eyeballs: warning
  hc: warning
  health_checker: warning
  http: warning
  http2: warning
  hystrix: warning
  init: warning
  io: warning
  jwt: warning
  kafka: warning
  key_value_store: warning
  lua: warning
  main: warning
  matcher: warning
  misc: error
  mongo: warning
  multi_connection: warning
  oauth2: warning
  quic: warning
  quic_stream: warning
  pool: warning
  rate_limit_quota: warning
  rbac: debug
  rds: warning
  redis: warning
  router: warning
  runtime: warning
  stats: warning
  secret: warning
  tap: warning
  testing: warning
  thrift: warning
  tracing: warning
  upstream: warning
  udp: warning
  wasm: warning
  websocket: warning

3. 외부 인가 로그 및 요청 확인을 위한 프록시와 인가 서비스 로그 모니터링

1
2
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f
kubectl logs -n istioinaction -l app=ext-authz -c ext-authz -f

4. 외부 인가 헤더 없이 요청 시 거부 확인

1
kubectl -n default exec -it deploy/sleep -- curl webapp.istioinaction/api/catalog

✅ 출력

1
denied by ext_authz for not found header `x-ext-authz: allow` in the request
1
2
3
4
5
6
7
8
9
10
11
12
2025-05-10T10:34:01.356206Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 10.10.0.16:59308, directRemoteIP: 10.10.0.16:59308, remoteIP: 10.10.0.16:59308,localAddress: 10.10.0.18:8080, ssl: none, headers: ':authority', 'webapp.istioinaction'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-forwarded-proto', 'http'
'x-request-id', '46dcabcb-4580-9409-b8ac-22f1651b7460'
, dynamicMetadata: 	thread=41
2025-05-10T10:34:01.356235Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:130	shadow denied, matched policy istio-ext-authz-ns[istioinaction]-policy[ext-authz]-rule[0]	thread=41
2025-05-10T10:34:01.356247Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:167	no engine, allowed by default	thread=41
[2025-05-10T10:34:01.356Z] "GET /api/catalog HTTP/1.1" 403 UAEX ext_authz_denied - "-" 0 76 10 10 "-" "curl/8.5.0" "46dcabcb-4580-9409-b8ac-22f1651b7460" "webapp.istioinaction" "-" inbound|8080|| - 10.10.0.18:8080 10.10.0.16:59308 - -
1
2025/05/10 10:34:01 [HTTP][denied]: GET webapp.istioinaction/api/catalog, headers: map[Content-Length:[0] X-B3-Parentspanid:[c78bfd0e2f123604] X-B3-Sampled:[1] X-B3-Spanid:[d8003510c68701f0] X-B3-Traceid:[db3d0a1efc9e54d816ddf94217d4bc9c] X-Envoy-Expected-Rq-Timeout-Ms:[600000] X-Envoy-Internal:[true] X-Forwarded-Client-Cert:[By=spiffe://cluster.local/ns/istioinaction/sa/default;Hash=51eb6a0a5ab9054d593b864abb50b243bf8e18ec622743afdf1f0508a825ef82;Subject="";URI=spiffe://cluster.local/ns/istioinaction/sa/webapp] X-Forwarded-For:[10.10.0.18] X-Forwarded-Proto:[https] X-Request-Id:[392167a4-3495-9b8b-8634-a14585488cda]], body: []

5. 외부 인가 헤더 포함 시 요청 허용 확인

1
kubectl -n default exec -it deploy/sleep -- curl -H "x-ext-authz: allow" webapp.istioinaction/api/catalog

✅ 출력

1
[{"id":1,"color":"amber","department":"Eyewear","name":"Elinor Glasses","price":"282.00"},{"id":2,"color":"cyan","department":"Clothing","name":"Atlas Shirt","price":"127.00"},{"id":3,"color":"teal","department":"Clothing","name":"Small Metal Shoes","price":"232.00"},{"id":4,"color":"red","department":"Watches","name":"Red Dragon Watch","price":"232.00"}]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2025-05-10T10:36:09.388730Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:114	checking request: requestedServerName: , sourceIP: 10.10.0.16:36274, directRemoteIP: 10.10.0.16:36274, remoteIP: 10.10.0.16:36274,localAddress: 10.10.0.18:8080, ssl: none, headers: ':authority', 'webapp.istioinaction'
':path', '/api/catalog'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.5.0'
'accept', '*/*'
'x-ext-authz', 'allow'
'x-forwarded-proto', 'http'
'x-request-id', 'f7ba6378-8b94-98b5-804c-1158cc25e3e1'
, dynamicMetadata: 	thread=41
2025-05-10T10:36:09.388755Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:130	shadow denied, matched policy istio-ext-authz-ns[istioinaction]-policy[ext-authz]-rule[0]	thread=41
2025-05-10T10:36:09.388764Z	debug	envoy rbac external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:167	no engine, allowed by default	thread=41
[2025-05-10T10:36:09.397Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 2 2 "-" "beegoServer" "f7ba6378-8b94-98b5-804c-1158cc25e3e1" "catalog.istioinaction:80" "10.10.0.17:3000" outbound|80||catalog.istioinaction.svc.cluster.local 10.10.0.18:45848 10.200.1.59:80 10.10.0.18:60356 - default
[2025-05-10T10:36:09.388Z] "GET /api/catalog HTTP/1.1" 200 - via_upstream - "-" 0 357 11 3 "-" "curl/8.5.0" "f7ba6378-8b94-98b5-804c-1158cc25e3e1" "webapp.istioinaction" "10.10.0.18:8080" inbound|8080|| 127.0.0.6:43391 10.10.0.18:8080 10.10.0.16:36274 - default
1
2025/05/10 10:36:09 [HTTP][allowed]: GET webapp.istioinaction/api/catalog, headers: map[Content-Length:[0] X-B3-Parentspanid:[76ee940f62c769cd] X-B3-Sampled:[1] X-B3-Spanid:[26d2476cffea552c] X-B3-Traceid:[c686c0a213cbfb800d4abde649577f59] X-Envoy-Expected-Rq-Timeout-Ms:[600000] X-Envoy-Internal:[true] X-Ext-Authz:[allow] X-Forwarded-Client-Cert:[By=spiffe://cluster.local/ns/istioinaction/sa/default;Hash=51eb6a0a5ab9054d593b864abb50b243bf8e18ec622743afdf1f0508a825ef82;Subject="";URI=spiffe://cluster.local/ns/istioinaction/sa/webapp] X-Forwarded-For:[10.10.0.18] X-Forwarded-Proto:[https] X-Request-Id:[c699527e-b8d5-9860-b0a9-ad9170c00057]], body: []

This post is licensed under CC BY 4.0 by the author.