Open Policy Agent¶
はじめに¶
本サイトにつきまして、【IT技術の知見】はじめに - 俺の技術ノート をご認識のほど宜しくお願いいたします。
01. Open Policy Agent の仕組み¶
アーキテクチャ¶
Open Policy Agent は、Open Policy Agent、rego ファイル、DB、といったコンポーネントから構成される。

Open Policy Agent¶
Open Policy Agent は、rego ファイルの認可スコープに基づいて許否を決定し、boolean 値を返す。
返却された boolean 値に基づいて、クライアント側 (例:アプリケーション、kube-apiserver) で認可結果を適用する。

rego ファイル¶
認可スコープのロジックを定義する。
DB¶
資格情報を json 形式、認可スコープ定義を rego 形式で、保管する。
02. ユースケース¶
アプリケーションの認可マイクロサービスとして¶
▼ アプリケーションの認可マイクロサービスとは¶
アプリケーションの認可スコープ定義の責務を認可マイクロサービスとして切り分ける。
アプリケーションは Open Policy Agent にリクエストを送信し、Open Policy Agent は認可スコープに基づいて許否を決定して boolean 値を返す。
返却された boolean 値に基づいて、アプリケーションは認可結果を適用する。
▼ 資格情報の作成¶
-
資格情報を
json形式で作成する。ここでは、各アカウントが一般社員または管理職のいずれかであるかを定義している。
// subordinates.json ファイル {"alice": ["bob"], "bob": [], "charlie": ["david"], "david": []} -
アプリケーションは、Open Policy Agent に資格情報を送信し、資格情報を DB に作成する。
$ curl \ -X PUT \ -H 'Content-Type:application/json' \ --data-binary @subordinates.json \ 127.0.0.1:8181/v1/data/subordinates
▼ 認可スコープの定義¶
-
認可スコープ定義のロジックを
rego形式で作成する。package httpapi.authz # 社員の資格情報をインポートする。 import data.subordinates as subord default allow = false # 一般社員は、自身の給与のみで参照権限を持つ (trueを返却する) 。 allow { some username input.method == "GET" input.path = ["finance", "salary", username] input.user == username } # 管理職は、自身と部下社員の給与で参照権限を持つ (trueを返却する) 。 allow { some username input.method == "GET" input.path = ["finance", "salary", username] subord[input.user][_] == username } -
アプリケーションは、Open Policy Agent に
regoファイルを送信し、認可スコープ定義を DB に作成する。$ curl \ -X PUT \ -H 'Content-Type: text/plain'\ --data-binary @httpapi_authz.rego \ 127.0.0.1:8181/v1/policies/httpapi_authz
▼ 認可スコープのリクエスト¶
-
認可スコープを取得するためのリクエストを
json形式で作成する。実際は、aliceというアカウントがデータを参照できるかどうかを取得するために、アプリケーションがリクエストを作成する。
// request.json ファイル { // リクエストの内容 "input": { // GET メソッド "method": "GET", // パス "path": ["finance", "salary", "alice"], // アカウント名 "user": "alice", }, } -
アプリケーションは、alice アカウントの参照権限の有無を Open Policy Agent にリクエストを送信する。
Open Policy Agentは、アプリケーションに
trueを返却する。$ curl \ -X POST \ -H 'Content-Type:application/json' \ --data-binary @request.json \ 127.0.0.1:8181/v1/data/httpapi/authz/allow | jq . { "result": "true" }
Kubernetes の Gatekeeper として¶
▼ Gatekeeper とは¶
これは認可ツールではなく、マニフェストのコード規約違反を検知する PaC ツールである。
内部的に Open Policy Agent を使用して、Kubernetes のマニフェストを検証する。
kube-apiserver の validating-admission ステップ時に、Gatekeeper の webhook サーバーに AdmissionReview のリクエストが送信され、Gatekeeper の持つ Open Policy Agent の処理を発火させる。
そのため、GitOps の CD パイプライン上にバリデーションを実行できる。

▼ gatekeeper-validating-webhook-configuration¶
Pod の作成/更新時に webhook サーバーへリクエストを送信できるようにする。そのため、ValidatingWebhookConfiguration で ValidatingWebhook アドオンを設定する。
.webhooks.failurePolicy キーで設定しているとおり、webhook サーバーのコールに失敗した場合は、無視して kube-apiserver の処理を続ける。
そのため、Gatekeeper が起動に失敗しても、Pod が中止されることはない。
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: gatekeeper-validating-webhook-configuration
labels:
gatekeeper.sh/system: "yes"
webhooks:
# webhook 名は完全修飾ドメイン名にする。
- name: validation.gatekeeper.sh
admissionReviewVersions: ["v1", "v1beta1"]
clientConfig:
# webhook サーバーを Cluster 内部に自作する場合は、webhook サーバーに証明書バンドルを登録する。
caBundle: Ci0tLS0tQk...
# Gatekeeper の Webhook Service の宛先情報を登録する。
service:
name: gatekeeper-webhook-service
namespace: gatekeeper-system
# エンドポイント
path: /v1/admit
port: 443
failurePolicy: Ignore
matchPolicy: Exact
namespaceSelector:
matchExpressions:
- key: admission.gatekeeper.sh/ignore
operator: DoesNotExist
objectSelector: {}
# validating-admission ステップ発火条件を登録する。
rules:
- apiGroups: ["*"]
apiVersions: ["*"]
operations: ["CREATE", "UPDATE"]
resources: ["*"]
scope: "*"
sideEffects: None
timeoutSeconds: 3
# webhook 名は完全修飾ドメイン名にする。
- name: check-ignore-label.gatekeeper.sh
admissionReviewVersions: ["v1", "v1beta1"]
clientConfig:
# webhook サーバーを Cluster 内部に自作する場合は、webhook サーバーに証明書バンドルを登録する。
caBundle: Ci0tLS0tQk...
# Gatekeeper の Webhook Service の宛先情報を登録する。
service:
name: gatekeeper-webhook-service
namespace: gatekeeper-system
# エンドポイント
path: /v1/admitlabel
port: 443
# webhook サーバーのコールに失敗した場合の処理を設定する。
failurePolicy: Fail
matchPolicy: Exact
namespaceSelector: {}
objectSelector: {}
# validating-admission ステップ発火条件を登録する。
rules:
- apiGroups: [""]
apiVersions: ["*"]
operations: ["CREATE", "UPDATE"]
resources: ["namespaces"]
scope: "*"
sideEffects: None
timeoutSeconds: 3