はじめに
istioの挙動の確認をする。
実施環境について
- Mac M3+Kindの環境にて実施
- 手間をかけず動作確認したこともあり、ChatGPTを使って資材を用意
Let's Poc
セットアップ
環境構築スクリプト
#!/bin/bash
# --- Kindクラスタ作成用スクリプト ---
# 前提: Dockerインストール済み (Mac M3対応)
# 前提: istioctlインストール済み(https://istio.io/latest/docs/setup/getting-started/#download)
# Mac M3 (arm64) でも問題なく動作確認済み
# ✅ Mac環境向け補足 ✅
# - Docker Desktop (arm64版) 必須
# - NodePortアクセスは localhost から可能(例: http://localhost:18080)
# - Docker DesktopのResources→Networkでポート制限が無いか確認
# - istioctl はarm64バイナリあり
# クラスタ名
CLUSTER_NAME="istio-poc"
# Kindクラスタ構成ファイル作成
touch kind-config.yaml
cat <<EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30080
hostPort: 18080
protocol: TCP
- containerPort: 30443
hostPort: 18443
protocol: TCP
EOF
# クラスタ作成
kind create cluster --name $CLUSTER_NAME --config kind-config.yaml
# kubeconfig切り替え
echo "\n>>> 現在のコンテキスト:"
kubectl config current-context
# Istioインストール (demoプロファイル)
istioctl install --set profile=demo -y
# ✅ Ingress GatewayのServiceをNodePortに変更
kubectl patch svc istio-ingressgateway -n istio-system \
-p '{"spec": {"type": "NodePort", "ports": [{"name": "http2","port": 80,"targetPort": 8080,"nodePort": 30080},{"name": "https","port": 443,"targetPort": 8443,"nodePort": 30443}]}}'
# ✅ サンプルTLS証明書作成
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 \
-subj "/CN=localhost" \
-keyout tls.key -out tls.crt
kubectl create -n istio-system secret tls httpbin-credential --key=tls.key --cert=tls.crt
# labelで自動インジェクション有効化
target_namespace="default"
kubectl label namespace $target_namespace istio-injection=enabled --overwrite
# サンプルアプリデプロイ (httpbin + sleep)
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.26/samples/httpbin/httpbin.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.26/samples/sleep/sleep.yaml
# ✅ Istio Gateway + VirtualService を適用 (HTTP + HTTPS対応)
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: httpbin-credential
hosts:
- "*"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "*"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /ip
route:
- destination:
host: httpbin
port:
number: 8000
EOF
# 動作確認コマンド例
echo "\n>>> curl from sleep to httpbin:\n"
kubectl exec deploy/sleep -c sleep -- curl -sS httpbin:8000/ip
# ✅ Mac環境: NodePortアクセス例 ✅
echo "\n>>> ブラウザやcurlでのアクセス例:"
echo "http://localhost:18080/ip"
echo "https://localhost:18443/ip (自己署名証明書のため警告あり)"
Pod経由で疎通確認。
kubectl exec deploy/sleep -c sleep -- curl -sS httpbin:8000/ip
{
"origin": "127.0.0.6:37291"
}
NodePortアクセス例で疎通確認。
curl http://localhost:18080/ip
{
"origin": "10.244.0.1"
}
# TLS
curl -k https://localhost:18443/ip
{
"origin": "10.244.0.1"
}
mTLS未対応Podのデプロイ(sleep-unmeshed)も検証のため作成しておく
kubectl create ns unmeshed
kubectl label ns unmeshed istio-injection=disabled
kubectl run sleep-unmeshed -n unmeshed --image=curlimages/curl -- sleep infinity
検証① - 承認ポリシー
PeerAuthenticationm(mTLS強制)
「メッシュ内部通信の暗号化」を制御するポリシーです。
- PeerAuthentication (mTLS強制)を適用
cat <<EOF | kubectl apply -f -
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: STRICT
EOF
動作確認(詳細)
- 外部 → Ingress Gateway (HTTP)
curl -v http://localhost:18080/ip
* Host localhost:18080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:18080...
* Connected to localhost (::1) port 18080
> GET /ip HTTP/1.1
> Host: localhost:18080
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< access-control-allow-credentials: true
< access-control-allow-origin: *
< content-type: application/json; charset=utf-8
< date: Sun, 20 Jul 2025 08:17:02 GMT
< content-length: 29
< x-envoy-upstream-service-time: 2
< server: istio-envoy
<
{
"origin": "10.244.0.1"
}
- 外部 → Ingress Gateway (HTTPS)
curl -vk https://localhost:18443/ip
* Host localhost:18443 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:18443...
* Connected to localhost (::1) port 18443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
* subject: CN=localhost
* start date: Jul 20 07:32:58 2025 GMT
* expire date: Jul 20 07:32:58 2026 GMT
* issuer: CN=localhost
* SSL certificate verify result: self signed certificate (18), continuing anyway.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://localhost:18443/ip
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: localhost:18443]
* [HTTP/2] [1] [:path: /ip]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
> GET /ip HTTP/2
> Host: localhost:18443
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
< access-control-allow-credentials: true
< access-control-allow-origin: *
< content-type: application/json; charset=utf-8
< date: Sun, 20 Jul 2025 08:16:13 GMT
< content-length: 29
< x-envoy-upstream-service-time: 1
< server: istio-envoy
<
{
"origin": "10.244.0.1"
}
* Connection #0 to host localhost left intact
- メッシュ内部(sleep → httpbin)
kubectl exec deploy/sleep -c sleep -- curl -v httpbin:8000/ip
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Host httpbin:8000 was resolved.
* IPv6: (none)
* IPv4: 10.96.244.2
* Trying 10.96.244.2:8000...
* Connected to httpbin (10.96.244.2) port 8000
* using HTTP/1.x
> GET /ip HTTP/1.1
> Host: httpbin:8000
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< access-control-allow-credentials: true
< access-control-allow-origin: *
< content-type: application/json; charset=utf-8
< date: Sun, 20 Jul 2025 08:07:04 GMT
< content-length: 34
< x-envoy-upstream-service-time: 0
< server: envoy
<
{ [34 bytes data]
100 34 100 34 0 0 13583 0 --:--:-- --:--:-- --:--:-- 17000
* Connection #0 to host httpbin left intact
{
"origin": "127.0.0.6:42037"
}
- メッシュ内部(非mTLS Pod → httpbin)※サイドカー無しPodからはmTLS未対応で拒否
kubectl exec -n unmeshed sleep-unmeshed -- curl -v http://httpbin.default.svc.cluster.local:8000/ip
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Host httpbin.default.svc.cluster.local:8000 was resolved.
* IPv6: (none)
* IPv4: 10.96.244.2
* Trying 10.96.244.2:8000...
* Connected to httpbin.default.svc.cluster.local (10.96.244.2) port 8000
* using HTTP/1.x
> GET /ip HTTP/1.1
> Host: httpbin.default.svc.cluster.local:8000
> User-Agent: curl/8.15.0
> Accept: */*
>
* Recv failure: Connection reset by peer
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
* closing connection #0
curl: (56) Recv failure: Connection reset by peer
command terminated with exit code 56
動作まとめ:mTLS(STRICT)のみ適用時の挙動
| 通信経路 | 挙動 | 説明 |
|---|---|---|
| 外部 → Ingress Gateway (HTTP) | ✅ 成功 | 外部(NodePort経由)からのHTTPアクセスはmTLS非対象。例: http://localhost:18080/ip
|
| 外部 → Ingress Gateway (HTTPS) | ✅ 成功 | HTTPS(TLS)は通常通り動作。自己署名証明書使用。例: https://localhost:18443/ip
|
| メッシュ内部(sleep → httpbin) | ✅ 成功 | IstioサイドカーありPod間通信はmTLSで成功。例: kubectl exec sleep -- curl httpbin:8000/ip
|
| 非メッシュPod → httpbin | ❌ 失敗 | サイドカー無しPodからはmTLS未対応で拒否。例: curl (56) Recv failure: Connection reset by peer
|
補足
-
PeerAuthentication(mode:STRICT) は メッシュ内部通信 のみmTLSを強制します。 - Ingress Gateway経由の通信は対象外。HTTP/HTTPSは通常通り通過。
- 外部通信もブロックしたい場合は
AuthorizationPolicyが必要です。
AuthorizationPolicy
Podレベルのアクセス制御 を行うためのポリシーです。
通信の「許可(ALLOW)」または「拒否(DENY)」をルールベースで定義できます。
- AuthorizationPolicy(sleep Pod からの通信のみ許可)を適用
cat <<EOF | kubectl apply -f -
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: httpbin-allow-sleep
namespace: default
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/sleep"]
EOF
動作確認(詳細)
- 外部 → Ingress Gateway (HTTP)
curl -v http://localhost:18080/ip
* Host localhost:18080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:18080...
* Connected to localhost (::1) port 18080
> GET /ip HTTP/1.1
> Host: localhost:18080
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 403 Forbidden
< content-length: 19
< content-type: text/plain
< date: Sun, 20 Jul 2025 08:29:32 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 9
<
* Connection #0 to host localhost left intact
RBAC: access denied%
- 外部 → Ingress Gateway (HTTPS)
curl -vk https://localhost:18443/ip
* Host localhost:18443 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:18443...
* Connected to localhost (::1) port 18443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
* subject: CN=localhost
* start date: Jul 20 07:32:58 2025 GMT
* expire date: Jul 20 07:32:58 2026 GMT
* issuer: CN=localhost
* SSL certificate verify result: self signed certificate (18), continuing anyway.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://localhost:18443/ip
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: localhost:18443]
* [HTTP/2] [1] [:path: /ip]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
> GET /ip HTTP/2
> Host: localhost:18443
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/2 403
< content-length: 19
< content-type: text/plain
< date: Sun, 20 Jul 2025 08:29:58 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 1
<
* Connection #0 to host localhost left intact
RBAC: access denied%
- メッシュ内部(sleep → httpbin)
kubectl exec deploy/sleep -c sleep -- curl -vs httpbin:8000/ip
* Host httpbin:8000 was resolved.
* IPv6: (none)
* IPv4: 10.96.244.2
* Trying 10.96.244.2:8000...
* Connected to httpbin (10.96.244.2) port 8000
* using HTTP/1.x
> GET /ip HTTP/1.1
> Host: httpbin:8000
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< access-control-allow-credentials: true
< access-control-allow-origin: *
< content-type: application/json; charset=utf-8
< date: Sun, 20 Jul 2025 08:30:33 GMT
< content-length: 34
< x-envoy-upstream-service-time: 0
< server: envoy
<
{ [34 bytes data]
* Connection #0 to host httpbin left intact
{
"origin": "127.0.0.6:45949"
}
- 非メッシュPod(sleep-unmeshed)
kubectl exec -n unmeshed sleep-unmeshed -- curl -vs http://httpbin.default.svc.cluster.local:8000/ip
* Host httpbin.default.svc.cluster.local:8000 was resolved.
* IPv6: (none)
* IPv4: 10.96.244.2
* Trying 10.96.244.2:8000...
* Connected to httpbin.default.svc.cluster.local (10.96.244.2) port 8000
* using HTTP/1.x
> GET /ip HTTP/1.1
> Host: httpbin.default.svc.cluster.local:8000
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
* Recv failure: Connection reset by peer
* closing connection #0
command terminated with exit code 56
- メッシュ内部別Pod(例: sleep2)
sleep2 をデプロイ(同じ namespace)
kubectl run sleep2 --image=curlimages/curl -- sleep infinity
疎通確認
kubectl exec sleep2 -- curl -sv httpbin:8000/ip
* Host httpbin:8000 was resolved.
* IPv6: (none)
* IPv4: 10.96.244.2
* Trying 10.96.244.2:8000...
* Connected to httpbin (10.96.244.2) port 8000
* using HTTP/1.x
> GET /ip HTTP/1.1
> Host: httpbin:8000
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 403 Forbidden
< content-length: 19
< content-type: text/plain
< date: Sun, 20 Jul 2025 08:32:06 GMT
< server: envoy
< x-envoy-upstream-service-time: 5
<
{ [19 bytes data]
* Connection #0 to host httpbin left intact
RBAC: access denied%
動作まとめ:mTLS(STRICT)+ AuthorizationPolicy の挙動
| 通信経路 | mTLSのみ (AuthorizationPolicyなし) | mTLS + AuthorizationPolicyあり | 説明 |
|---|---|---|---|
| 外部 → Ingress Gateway (HTTP) | ✅ 成功 | ❌ 拒否 | AuthorizationPolicyが適用されると、外部アクセスも対象になるため拒否される |
| 外部 → Ingress Gateway (HTTPS) | ✅ 成功 | ❌ 拒否 | 同上、HTTPSも拒否される |
| メッシュ内部(sleep → httpbin) | ✅ 成功 | ✅ 成功 |
sleep のServiceAccountは許可されるため成功 |
| 非メッシュPod(sleep-unmeshed) → httpbin | ❌ 失敗 | ❌ 失敗 | mTLS強制により通信失敗(AuthorizationPolicy以前の段階で失敗) |
| メッシュ内部別Pod(例: sleep2) → httpbin | ✅ 成功 | ❌ 拒否 |
sleep 以外のPodは principals 不一致で拒否される |
RequestAuthentication
RequestAuthentication は HTTPリクエストのJWTトークン検証 に使用します。
→ mTLS が「通信の暗号化」
→ RequestAuthentication は「HTTPリクエストの認証(JWT)」にフォーカスします。
[内部クライアント] ──> [Ingress Gateway] ──> [httpbin]
│
+─────────┘
│ mTLS (PeerAuthentication)
[外部] ──> [Ingress Gateway] ──> [httpbin]
│
+─────────┘
│ JWTトークン検証 (RequestAuthentication)
※検証をわかりやすくするために、AuthorizationPolicy(sleep Pod からの通信のみ許可)のポリシーは一度削除
- RequestAuthentication マニフェスト例(JWT認証設定)
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: httpbin-jwt
namespace: default
spec:
selector:
matchLabels:
app: httpbin
jwtRules:
- issuer: "testing@secure.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.26/security/tools/jwt/samples/jwks.json"
- AuthorizationPolicy
# Istioは mTLS と JWT の両方の認証情報を同時に使わないケースがある ため、以下動作をします:
# • メッシュ内通信(mTLS)の場合:
# • requestPrincipal は基本 空文字(””) になることが多い(特に Pod → Pod の時)
# • JWTは通常 外部(Ingress Gateway)経由のみ評価対象
# ということで以下で分離
# Podからは principals 許可、外部は requestPrincipals 許可。例:ルールを2つに分ける。
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: httpbin-require-jwt
namespace: default
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/default/sa/sleep
- from:
- source:
requestPrincipals:
- "testing@secure.istio.io/testing@secure.istio.io"
- これを適用すると、「PeerAuthentication+AuthorizationPolicyあり」の構成となる。
メッシュ外からのトラフィック(Ingress Gateway経由)は mTLS無し なので、デフォルトで拒否 されます。
つまり 外部からのHTTP(S)アクセスは、mTLSレイヤーでFail → AuthorizationPolicyの前で403(RBAC) が返る。 - principalsの指定がない場合、mTLSが強制されていることが保証できないためか、sleep Pod経由であっても403応答となる。なので必須で指定する必要があった。
動作確認(詳細)
- 準備
TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.26/security/tools/jwt/samples/demo.jwt -s)
echo $TOKEN
> eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
- sleep Pod → JWT無し → 200 OK
kubectl exec deploy/sleep -c sleep -- curl -sv httpbin:8000/ip
* Host httpbin:8000 was resolved.
* IPv6: (none)
* IPv4: 10.96.244.2
* Trying 10.96.244.2:8000...
* Connected to httpbin (10.96.244.2) port 8000
* using HTTP/1.x
> GET /ip HTTP/1.1
> Host: httpbin:8000
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< access-control-allow-credentials: true
< access-control-allow-origin: *
< content-type: application/json; charset=utf-8
< date: Sun, 20 Jul 2025 10:25:43 GMT
< content-length: 34
< x-envoy-upstream-service-time: 4
< server: envoy
<
{ [34 bytes data]
* Connection #0 to host httpbin left intact
{
"origin": "127.0.0.6:53881"
}
- sleep Pod → JWTあり → 200 OK
kubectl exec deploy/sleep -c sleep -- curl -sv -H "Authorization: Bearer $TOKEN" httpbin:8000/ip
* Host httpbin:8000 was resolved.
* IPv6: (none)
* IPv4: 10.96.244.2
* Trying 10.96.244.2:8000...
* Connected to httpbin (10.96.244.2) port 8000
* using HTTP/1.x
> GET /ip HTTP/1.1
> Host: httpbin:8000
> User-Agent: curl/8.15.0
> Accept: */*
> Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
>
* Request completely sent off
< HTTP/1.1 200 OK
< access-control-allow-credentials: true
< access-control-allow-origin: *
< content-type: application/json; charset=utf-8
< date: Sun, 20 Jul 2025 10:26:20 GMT
< content-length: 34
< x-envoy-upstream-service-time: 0
< server: envoy
<
{ [34 bytes data]
* Connection #0 to host httpbin left intact
{
"origin": "127.0.0.6:38319"
}
- sleep2 Pod → JWT無し → 403
kubectl exec sleep2 -- curl -sv httpbin:8000/ip
* Host httpbin:8000 was resolved.
* IPv6: (none)
* IPv4: 10.96.244.2
* Trying 10.96.244.2:8000...
* Connected to httpbin (10.96.244.2) port 8000
* using HTTP/1.x
> GET /ip HTTP/1.1
> Host: httpbin:8000
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
RBAC: access denied< HTTP/1.1 403 Forbidden
< content-length: 19
< content-type: text/plain
< date: Sun, 20 Jul 2025 10:27:41 GMT
< server: envoy
< x-envoy-upstream-service-time: 4
<
{ [19 bytes data]
* Connection #0 to host httpbin left intact
- sleep2 Pod → JWTあり → 403
kubectl exec sleep2 -- curl -sv -H "Authorization: Bearer $TOKEN" httpbin:8000/ip
* Host httpbin:8000 was resolved.
* IPv6: (none)
* IPv4: 10.96.244.2
* Trying 10.96.244.2:8000...
* Connected to httpbin (10.96.244.2) port 8000
* using HTTP/1.x
> GET /ip HTTP/1.1
> Host: httpbin:8000
> User-Agent: curl/8.15.0
> Accept: */*
> Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
>
* Request completely sent off
RBAC: access denied< HTTP/1.1 403 Forbidden
< content-length: 19
< content-type: text/plain
< date: Sun, 20 Jul 2025 10:28:40 GMT
< server: envoy
< x-envoy-upstream-service-time: 1
<
{ [19 bytes data]
* Connection #0 to host httpbin left intact
- 外部 → JWT無し → 403
curl -v http://localhost:18080/ip
* Host localhost:18080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:18080...
* Connected to localhost (::1) port 18080
> GET /ip HTTP/1.1
> Host: localhost:18080
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 403 Forbidden
< content-length: 19
< content-type: text/plain
< date: Sun, 20 Jul 2025 10:29:08 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 9
<
* Connection #0 to host localhost left intact
RBAC: access denied%
- 外部 → JWTあり → 200 OK
curl -v -H "Authorization: Bearer $TOKEN" http://localhost:18080/ip
* Host localhost:18080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:18080...
* Connected to localhost (::1) port 18080
> GET /ip HTTP/1.1
> Host: localhost:18080
> User-Agent: curl/8.7.1
> Accept: */*
> Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
>
* Request completely sent off
< HTTP/1.1 200 OK
< access-control-allow-credentials: true
< access-control-allow-origin: *
< content-type: application/json; charset=utf-8
< date: Sun, 20 Jul 2025 11:21:05 GMT
< content-length: 29
< x-envoy-upstream-service-time: 6
< server: istio-envoy
<
{
"origin": "10.244.0.1"
}
✅ 通信パターン別の動作
| 通信元 | JWTの有無 | mTLS状況 | 結果 | 説明 |
|---|---|---|---|---|
| sleep Pod | ❌ 無し | ✅ mTLS OK | ✅ 200 OK | ServiceAccount一致(principals許可) |
| sleep Pod | ✅ あり | ✅ mTLS OK | ✅ 200 OK | JWT無視、principals一致でOK |
| sleep2 Pod | ❌ 無し | ✅ mTLS OK | ❌ 403 Forbidden | principals不一致で拒否 |
| sleep2 Pod | ✅ あり | ✅ mTLS OK | ❌ 403 Forbidden | principals不一致で拒否 |
| 外部 (Ingress Gateway) | ❌ 無し | ❌ mTLS無し | ❌ 403 Forbidden | JWT無し拒否 |
| 外部 (Ingress Gateway) | ✅ あり | ❌ mTLS無し | ✅ 200 OK | JWT検証成功し requestPrincipals 一致でOK |