複雑に絡み合ったマイクロサービス(MSA)環境では、数多くのサービスが互いに通信しています。このとき、このような疑問が浮かびます。
「今、私のサービスにリクエストを送ってきたあの相手、信頼できるのだろうか?」🤔
まるで自宅の玄関のように、誰でも自由に出入りさせるわけにはいきません。サービスメッシュの代表格であるIstioは、このようなセキュリティ問題を解決するために、非常に厳格で体系的な「身元確認」システムを備えています。それがピア認証(Peer Authentication)とリクエスト認証(Request Authentication)です。
この2つの方法がどのように私たちのサービスを安全に守るのか、全体像とともに詳しく掘り下げていきましょう。
[image 1 — download failed]
🗺️ まずは全体像から:誰のための認証か?
Istioの認証戦略を理解する最も簡単な方法は、「認証対象」が誰であるかを区別することです。
- サービス 🤝 サービス(機械間通信):内部のサービス同士が互いを信頼して通信できるか?
- ユーザー 👩💻➡️ サービス(人間/外部システムの通信):サービスを利用するエンドユーザーや外部システムが送信したリクエストを信頼できるか?
Istioは、これら2つのシナリオに合わせてそれぞれ異なる認証方式を提供します。これこそがピア認証とリクエスト認証の核心的な違いです。
(Source: istio.io)
1️⃣ ピア認証 (Peer Authentication): 「私たち同士は暗号で話す」🤫
これは、サービスメッシュ内部のワークロード(ポッド、サービス)が互いに通信する際に使用する認証方式です。つまり、サービス間(Service-to-Service)通信の信頼性を保証します。
まるでスパイ映画でエージェントが互いを確認するために暗号を唱えるようなものです。この暗号こそが相互TLS (mTLS)です。
✨ どのように動作しますか? (mTLS)
mTLSは、クライアントとサーバーが互いに証明書を提示して身元を確認する方式です。
- reviewsサービスがratingsサービスにリクエストを送信します。
- reviewsとratingsは通信を開始する前に、Istioが発行した証明書(certificate)を互いに交換します。
- 互いの証明書が有効であることを確認し、身元が証明されると、安全な暗号化トンネル(TLS)を生成します。🔒
- このトンネルを通じて、すべての通信内容は暗号化されて安全に伝達されます。
YAMLコードで見てみましょう
PeerAuthenticationポリシーを通じて、特定のネームスペースにmTLSを強制することができます。
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: "default"
namespace: "production" # 'production'ネームスペースに適用
spec:
mtls:
mode: STRICT # mTLS通信のみ許可!
- mode: STRICT:「パスワード(mTLS)を知らない者は絶対に通信不可!」という意味です。productionネームスペースのすべてのサービスはmTLSのみで通信する必要があります。平文(HTTP)リクエストはブロックされます。
- mode: PERMISSIVE:既存サービスとの互換性のために、mTLSと平文通信の両方を許可するモードです。mTLSを段階的に導入する際に便利です。
2️⃣ リクエスト認証 (Request Authentication): 「身分証明書(JWT)を見せていただけますか?」🎟️
これは、サービスメッシュの入り口(Ingress Gateway)で、最終ユーザー(End-User)や外部システムが送信したリクエストを認証する際に使用されます。
コンサート会場に入る際に、入り口でチケットを検査するようなものです。このとき使用される標準的なデジタルチケットがJWT(JSON Web Token)です。
✨ どのように動作しますか? (JWT)
JWTは、ユーザーの情報(誰であるか、どのような権限を持っているかなど)と署名を含む暗号化されたトークンです。
- ユーザーはログインを通じて認証サーバーからJWTを発行してもらいます。
- ユーザーはAPIをリクエストするたびに、HTTPヘッダー(例:Authorization: Bearer )にこのJWTを含めて送信します。
- Istio Ingress GatewayはRequestAuthenticationポリシーに従って、このJWTが有効であるかを検証します。
- 署名が有効で、期限切れでなく、発行元が信頼できる場合、リクエストは内部サービスに転送されます。
YAMLコードとRawデータで見てみましょう
RequestAuthenticationポリシーは、JWTの発行者(issuer)と公開鍵(JWKS)の場所を指定します。
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
name: "jwt-example"
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
jwtRules:
- issuer: "https://accounts.google.com" # JWT発行者
jwksUri: "https://www.googleapis.com/oauth2/v3/certs" # 公開鍵の場所
このポリシーは、istio-ingressgatewayに入ってくるリクエストに対して、発行者が
– サンプルJWT Rawデータ:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoidXNlcjEyMyIsImV4cCI6MTY3ODg4NjQwMCwiZW1haWwiOiJ0ZXN0QGV4YW1wbGUuY29tIn0.SIG_PART
(上記のトークンは3つの部分で構成されます:Header.Payload.Signature)
– デコードされたPayload:
{
"iss": "https://example.com",
"sub": "user123",
"exp": 1678886400,
"email": "test@example.com"
}
IstioはこのPayloadの内容を見て、iss(発行者)がポリシーと一致するか、exp(有効期限)が過ぎていないかなどを検証します。
🤔 よくある誤解を解消
- 「API Keyだけで認証してはいけませんか?」
- API Keyは主に「どのアプリケーション」がリクエストしたかを識別するために使用されます。一方、JWTは「どのユーザー」がリクエストしたか、そのユーザーの役割は何かなど、はるかに豊富な情報を含めることができ、ユーザー中心の認証により適しており、標準的です。
- 「内部ネットワークだから、サービス同士はHTTPで通信しても安全ではないですか?」
- 絶対に違います!🙅♂️ 「ゼロトラスト(Zero Trust)」セキュリティモデルによれば、内部ネットワークだからといって無条件に信頼してはなりません。もし1つのサービスがハッキングされた場合、そのサービスを通じて内部の他のすべてのサービスに攻撃が拡散する可能性があります。ピア認証(mTLS)は、このような内部拡散を防ぐ最も重要な防衛線です。
🏁 まとめ
Istioの2つの認証方式をもう一度要約してみましょう。
- ピア認証 (Peer Authentication):サービス間通信をmTLSで暗号化し、互いの身元を確認します。(内部セキュリティ強化🛡️)
- リクエスト認証 (Request Authentication):最終ユーザーのリクエストをJWTで検証し、認可されたユーザーのみアクセスを許可します。(外部境界セキュリティ🚪)
これら2つの認証メカニズムは連携して機能し、外部からの侵入と内部からの不正アクセスを両方遮断する強力な多層防御システムを構築します。Istioを通じてサービスのセキュリティを一段階アップグレードしてみてください!
コメントを残す