新着: プロジェクトの最新情報をTwitterMastodonで入手してください。

approver-policy

approver-policy は、cert-manager の 承認者であり、CertificateRequestPolicyカスタムリソースで定義されたポリシーに基づいて CertificateRequest を承認または拒否します。

インストール

approver-policyのインストール方法については、インストールガイドをご覧ください。

設定

ポリシーリソースの例はこちらにあります。

CertificateRequest が作成されると、approver-policy は、リクエストが既存のポリシーに適しているかどうかを評価し、適している場合は、承認または拒否すべきかどうかを評価します。

CertificateRequest がポリシーに適しており、ポリシーによって評価されるためには、RBAC を介してバインドされており、かつ、ポリシーセレクターによって選択されている必要があります。CertificateRequestPolicy は現在、セレクターとして issuerRef のみをサポートしています。

少なくとも 1 つのポリシーがリクエストを許可する場合、リクエストは承認されます。少なくとも 1 つのポリシーがリクエストに適しているものの、そのいずれもリクエストを許可しない場合、リクエストは拒否されます。

拒否された CertificateRequest は、永続的に失敗したとみなされます。それが Certificate リソースのために作成された場合、発行は他のすべての永続的な発行失敗と同様に、指数バックオフで再試行されます。承認も拒否もされていない(一致するポリシーが見つからなかったため)CertificateRequest は、承認または拒否されるまで、cert-manager によってさらに処理されることはありません。

CertificateRequestPolicy はクラスター スコープのリソースであり、「ポリシー プロファイル」と考えることができます。それらは、そのポリシーによって承認されるすべてのリクエストを記述します。ポリシーは、RBAC を使用して Kubernetes ユーザーおよび ServiceAccount にバインドされます。

以下は、コモンネームが "hello.world" の証明書のみをリクエストできるすべての Kubernetes ユーザーにバインドされているポリシーの例です。

apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
name: test-policy
spec:
allowed:
commonName:
value: "hello.world"
required: true
selector:
# Select all IssuerRef
issuerRef: {}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cert-manager-policy:hello-world
rules:
- apiGroups: ["policy.cert-manager.io"]
resources: ["certificaterequestpolicies"]
verbs: ["use"]
# Name of the CertificateRequestPolicies to be used.
resourceNames: ["test-policy"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cert-manager-policy:hello-world
roleRef:
# ClusterRole or Role _must_ be bound to a user for the policy to be considered.
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cert-manager-policy:hello-world
subjects:
# The users who should be bound to the policies defined.
# Note that in the case of users creating Certificate resources, cert-manager
# is the entity that is creating the actual CertificateRequests, and so the
# cert-manager controller's
# Service Account should be bound instead.
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io

挙動

CertificateRequestPolicy は 4 つの部分に分かれています。allowedcontraintsselector、および plugins です。

許可

許可とは、リクエスト内の対応する属性と一致する属性を定義するブロックです。リクエストが許可された属性を省略した場合、リクエストはポリシーによって許可されますが、許可されたブロックに存在しない属性が含まれている場合、リクエストを拒否します。

許可された属性は、required としてマークできます。true の場合、属性がリクエストで定義されていることを強制します。対応するフィールドも定義されている場合にのみ、フィールドを required としてマークできます。required フィールドは、isCA または usages では使用できません。

次の CertificateRequestPolicy では、リクエストが DNS 名をリクエストしない場合、DNS 名 "example.com" をリクエストする場合、リクエストは許可されますが、"bar.example.com" をリクエストする場合は拒否されます。

spec:
...
allowed:
dnsNames:
values:
- "example.com"
- "foo.example.com"
...

以下では、リクエストにコモンネームが含まれていない場合、リクエストは拒否されますが、コモンネームが ".com" で終わるリクエストは許可されます。

spec:
...
allowed:
commonName:
value: "*.com"
required: true
...

許可されたフィールドが省略された場合、その属性はリクエストに対して「すべて拒否」とみなされます。

許可された文字列フィールドは、その値の中でワイルドカード "*" を受け入れます。パターン内のワイルドカード "*" は、長さが 0 以上の任意の文字列を表します。"*" のみを含むパターンは、すべてに一致します。"\*foo" を含むパターンは、"foo"、および "foo" で終わる任意の文字列 (例: "bar-foo") に一致します。"\*.foo" を含むパターンは、"bar-123.foo" に一致しますが、"barfoo" には一致しません。

リストである許可されたフィールドは、そのリストのサブセットであるリクエストを許可します。つまり、usages["server auth", "client auth"] が含まれている場合、["server auth"] のみを含むリクエストは許可されますが、["server auth", "cert sign"] は許可されません。

以下は、CertificateRequestPolicy のサポートされているすべての許可フィールドを含む例です。

apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
name: my-policy
spec:
allowed:
commonName:
value: "example.com"
dnsNames:
values:
- "example.com"
- "*.example.com"
ipAddresses:
values:
- "1.2.3.4"
- "10.0.1.*"
uris:
values:
- "spiffe://example.org/ns/*/sa/*"
emailAddresses:
values:
- "*@example.com"
required: true
isCA: false
usages:
- "server auth"
- "client auth"
subject:
organizations:
values: ["hello-world"]
countries:
values: ["*"]
organizationalUnits:
values: ["*"]
localities:
values: ["*"]
provinces:
values: ["*"]
streetAddresses:
values: ["*"]
postalCodes:
values: ["*"]
serialNumber:
value: "*"
...

検証

approver-policy 0.11.0 以降では、Common Expression Language (CEL) を使用して、より高度な許可されたリクエスト属性検証ルールを定義できるようになりました。この機能を追加した主な動機は、許可されたリクエスト属性値をリクエスト名前空間の関数として有効にすることでした。しかし、CEL は小さなプログラミング言語であるため、検証ルールは allowed 属性値の指定における基本的なワイルドカードサポートを補完または置き換えることもできます。

リクエスト属性値は、self 変数の式で利用できるようになります。多値のリクエスト属性の場合、検証は値ごとに 1 回実行されます。self 変数と同様に、approver-policy は、検証するリクエストを表す cr 変数を提供します。この変数はオブジェクト型であり、執筆時点では、namespacename の 2 つのフィールドのみがあります。

以下では、approver-policy CEL 検証ルールを使用して、X.509 SVID 証明書が名前空間(およびサービスアカウント)を識別する SPIFFE ID (X.509 URI SAN) で発行されるようにします。

spec:
...
allowed:
uris:
validations:
- rule: self.startsWith('spiffe://trust.domain/ns/' + cr.namespace + '/sa/')
message: only URIs representing the current namespace in the SPIFFE ID are allowed.
...

CEL 検証を使用できる場所の詳細については、approver-policy の API リファレンスドキュメントを参照してください。また、CEL 式の作成には、CEL 言語定義が役立つ場合があります。

制約

制約とは、リクエストが持つことができる属性を制限するために使用されるブロックです。制約が定義されていない場合、その属性は「すべて許可」とみなされます。

以下は、CertificateRequestPolicy のサポートされているすべての制約フィールドを含む例です。

apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
name: my-policy
spec:
...
constraints:
minDuration: 1h
maxDuration: 24h
privateKey:
algorithm: RSA
minSize: 2048
maxSize: 4096
...

セレクター

セレクターは必須フィールドであり、評価のためにCertificateRequestPolicyをCertificateRequestと照合するために使用されます。CertificateRequestPolicyは、リクエストの評価対象とするために、CertificateRequestを選択(つまり、一致)する必要があります。

⚠️ ポリシーをリクエストに対して評価対象とするためには、ユーザーは依然としてRBACによって拘束される必要があることに注意してください。

approver-policyは、リクエストのissuerRefnamespaceによる選択をサポートします。

issuerRefまたはnamespaceセレクターの少なくともいずれかは、空({})に設定した場合でも、定義する必要があります。両方のセレクターが定義されている場合、ポリシーによってリクエストが評価されるためには、両方のセレクターがCertificateRequestで一致する必要があります。

issuerRef

issuerRef CertificateRequestPolicyセレクターは、CertificateRequestの対応するissuerRefスタンザに基づいて選択を行います。

issuerRefの値はワイルドカード"*"を受け入れます。issuerRefが空のオブジェクト{}に設定されている場合、ポリシーはすべてのリクエストと一致します。

apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
name: my-policy
spec:
...
selector:
issuerRef:
name: "my-ca"
kind: "*Issuer"
group: "cert-manager.io"
apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
name: match-all-requests
spec:
...
selector:
issuerRef: {}

namespace

namespace CertificateRequestPolicyセレクターは、CertificateRequestが作成されたNamespaceに基づいて選択を行います。セレクターは、matchNamesまたはmatchLabelsのいずれかで定義できます。

matchNamesは、Namespaceの名前と一致する文字列のリストを受け取ります。ワイルドカード"*"を受け入れます。

matchLabelsは、CertificateRequestが作成されたNamespaceのラベルと一致するキーと値の文字列のリストを受け取ります。matchLabelsの動作の詳細については、Kubernetesドキュメントを参照してください。

namespaceが空のオブジェクト{}に設定されている場合、ポリシーはすべてのリクエストと一致します。

apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
name: my-policy
spec:
...
selector:
namespace:
matchNames:
- "default"
- "app-team-*"
matchLabels:
foo: bar
team: dev
apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
name: match-all-requests
spec:
...
selector:
namespace: {}

プラグイン

プラグインは、コンパイル時にapprover-policyに組み込まれる外部承認者です。プラグインは、既存のチェックでは提供できない特別な機能をユーザーが必要とする場合に、既存のポリシーチェックの拡張機能として使用されるように設計されています。

プラグインは、CertificateRequestPolicyのspecのブロックとして定義されます。

apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
name: plugins
spec:
...
plugins:
my-plugin:
values:
val-1: key-1

コミュニティからの既知のプラグイン

外部承認者ポリシープラグインを実装する場合は、https://github.com/cert-manager/example-approver-policy-pluginにある実装例を参照してください。

approver-policy用のプラグインを実装しましたか?cert-managerウェブサイトプロジェクトでプルリクエストを開いて、このページからプラグインへのリンクを追加してください。

APIリファレンス

📖 approver-policy APIリファレンスをお読みください。