☸️ 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
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
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"
|
✅ 출력
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
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
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
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
| 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)
|
✅ 출력
(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
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
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
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
|
✅ 출력
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
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
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
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
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
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. 미인증 요청 허용을 위한 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
|
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
| [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
| [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
| [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
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
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
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
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
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"]
...
|
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: []
|