認可ポリシーの概要

1 か所で実行できるモノリシック アプリケーションとは異なり、グローバルに分散されたマイクロサービス アプリはネットワーク境界を越えて呼び出しを行います。このため、アプリケーションのエントリ ポイントが増え、悪意のある攻撃を受ける可能性が高くなります。また、Kubernetes Pod には一時的な IP が割り振られるため、従来の IP ベースのファイアウォール ルールでは、ワークロード間のアクセスを十分に保護することはできません。マイクロサービス アーキテクチャでは、セキュリティに対する新しいアプローチが必要です。Kubernetes サービス アカウントや Istio セキュリティ ポリシーなどのセキュリティ機能を搭載している Cloud Service Mesh は、アプリケーションの保護に役立つ優れた機能を提供します。

このページでは、アプリケーション オペレーターに向けた AuthorizationPolicy カスタム リソース(CR)の概要を説明します。認可ポリシーを使用すると、アプリケーション(L7)レイヤおよびトランスポート(L3 / 4)レイヤのワークロードに対するアクセス制御を有効にできます。認可ポリシーを構成して、サービスまたはユーザーが行える内容についての権限を指定します。

認可ポリシー

デフォルトでは、メッシュ内のサービス間(エンドユーザーとサービス間)のリクエストは許可されます。AuthorizationPolicy CR を使用して、ワークロードにきめ細かいポリシーを定義します。認可ポリシーを適用すると、Cloud Service Mesh はこれらのポリシーをサイドカー プロキシに配布します。ワークロードがリクエストを受信すると、サイドカー プロキシは認可ポリシーをチェックし、リクエストを許可するかどうかを決定します。

ポリシーの範囲

ポリシーは、サービス メッシュ全体、名前空間、または個々のワークロードに適用できます。

  • メッシュ全体のポリシーを適用するには、metadata:namespace フィールドでルート名前空間 istio-system を指定します。

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "mesh-wide"
      namespace: istio-system
    spec:
    ...
    
  • 名前空間にポリシーを適用するには、metadata:namespace フィールドに名前空間を指定します。

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "currencyservice"
      namespace: currencyservice
    spec:
    ...
    
  • ポリシーを特定のワークロードに制限するには、selector フィールドを追加します。

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "frontend"
      namespace: demo
    spec:
      selector:
        matchLabels:
          app: frontend
       ...
    

基本構造

認可ポリシーには、ポリシーの範囲、actionrules のリストが含まれます。

  • 前のセクションで説明したように、ポリシーの範囲は、メッシュ全体、名前空間、または特定のワークロードにすることが可能です。ポリシーの範囲を追加する場合は、selector フィールドにポリシーの対象を指定します。

  • action フィールドは、リクエストに対して ALLOW または DENY のどちらを使用するかを指定します。アクションを指定しない場合、アクションはデフォルトで ALLOW に設定されます。わかりやすくするため、アクションは常に指定することをおすすめします(認可ポリシーでは AUDIT アクションと CUSTOM アクションを使用できます)。

  • rules で、アクションをトリガーするタイミングを指定します。

    • rulesfrom フィールドには、リクエストのソースを指定します。

    • rulesto フィールドには、リクエストのオペレーションを指定します。

    • when フィールドには、ルールの適用に必要な追加の条件を指定します。

下記の例で、

  • このポリシーは、demo 名前空間内の frontend サービスに対するリクエストに適用されています。

  • リクエスト ヘッダーに「hello:world」が含まれている場合、リクエストは許可されますが、含まれていない場合は拒否されます。

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "hello-world"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: frontend
  action: ALLOW
  rules:
  - when:
    - key: request.headers[hello]
      values: ["world"]

リクエスト オペレーションのアクセス制御

HTTP メソッドや TCP ポートなどの特定のリクエスト オペレーションへのアクセスを制御するには、rules の下に to セクションを追加します。次の例では、GETPOST の HTTP メソッドにのみ、demo 名前空間の currencyservice が許可されています

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: currencyservice
 namespace: demo
spec:
 selector:
   matchLabels:
     app: currencyservice
 action: ALLOW
 rules:
 - to:
   - operation:
       methods: ["GET", "POST"]

認証済み ID のアクセス制御

前の例では、ポリシーは未認証のワークロードからのリクエストを許可しています。STRICT 相互 TLS(mTLS)を有効にしている場合は、source セクションのリクエスト元であるワークロードまたは名前空間の ID に基づいてアクセスを制限できます。

  • ワークロード レベルでアクセスを制御するには、principals フィールドまたは notPrincipal フィールドを使用します。

  • 名前空間レベルでアクセスを制御するには、namespaces フィールドまたは notNamespaces フィールドを使用します。

上のすべてのフィールドで STRICT mTLS を有効にする必要があります。STRICT mTLS を設定できない場合は、平文リクエストを拒否で代わり解決策をご確認ください。

特定のワークロード

次の例では、frontend サービスから currencyservice へのリクエストのみが許可されます。他のワークロードから currencyservice へのリクエストは拒否されます。

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "currencyservice"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: currencyservice
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["example-project-1234.svc.id.goog/ns/demo/sa/frontend-sa"]

サービス アカウントを指定するには、Cloud Service Mesh 認証局(Mesh CA)と Certificate Authority Service(CA Service)の principals を次の形式にする必要があります。

principals: ["PROJECT_ID.svc.id.goog/ns/NAMESPACE/sa/SERVICE_ACCOUNT_NAME"]

PROJECT_ID.svc.id.goog は、Mesh CA の信頼ドメインです。Istio CA(旧称 Citadel)を使用する場合、デフォルトの信頼ドメインは cluster.local です。

特定の名前空間

次の例は、ソースが foo 名前空間でない場合に、リクエストを拒否するポリシーを示しています。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin-deny
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: DENY
 rules:
 - from:
   - source:
       notNamespaces: ["foo"]

値の一致

認可ポリシーのほとんどのフィールドでは、次の一致スキーマがすべてサポートされています。

  • 完全一致: 文字列の正確な一致。
  • ワイルドカード文字 "*" を使用したワイルドカードの一致。
    • 接頭辞の一致: "*" で終わる文字列。たとえば、"test.example.*""test.example.com" または "test.example.com.cn" と一致します。
    • 接尾辞の一致: "*" で始まる文字列。たとえば、"*.example.com""eng.example.com" または "test.eng.example.com" と一致します。
  • プレゼンスの一致: フィールドが存在し、空ではないことが必要であることを指定するには、fieldname: ["*"] 形式を使用します。これは、フィールドを指定しないままにすることとは異なります。つまり、空の値を含むすべてのフィールドと一致します。

ただし、次のような例外があります。たとえば、次のフィールドでは完全一致のみがサポートされています。

  • when セクションの key フィールド
  • source セクションの ipBlocks
  • to セクションの ports フィールド

次のポリシーの例では、/test/* 接頭辞または */info 接尾辞を使用したパスでアクセスが許可されています。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: tester
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/test/*", "*/info"]

除外の一致

when フィールドの notValuessource フィールドの notIpBlocksto フィールドの notPorts のような否定条件との一致のため、Cloud Service Mesh では除外の一致をサポートしています。次の例では、リクエストパスが /healthz でない場合、JWT 認証から派生した有効なリクエスト principals が必要になります。このポリシーでは /healthz パスへのリクエストが JWT 認証から除外されます。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: disable-jwt-for-healthz
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        notPaths: ["/healthz"]
    from:
    - source:
        requestPrincipals: ["*"]

平文のリクエストを拒否する

Cloud Service Mesh 1.5 以降では、自動 mTLS はデフォルトで有効になっています。自動 mTLS の場合、クライアント サイドカー プロキシがサーバーにサイドカーがあるかどうかを自動的に検出します。クライアント サイドカーは、サイドカーを含むワークロードには mTLS を送信し、サイドカーを含まないワークロードには平文を送信します。最適なセキュリティのために、STRICT mTLS を有効にすることをおすすめします。

ワークロードまたは名前空間に対して STRICT モードの mTLS を有効にできない場合は、次の操作を行います。

  • namespaces または principals が空ではないトラフィックを明示的に許可する認可ポリシーを作成する。または
  • namespaces または principals が空であるトラフィックを明示的に拒否する認可ポリシーを作成する。

namespacesprincipals は mTLS リクエストでのみ抽出できるため、これらのポリシーは平文のトラフィックを効果的に拒否します。

次のポリシーは、リクエスト内のプリンシパルが空の場合(平文のリクエストの場合)にリクエストを拒否します。プリンシパルが空でない場合は、ポリシーはリクエストを許可します。["*"] は空でないことを意味します。notPrincipals で使用する場合は、空のプリンシパルでの一致を意味します。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-mtls
  namespace: NAMESPACE
spec:
  action: DENY
  rules:
  - from:
    - source:
        notPrincipals: ["*"]

認可ポリシーの優先順位

ALLOWDENY の認可ポリシーを個別に構成することもできますが、ポリシーが希望どおりに動作するように、ポリシーの優先順位とデフォルトの動作を理解しておく必要があります。次の図は、ポリシーの優先順位を示しています。

認可ポリシーの優先順位

以降のセクションのポリシーの例では、デフォルトの動作の一部とそのポリシーが役立つ状況について説明します。

すべて許可しない

次の例は、何も一致しない ALLOW ポリシーを示しています。デフォルトでは、他の ALLOW ポリシーが存在しない場合、リクエストは常に拒否されます。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-nothing
spec:
  action: ALLOW

最初は何も許可しないポリシーを適用し、段階的に ALLOW ポリシーを追加して、ワークロードへのアクセスを増やすことは、良いセキュリティ対策です。

すべてのアクセスを拒否する

次の例は、すべてに一致する DENY ポリシーを示しています。DENY ポリシーは ALLOW ポリシーよりも先に評価されるため、リクエストに一致する ALLOW ポリシーがある場合でも、すべてのリクエストが拒否されます。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
spec:
  action: DENY
  rules:
  - {}

すべてを拒否するポリシーは、ワークロードへのすべてのアクセスを一時的に無効にする場合に便利です。

すべてのアクセスを許可する

次の例は、すべてに一致し、ワークロードに対する完全アクセス権を許可する ALLOW ポリシーを示しています。すべてを許可するポリシーは、常にリクエストを許可するため、他の ALLOW ポリシーが無効になります。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-all
spec:
  action: ALLOW
  rules:
  - {}

すべてを許可するポリシーは、ワークロードへの完全アクセス権を一時的に公開したい場合に便利です。DENY ポリシーがある場合、DENY ポリシーが ALLOW ポリシーの前に評価されるため、リクエストは拒否される可能性があります。

ベスト プラクティス

  1. サービスごとに Kubernetes サービス アカウントを作成し、Deployment でサービス アカウントを指定します。次に例を示します。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: frontend-sa
      namespace: demo
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
      namespace:demo
    spec:
      selector:
        matchLabels:
          app: frontend
      template:
        metadata:
          labels:
            app: frontend
        spec:
          serviceAccountName: frontend-sa
        ...
    
  2. すべて許可しないポリシーから始めて、ALLOW ポリシーを段階的に追加し、ワークロードへのアクセスを増やします。

  3. サービスで JWT を使用する場合:

    1. 認可されていないリクエストをブロックする DENY ポリシーを作成します。次に例を示します。

      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: requireJWT
        namespace: admin
      spec:
        action: DENY
        rules:
        -  from:
          - source:
              notRequestPrincipals: ["*"]
      
    2. すべて許可しないポリシーを適用します。

    3. ワークロードごとに ALLOW ポリシーを定義します。例については、JWT トークンをご覧ください。

次のステップ

Cloud Service Mesh のセキュリティ機能について学習します。

Istio ドキュメントの認可ポリシーの詳細については、以下をご覧ください。