セキュリティの問題

エンドユーザー認証が失敗する

Istioを使用すると、リクエスト認証ポリシーを通じてエンドユーザーの認証を有効にできます。ポリシーの仕様のトラブルシューティングを行うには、次の手順に従ってください。

  1. jwksUriが設定されていない場合は、JWT発行者がURL形式であり、url + /.well-known/openid-configurationをブラウザで開くことができることを確認してください。たとえば、JWT発行者がhttps://#の場合、https://#/.well-known/openid-configurationが有効なURLであり、ブラウザで開くことができることを確認してください。

    apiVersion: security.istio.io/v1
    kind: RequestAuthentication
    metadata:
      name: "example-3"
    spec:
      selector:
        matchLabels:
          app: httpbin
      jwtRules:
      - issuer: "testing@secure.istio.io"
        jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.24/security/tools/jwt/samples/jwks.json"
    
  2. JWTトークンがHTTPリクエストのAuthorizationヘッダーに配置されている場合は、JWTトークンが有効であることを確認してください(期限切れなど)。JWTトークンのフィールドは、jwt.ioなどのオンラインJWT解析ツールを使用してデコードできます。jwt.io

  3. istioctl proxy-configコマンドを使用して、ターゲットワークロードのEnvoyプロキシ設定を確認してください。

    上記の例に従ってポリシーを適用した後、次のコマンドを使用して、インバウンドポート80のlistener設定を確認します。ポリシーで指定された発行者とJWKSと一致する設定を持つenvoy.filters.http.jwt_authnフィルターが表示されるはずです。

    $ POD=$(kubectl get pod -l app=httpbin -n foo -o jsonpath={.items..metadata.name})
    $ istioctl proxy-config listener ${POD} -n foo --port 80 --type HTTP -o json
    <redacted>
                                {
                                    "name": "envoy.filters.http.jwt_authn",
                                    "typedConfig": {
                                        "@type": "type.googleapis.com/envoy.config.filter.http.jwt_authn.v2alpha.JwtAuthentication",
                                        "providers": {
                                            "origins-0": {
                                                "issuer": "testing@secure.istio.io",
                                                "localJwks": {
                                                    "inlineString": "*redacted*"
                                                },
                                                "payloadInMetadata": "testing@secure.istio.io"
                                            }
                                        },
                                        "rules": [
                                            {
                                                "match": {
                                                    "prefix": "/"
                                                },
                                                "requires": {
                                                    "requiresAny": {
                                                        "requirements": [
                                                            {
                                                                "providerName": "origins-0"
                                                            },
                                                            {
                                                                "allowMissing": {}
                                                            }
                                                        ]
                                                    }
                                                }
                                            }
                                        ]
                                    }
                                },
    <redacted>
    

認可が厳しすぎるか、緩すぎる

ポリシーYAMLファイルにタイプミスがないことを確認してください

よくある間違いの1つは、YAMLで意図せずに複数の項目を指定することです。次のポリシーを例として示します

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: example
  namespace: foo
spec:
  action: ALLOW
  rules:
  - to:
    - operation:
        paths:
        - /foo
  - from:
    - source:
        namespaces:
        - foo

パスが/foo**かつ**ソース名前空間がfooの場合、ポリシーによってリクエストが許可されると予想されるかもしれません。しかし、実際には、パスが/foo**または**ソース名前空間がfooの場合にリクエストが許可されます。これはより緩やかな条件です。

YAML構文では、from:の前にある-は、リスト内の新しい要素であることを意味します。これにより、ポリシーに1つのルールではなく2つのルールが作成されます。認可ポリシーでは、複数のルールはORのセマンティクスを持ちます。

この問題を解決するには、余分な-を削除して、パスが/foo**かつ**ソース名前空間がfooの場合にリクエストを許可するルールが1つだけになるようにポリシーを変更します。これはより厳しい条件です。

TCPポートでHTTP専用フィールドを使用していないことを確認してください

HTTP専用フィールド(例:hostpathheaders、JWTなど)は生のTCP接続には存在しないため、認可ポリシーはより厳しくなります。

ALLOWポリシーの場合、これらのフィールドは一致しません。DENYCUSTOMアクションの場合、これらのフィールドは常に一致すると見なされます。最終的な効果は、予期しない拒否を引き起こす可能性のある、より厳格なポリシーになります。

ポートが正しいプロトコルで適切に名前付けされていることを確認するために、Kubernetesサービス定義を確認してください。HTTP専用フィールドをポートで使用している場合は、ポート名にhttp-プレフィックスが付いていることを確認してください。

ポリシーが正しいターゲットに適用されていることを確認してください

ワークロードセレクターと名前空間を確認して、正しいターゲットに適用されていることを確認してください。有効な認可ポリシーを確認するには、istioctl x authz check POD-NAME.POD-NAMESPACEを実行します。

ポリシーで指定されたアクションに注意してください

  • 指定されていない場合、ポリシーはデフォルトでALLOWアクションを使用します。

  • ワークロードに複数のアクション(CUSTOMALLOWDENY)が同時に適用されている場合、リクエストを許可するにはすべてのアクションを満たす必要があります。言い換えれば、いずれかのアクションが拒否した場合、リクエストは拒否され、すべてのアクションが許可した場合のみ許可されます。

  • AUDITアクションはアクセス制御を強制せず、いずれの場合もリクエストを拒否しません。

評価順序の詳細については、認可の暗黙的な有効化を参照してください。

Istiodがポリシーを受け入れることを確認してください

Istiodは認可ポリシーを変換してプロキシに配布します。次の手順は、Istiodが期待通りに動作していることを確認するのに役立ちます。

  1. 次のコマンドを実行して、Istiodのデバッグログを有効にします。

    $ istioctl admin log --level authorization:debug
    
  2. 次のコマンドでIstiodログを取得します。

    $ kubectl logs $(kubectl -n istio-system get pods -l app=istiod -o jsonpath='{.items[0].metadata.name}') -c discovery -n istio-system
    
  3. 出力を確認し、エラーがないことを確認します。たとえば、次のようなものが見られる場合があります。

    2021-04-23T20:53:29.507314Z info ads Push debounce stable[31] 1: 100.981865ms since last change, 100.981653ms since last push, full=true
    2021-04-23T20:53:29.507641Z info ads XDS: Pushing:2021-04-23T20:53:29Z/23 Services:15 ConnectedEndpoints:2  Version:2021-04-23T20:53:29Z/23
    2021-04-23T20:53:29.507911Z debug authorization Processed authorization policy for httpbin-74fb669cc6-lpscm.foo with details:
        * found 0 CUSTOM actions
    2021-04-23T20:53:29.508077Z debug authorization Processed authorization policy for curl-557747455f-6dxbl.foo with details:
        * found 0 CUSTOM actions
    2021-04-23T20:53:29.508128Z debug authorization Processed authorization policy for httpbin-74fb669cc6-lpscm.foo with details:
        * found 1 DENY actions, 0 ALLOW actions, 0 AUDIT actions
        * generated config from rule ns[foo]-policy[deny-path-headers]-rule[0] on HTTP filter chain successfully
        * built 1 HTTP filters for DENY action
        * added 1 HTTP filters to filter chain 0
        * added 1 HTTP filters to filter chain 1
    2021-04-23T20:53:29.508158Z debug authorization Processed authorization policy for curl-557747455f-6dxbl.foo with details:
        * found 0 DENY actions, 0 ALLOW actions, 0 AUDIT actions
    2021-04-23T20:53:29.509097Z debug authorization Processed authorization policy for curl-557747455f-6dxbl.foo with details:
        * found 0 CUSTOM actions
    2021-04-23T20:53:29.509167Z debug authorization Processed authorization policy for curl-557747455f-6dxbl.foo with details:
        * found 0 DENY actions, 0 ALLOW actions, 0 AUDIT actions
    2021-04-23T20:53:29.509501Z debug authorization Processed authorization policy for httpbin-74fb669cc6-lpscm.foo with details:
        * found 0 CUSTOM actions
    2021-04-23T20:53:29.509652Z debug authorization Processed authorization policy for httpbin-74fb669cc6-lpscm.foo with details:
        * found 1 DENY actions, 0 ALLOW actions, 0 AUDIT actions
        * generated config from rule ns[foo]-policy[deny-path-headers]-rule[0] on HTTP filter chain successfully
        * built 1 HTTP filters for DENY action
        * added 1 HTTP filters to filter chain 0
        * added 1 HTTP filters to filter chain 1
        * generated config from rule ns[foo]-policy[deny-path-headers]-rule[0] on TCP filter chain successfully
        * built 1 TCP filters for DENY action
        * added 1 TCP filters to filter chain 2
        * added 1 TCP filters to filter chain 3
        * added 1 TCP filters to filter chain 4
    2021-04-23T20:53:29.510903Z info ads LDS: PUSH for node:curl-557747455f-6dxbl.foo resources:18 size:85.0kB
    2021-04-23T20:53:29.511487Z info ads LDS: PUSH for node:httpbin-74fb669cc6-lpscm.foo resources:18 size:86.4kB
    

    これは、Istiodが生成したことを示しています。

    • ワークロードhttpbin-74fb669cc6-lpscm.fooに対するポリシーns[foo]-policy[deny-path-headers]-rule[0]を持つHTTPフィルター構成。

    • ワークロードhttpbin-74fb669cc6-lpscm.fooに対するポリシーns[foo]-policy[deny-path-headers]-rule[0]を持つTCPフィルター構成。

Istiodがプロキシにポリシーを正しく配布することを確認してください

Istiodは認可ポリシーをプロキシに配布します。次の手順は、istiodが期待通りに動作していることを確認するのに役立ちます。

  1. 次のコマンドを実行して、httpbinワークロードのプロキシ構成ダンプを取得します。

    $ kubectl exec  $(kubectl get pods -l app=httpbin -o jsonpath='{.items[0].metadata.name}') -c istio-proxy -- pilot-agent request GET config_dump
    
  2. ログを確認して確認します。

    • ログには、受信リクエストごとに認可ポリシーを適用するenvoy.filters.http.rbacフィルターが含まれています。
    • 認可ポリシーを更新した後、Istioはそれに応じてフィルターを更新します。
  3. 次の出力は、httpbinのプロキシが、パス/headersへのアクセスを拒否するルールを持つenvoy.filters.http.rbacフィルターを有効にしていることを意味します。

    {
     "name": "envoy.filters.http.rbac",
     "typed_config": {
      "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC",
      "rules": {
       "action": "DENY",
       "policies": {
        "ns[foo]-policy[deny-path-headers]-rule[0]": {
         "permissions": [
          {
           "and_rules": {
            "rules": [
             {
              "or_rules": {
               "rules": [
                {
                 "url_path": {
                  "path": {
                   "exact": "/headers"
                  }
                 }
                }
               ]
              }
             }
            ]
           }
          }
         ],
         "principals": [
          {
           "and_ids": {
            "ids": [
             {
              "any": true
             }
            ]
           }
          }
         ]
        }
       }
      },
      "shadow_rules_stat_prefix": "istio_dry_run_allow_"
     }
    },
    

プロキシがポリシーを正しく適用することを確認してください

プロキシは最終的に認可ポリシーを適用します。次の手順は、プロキシが期待通りに動作していることを確認するのに役立ちます。

  1. 次のコマンドを使用して、プロキシで認可デバッグログを有効にします。

    $ istioctl proxy-config log deploy/httpbin --level "rbac:debug"
    
  2. 次の出力があることを確認してください。

    active loggers:
      ... ...
      rbac: debug
      ... ...
    
  3. いくつかのリクエストをhttpbinワークロードに送信して、いくつかのログを生成します。

  4. 次のコマンドでプロキシログを出力します。

    $ kubectl logs $(kubectl get pods -l app=httpbin -o jsonpath='{.items[0].metadata.name}') -c istio-proxy
    
  5. 出力を確認して確認します。

    • 出力ログには、リクエストが許可されたか拒否されたかによって、それぞれenforced allowedまたはenforced deniedが表示されます。

    • 認可ポリシーは、リクエストから抽出されたデータが必要です。

  6. パス/httpbinのリクエストの出力例を次に示します。

    ...
    2021-04-23T20:43:18.552857Z debug envoy rbac checking request: requestedServerName: outbound_.8000_._.httpbin.foo.svc.cluster.local, sourceIP: 10.44.3.13:46180, directRemoteIP: 10.44.3.13:46180, remoteIP: 10.44.3.13:46180,localAddress: 10.44.1.18:80, ssl: uriSanPeerCertificate: spiffe://cluster.local/ns/foo/sa/curl, dnsSanPeerCertificate: , subjectPeerCertificate: , headers: ':authority', 'httpbin:8000'
    ':path', '/headers'
    ':method', 'GET'
    ':scheme', 'http'
    'user-agent', 'curl/7.76.1-DEV'
    'accept', '*/*'
    'x-forwarded-proto', 'http'
    'x-request-id', '672c9166-738c-4865-b541-128259cc65e5'
    'x-envoy-attempt-count', '1'
    'x-b3-traceid', '8a124905edf4291a21df326729b264e9'
    'x-b3-spanid', '21df326729b264e9'
    'x-b3-sampled', '0'
    'x-forwarded-client-cert', 'By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=d64cd6750a3af8685defbbe4dd8c467ebe80f6be4bfe9ca718e81cd94129fc1d;Subject="";URI=spiffe://cluster.local/ns/foo/sa/curl'
    , dynamicMetadata: filter_metadata {
      key: "istio_authn"
      value {
        fields {
          key: "request.auth.principal"
          value {
            string_value: "cluster.local/ns/foo/sa/curl"
          }
        }
        fields {
          key: "source.namespace"
          value {
            string_value: "foo"
          }
        }
        fields {
          key: "source.principal"
          value {
            string_value: "cluster.local/ns/foo/sa/curl"
          }
        }
        fields {
          key: "source.user"
          value {
            string_value: "cluster.local/ns/foo/sa/curl"
          }
        }
      }
    }
    
    2021-04-23T20:43:18.552910Z debug envoy rbac enforced denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
    ...
    

    ログenforced denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]は、リクエストがポリシーns[foo]-policy[deny-path-headers]-rule[0]によって拒否されたことを意味します。

  7. ドライランモードの認可ポリシーの出力例を次に示します。

    ...
    2021-04-23T20:59:11.838468Z debug envoy rbac checking request: requestedServerName: outbound_.8000_._.httpbin.foo.svc.cluster.local, sourceIP: 10.44.3.13:49826, directRemoteIP: 10.44.3.13:49826, remoteIP: 10.44.3.13:49826,localAddress: 10.44.1.18:80, ssl: uriSanPeerCertificate: spiffe://cluster.local/ns/foo/sa/curl, dnsSanPeerCertificate: , subjectPeerCertificate: , headers: ':authority', 'httpbin:8000'
    ':path', '/headers'
    ':method', 'GET'
    ':scheme', 'http'
    'user-agent', 'curl/7.76.1-DEV'
    'accept', '*/*'
    'x-forwarded-proto', 'http'
    'x-request-id', 'e7b2fdb0-d2ea-4782-987c-7845939e6313'
    'x-envoy-attempt-count', '1'
    'x-b3-traceid', '696607fc4382b50017c1f7017054c751'
    'x-b3-spanid', '17c1f7017054c751'
    'x-b3-sampled', '0'
    'x-forwarded-client-cert', 'By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=d64cd6750a3af8685defbbe4dd8c467ebe80f6be4bfe9ca718e81cd94129fc1d;Subject="";URI=spiffe://cluster.local/ns/foo/sa/curl'
    , dynamicMetadata: filter_metadata {
      key: "istio_authn"
      value {
        fields {
          key: "request.auth.principal"
          value {
            string_value: "cluster.local/ns/foo/sa/curl"
          }
        }
        fields {
          key: "source.namespace"
          value {
            string_value: "foo"
          }
        }
        fields {
          key: "source.principal"
          value {
            string_value: "cluster.local/ns/foo/sa/curl"
          }
        }
        fields {
          key: "source.user"
          value {
            string_value: "cluster.local/ns/foo/sa/curl"
          }
        }
      }
    }
    
    2021-04-23T20:59:11.838529Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
    2021-04-23T20:59:11.838538Z debug envoy rbac no engine, allowed by default
    ...
    

    ログshadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]は、リクエストが**ドライラン**ポリシーns[foo]-policy[deny-path-headers]-rule[0]によって拒否されることを意味します。

    ログno engine, allowed by defaultは、ドライランポリシーがワークロードの唯一のポリシーであるため、リクエストが実際に許可されていることを意味します。

キーと証明書のエラー

Istioで使用されているキーや証明書の一部が正しくないと思われる場合は、任意のpodから内容を確認できます。

$ istioctl proxy-config secret curl-8f795f47d-4s4t7
RESOURCE NAME     TYPE           STATUS     VALID CERT     SERIAL NUMBER                               NOT AFTER                NOT BEFORE
default           Cert Chain     ACTIVE     true           138092480869518152837211547060273851586     2020-11-11T16:39:48Z     2020-11-10T16:39:48Z
ROOTCA            CA             ACTIVE     true           288553090258624301170355571152070165215     2030-11-08T16:34:52Z     2020-11-10T16:34:52Z

-o jsonフラグを渡すことで、完全な証明書の内容をopensslに渡して内容を分析できます。

$ istioctl proxy-config secret curl-8f795f47d-4s4t7 -o json | jq '[.dynamicActiveSecrets[] | select(.name == "default")][0].secret.tlsCertificate.certificateChain.inlineBytes' -r | base64 -d | openssl x509 -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            99:59:6b:a2:5a:f4:20:f4:03:d7:f0:bc:59:f5:d8:40
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: O = k8s.cluster.local
        Validity
            Not Before: Jun  4 20:38:20 2018 GMT
            Not After : Sep  2 20:38:20 2018 GMT
...
        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 Subject Alternative Name:
                URI:spiffe://cluster.local/ns/my-ns/sa/my-sa
...

表示された証明書に有効な情報が含まれていることを確認してください。特に、Subject Alternative NameフィールドはURI:spiffe://cluster.local/ns/my-ns/sa/my-saである必要があります。

相互TLSエラー

相互TLSに問題があると思われる場合は、まずIstiodが正常に動作していることを確認し、次にキーと証明書がサイドカーに正しく配信されていることを確認してください。

ここまですべて正常に動作していると思われる場合は、次に、正しい認証ポリシーが適用され、正しい宛先ルールが設定されていることを確認します。

クライアント側のサイドカーが相互TLSまたはプレーンテキストトラフィックを誤って送信する可能性があると思われる場合は、Grafanaワークロードダッシュボードを確認してください。アウトバウンドリクエストには、mTLSが使用されているかどうかが注釈付きで示されます。これを確認した後、クライアント側のサイドカーが誤動作していると判断した場合は、GitHubで問題を報告してください。

この情報は役に立ちましたか?
改善のための提案はありますか?

ご意見ありがとうございます!