Cloud Service Mesh でのセキュリティの問題の解決

このセクションでは、Istio API を使用した Cloud Service Mesh の一般的な問題とその解決方法について説明します。さらにサポートが必要な場合は、サポートの利用をご覧ください。

Cloud Service Mesh では、Cloud Service Mesh 認証局または Istiod がメッシュ内のすべてのクラスタのワークロードに証明書を発行します。認証(例: mTLS)と認可ポリシー(例: allow/deny)が各クラスタに push されます。これらのポリシーにより、通信可能なワークロードとその方法が決まります。

TLS に関する問題

以降のセクションでは、Cloud Service Mesh で TLS 関連の問題を解決する方法について説明します。

このセクションの例では、変数 ${CTX} を使用します。これは、クラスタへのアクセスに使用するデフォルトの Kubernetes 構成ファイルのコンテキスト名です。次の例のように ${CTX} 変数を設定します。

export CTX=gke_PROJECT_ID_CLUSTER_LOCATION_CLUSTER_NAME

TLS の適用を確認する

サービスに TLS 接続が必要な場合、暗号化されていないテキスト リクエストが許可されていないことを確認します。

kubectl exec SOURCE_POD -n SOURCE_NAMESPACE -c \
    SOURCE_CONTAINER -- curl -v DESTINATION_URL

サービスで TLS 接続が必要な場合、このような暗号化されていないリクエストは失敗し、次のような出力が表示されます。

curl: (56) Recv failure: Connection reset by peer command terminated with exit code 56

mTLS 証明書を確認する

mTLS が有効になっている場合は、X-Forwarded-Client-Cert ヘッダーをチェックして、ワークロードの mTLS 証明書を確認します。手順は次のとおりです。

  1. httpbin サンプル サービスをデプロイします。これにより、受信したヘッダーを表示できます。

  2. curl を使用して X-Forwarded-Client-Cert ヘッダーを表示します。

    kubectl exec --context=${CTX} SOURCE_POD -n SOURCE_NAMESPACE -c \
    SOURCE_CONTAINER -- curl http://httpbin.sample:8000/headers -s | \
    grep X-Forwarded-Client-Cert

    次の例のように、X-Forwarded-Client-Cert ヘッダーに mTLS 証明書情報が含まれています。

    X-Forwarded-Client-Cert": "By=spiffe://lt-multicluster-t2-5-15-2020.svc.id.goog/ns/sample/sa/httpbin;Hash=0781d68adfdab85b08b6758ed502f352464e81166f065cc6acde9433337b4494;Subject=\"OU=istio_v1_cloud_workload,O=Google LLC,L=Mountain View,ST=California,C=US\";URI=spiffe://lt-multicluster-t2-5-15-2020.svc.id.goog/ns/sample/sa/sleep
  3. また、サイドカーで openssl を使用して証明書チェーン全体を確認することもできます。

    kubectl debug --image istio/base --target istio-proxy -it --context=${CTX} SOURCE_POD \
    -n SOURCE_NAMESPACE -- openssl s_client -alpn istio -showcerts -connect httpbin.sample:8000

    出力に証明書チェーンが表示されます。Mesh CA を使用している場合は、ルート証明書の CN に istio_v1_cloud_workload_root-signer-... が含まれていることを確認します。Istiod を認証局として使用する場合は、ルート証明書が O = <var>YOUR_TRUST_DOMAIN</var> で設定されていることを確認してください。

Istiod ログの TLS bad certificate エラー

ログに TLS handshake bad certificate エラーが記録されている場合、Istiod がサービスへの TLS 接続を確立に失敗していることを示している可能性があります。

ログ内の正規表現文字列 TLS handshake error.*bad certificate を使用して、これらのエラーを見つけることができます。

通常、こうしたエラーは情報提供を目的としたもので、一時的なものです。エラーの出現が続く場合は、システムに問題があることを示している可能性があります。

  1. istio-sidecar-injector MutatingWebhookConfiguration に CA バンドルがあることを確認してください。

    自動サイドカー インジェクションに使用されるサイドカー インジェクタ Webhook には、API サーバーと Istiod との安全な接続を確立するために CA バンドルが必要です。この CA バンドルは istiod によって構成にパッチが適用されていますが、上書きされる(Webhook 構成を再適用した場合など)可能性があります。

  2. CA バンドルが存在することを確認します。

    kubectl get mutatingwebhookconfiguration -l app=sidecar-injector -o=jsonpath='{.items[0].webhooks[0].clientConfig.caBundle}'
    

    出力が空でない場合、CA バンドルが構成されます。CA バンドルがない場合は、Webhook を再スキャンし、CA バンドルを再インストールできるように istiod を再起動します。

認証ポリシーの拒否ロギング

認可ポリシーの拒否ロギングについて詳しくは、拒否ロギングをご覧ください。

認証ポリシーが適用されない

認証ポリシーが適用されないという現象が発生している場合は、次のコマンドを使用して確認します。

kubectl exec --context=${CTX} -it SOURCE_POD -n SOURCE_NAMESPACE \
    -c SOURCE_CONTAINER -- curl DESTINATION_URL

出力に access denied メッセージが含まれている場合は、次のように認証ポリシーが正しく適用されていることを示します。

RBAC: access denied

認証ポリシーが適用されていないことを確認した場合は、名前空間へのアクセスを拒否します。次の例では、authz-ns という名前の名前空間へのアクセスを拒否します。

kubectl apply --context=${CTX} -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-authz-ns
  namespace: authz-ns
spec:
  {}
EOF

Istiod ログの customresourcedefinitions.apiextensions.k8s.io is forbidden エラー

次のようなエラーが表示されることがあります。

error failed to list CRDs: customresourcedefinitions.apiextensions.k8s.io is forbidden: User "system:serviceaccount:istio-system:istiod-service-account" cannot list resource "customresourcedefinitions" in API group "apiextensions.k8s.io" at the cluster scope

ログ内の正規表現文字列 /error.*cannot list resource/ を使用して、これらのエラーを見つけることができます。

Istiod の Deployment に適切な IAM バインディングがない場合、またはカスタム リソースを読み取るための RBAC 権限がない場合に、このエラーが発生することがあります。

  1. アカウントに IAM バインディングが欠落していないか確認してください。最初に、認証情報と権限が正しく設定されていることを確認してください。次に、以下のコマンドを使用して IAM バインディングが存在することを確認します。この例の場合、PROJECT_ID は gcloud config get-value project の出力で、PROJECT_NUMBER は gcloud projects list --filter="project_id=${PROJECT_ID}" --format="value(project_number)" の出力です。

    gcloud projects add-iam-policy-binding ${PROJECT_ID} --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-meshdataplane.iam.gserviceaccount.com" --role "roles/meshdataplane.serviceAgent"
  2. RBAC ルールが正しくインストールされていることを確認します。

  3. RBAC ルールがない場合は、asmcli install を再実行して再作成します。

  4. RBAC ルールが存在し、引き続きエラーが表示される場合は、ClusterRoleBindingsRoleBindings が適切な Kubernetes サービス アカウントに対して RBAC ルールを接続していることを確認します。また、istiod デプロイメントが指定されたサービス アカウントを使用していることも確認してください。

Istiod ログの serverca プロセスエラー

次のようなエラーが表示されることがあります。

Authentication failed: Authenticator ClientCertAuthenticator at index 0 got error

ログ内の正規表現文字列 /serverca.*Authentication failed:.*JWT/ を使用して、これらのエラーを見つけることができます。

このエラーは、JWT 発行元の構成に誤りがあるか、クライアントが期限切れのトークンを使用しているか、他のセキュリティ上の問題により、istiod の認証で接続が妨げられている場合に発生します。