認可ポリシーの概要
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 ...
基本構造
認可ポリシーには、ポリシーの範囲、action
、rules
のリストが含まれます。
前のセクションで説明したように、ポリシーの範囲は、メッシュ全体、名前空間、または特定のワークロードにすることが可能です。ポリシーの範囲を追加する場合は、
selector
フィールドにポリシーの対象を指定します。action
フィールドは、リクエストに対してALLOW
またはDENY
のどちらを使用するかを指定します。アクションを指定しない場合、アクションはデフォルトでALLOW
に設定されます。わかりやすくするため、アクションは常に指定することをおすすめします(認可ポリシーではAUDIT
アクションとCUSTOM
アクションを使用できます)。rules
で、アクションをトリガーするタイミングを指定します。
下記の例で、
このポリシーは、
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
セクションを追加します。次の例では、GET
と POST
の 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
フィールドの notValues
、source
フィールドの notIpBlocks
、to
フィールドの 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
が空であるトラフィックを明示的に拒否する認可ポリシーを作成する。
namespaces
と principals
は mTLS リクエストでのみ抽出できるため、これらのポリシーは平文のトラフィックを効果的に拒否します。
次のポリシーは、リクエスト内のプリンシパルが空の場合(平文のリクエストの場合)にリクエストを拒否します。プリンシパルが空でない場合は、ポリシーはリクエストを許可します。["*"]
は空でないことを意味します。notPrincipals
で使用する場合は、空のプリンシパルでの一致を意味します。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-mtls
namespace: NAMESPACE
spec:
action: DENY
rules:
- from:
- source:
notPrincipals: ["*"]
認可ポリシーの優先順位
ALLOW
と DENY
の認可ポリシーを個別に構成することもできますが、ポリシーが希望どおりに動作するように、ポリシーの優先順位とデフォルトの動作を理解しておく必要があります。次の図は、ポリシーの優先順位を示しています。
以降のセクションのポリシーの例では、デフォルトの動作の一部とそのポリシーが役立つ状況について説明します。
すべて許可しない
次の例は、何も一致しない 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
ポリシーの前に評価されるため、リクエストは拒否される可能性があります。
ベスト プラクティス
サービスごとに 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 ...
すべて許可しないポリシーから始めて、
ALLOW
ポリシーを段階的に追加し、ワークロードへのアクセスを増やします。サービスで JWT を使用する場合:
認可されていないリクエストをブロックする
DENY
ポリシーを作成します。次に例を示します。apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: requireJWT namespace: admin spec: action: DENY rules: - from: - source: notRequestPrincipals: ["*"]
すべて許可しないポリシーを適用します。
ワークロードごとに
ALLOW
ポリシーを定義します。例については、JWT トークンをご覧ください。
次のステップ
Cloud Service Mesh のセキュリティ機能について学習します。
- Cloud Service Mesh のユーザー認証の構成
- サービスの監査ポリシーの構成
- トランスポートのセキュリティの構成
- Identity-Aware Proxy と Anthos Service Mesh の統合
- GKE クラスタで Cloud Service Mesh の Egress ゲートウェイを使用するためのベスト プラクティス
Istio ドキュメントの認可ポリシーの詳細については、以下をご覧ください。