NEW: プロジェクトの最新情報を入手:TwitterMastodon

証明書のデフォルト値を自動的に設定する方法を学ぶ

最終検証日:2024年1月19日

目的

ユーザーがCertificateリソースでできるだけ少ないYAMLを指定するクラスターをセットアップします。これは、Kyvernoを利用して、ユーザーが指定しないCertificateフィールドにカスタムの「デフォルト」値を適用することで実現します。

デフォルト値を持つことにはいくつかの利点があります。

  • Certificateの利用者は、YAMLリソースを最小限に抑えることができます。
  • Certificateの利用者は、必要に応じてフィールドを上書きする柔軟性を維持できます。
  • クラスター運用者は、cert-managerの組み込みのデフォルトに依存するのではなく、デフォルトを何にするかを決定できます。

ユースケース

クラスター全体にカスタムのデフォルトを設定することで、プラットフォームチームは以下のようなユースケースに取り組むことができます。

  • CertificateRequestリソースがクリーンアップされるようにする。

    ClusterPolicyを使用して、Certificate.Spec.RevisionHistoryLimitフィールドのカスタムのデフォルト値を設定します。

  • ユーザーがCertificateリソースに対して安全なデフォルトキー設定を選択できるようにする。

    ClusterPolicyを使用して、Certificate.Spec.PrivateKeyフィールドのカスタムのデフォルト値を設定します。

  • クラスター内のユーザーのIssuerをデフォルトにする。

    ClusterPolicyを使用して、Certificate.spec.issuerRefフィールドのカスタムのデフォルトを設定します。

  • 証明書が設定されるSecretの名前付けのデフォルトパターンを設定する。

    ClusterPolicyを使用して、必須フィールドであるspec.secretNameのカスタムのデフォルト値を設定します。

  • アプリケーション開発者が、最小限の設定で安全なX.509 TLS証明書を作成できるようにすることで、彼らの生活を楽にする。

    ClusterPolicyを使用して、他のすべての必須Certificate.specフィールドを設定します。1つのアイデンティティ仕様フィールドのみが必要になります。それは次のいずれかです。

    • commonNameまたはliteralSubject
    • dnsNames
    • uris
    • emailAddresses
    • ipAddresses
    • otherNames

プロセス

3つの異なるシナリオに対して、徐々に高度化しながらデフォルトを設定します。

  1. オプションのCertificateリソースフィールドのデフォルトを設定します。
  2. 必須のCertificateリソースフィールドのデフォルトを設定します。
  3. Ingressアノテーションを使用して証明書をリクエストする場合の、Certificateリソースフィールドのデフォルトを設定します。

セットアップ

前提条件

💻 ソフトウェア

  1. kubectl: Kubernetesクラスターを構成するためのKubernetesコマンドラインツール。
  2. helm: Kubernetesのパッケージマネージャー。
  3. kindオプション):Dockerまたはその他のコンテナランタイムで実行されるローカルのKubernetes環境を作成するため。

ローカルKubernetes環境

⚠️ 他のKubernetes環境をお持ちの場合は、このステップをスキップできます。

  1. このチュートリアルでは、kindを使用してクラスター環境を作成します。

    kind create cluster --name defaults

    ⏲ マシンによって異なりますが、クラスターの作成には1分もかかりません。

    ⚠️ このクラスターは学習目的でのみ適しています。本番環境での使用には適していません。

ソフトウェアのインストール

クラスター環境が整ったら、helmを使用して必要なKubernetesパッケージをインストールします。

  1. helmチャートのバージョンの環境変数を設定します。

    export CERT_MANAGER_CHART_VERSION="v1.16.1" \
    KYVERNO_CHART_VERSION="3.1.4" \
    INGRESS_NGINX_CHART_VERSION="4.9.0"
  2. cert-managerをインストールします。

    helm upgrade --install cert-manager cert-manager \
    --namespace cert-manager \
    --version $CERT_MANAGER_CHART_VERSION \
    --set crds.enabled=true \
    --set startupapicheck.enabled=false \
    --create-namespace \
    --repo https://charts.jetstack.io/
  3. Kyvernoをインストールします。

    helm upgrade --install kyverno kyverno \
    --namespace kyverno-system \
    --version $KYVERNO_CHART_VERSION \
    --create-namespace \
    --repo https://kyverno.github.io/kyverno/
  4. ingress-nginxをインストールします。

    helm upgrade --install ingress-nginx ingress-nginx \
    --namespace ingress-nginx \
    --version $INGRESS_NGINX_CHART_VERSION \
    --create-namespace \
    --repo https://kubernetes.github.io/ingress-nginx

完全なインストール手順については、次のリンクを参照してください。

デフォルトの設定

メインのチュートリアルはここから始まり、3つのシナリオのそれぞれに取り組む前に、いくつかの背景を説明します。

必須と非必須

Certificateリソースには、多くの「必須」フィールドを含むspecセクションがあります。これは、Certificateリソースを作成するときにこれらのフィールドが存在する必要があることを意味します。また、各Certificateリソースで明示的に定義する必要がない他の多くのフィールドもあります。これは基本的に、これらのフィールドの1つの値が必須ではないか、または他の場所でデフォルトが定義されていることを意味します。その「他の場所」は、cert-managerコードベースである可能性もあれば、X.509証明書を作成して返す発行者である可能性もあります。これらの値を操作してカスタムにし、Certificateユーザーの生活を楽にする方法を見ていきましょう。

このチュートリアルでは、いくつかのClusterPolicyリソースとCertificateリソースをセットアップします。Certificateスペックに存在しないClusterIssuerを参照しますが、このチュートリアルでは、実際に証明書をリクエストしないため、ClusterIssuerは必須ではありません。つまり、誰でも自分のドメインがなくてもこのチュートリアルに従うことができます。

⚠️ 開始を容易にするために、クラスター スコープのClusterPolicyリソースを使用しています。 将来的には、Policyリソースを使用することで、デフォルトを名前空間レベルにスコープ設定できますが、このチュートリアルでは取り上げません。

1 - オプションフィールドのデフォルト設定

このセクションでは、すべてのCertificateリソースに対して3つのフィールドを自動的に設定するルールを作成します。ここにある3つのフィールドはいずれも必須フィールドではありませんが、プラットフォームと発行者の設定によっては設定する必要がある場合があります。これらのルールは次のようになります。

  • デフォルト値を設定: revisionHistoryLimit: 2
  • spec.privateKey.rotationPolicy のデフォルト値を Always に設定します。
  • spec.privateKey フィールドすべてのデフォルト値を設定します。

ℹ️ これらのルールが、ユースケースのうち最初の2つにどのように対応しているかを確認してください。

  1. まず、ClusterPolicy を見てみましょう。

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
    name: mutate-certificates
    spec:
    failurePolicy: Fail
    rules:
    # Set a sane default for the history field if not already present
    - name: set-revisionHistoryLimit
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    # +(...) This is the clever syntax for if not already set
    +(revisionHistoryLimit): 2
    # Set rotation to always if not already set
    - name: set-privateKey-rotationPolicy
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    privateKey:
    +(rotationPolicy): Always
    # Set private key details for algorithm and size
    - name: set-privateKey-details
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    privateKey:
    +(algorithm): ECDSA
    +(size): 521
    +(encoding): PKCS1

    🔗 cpol-mutate-certificates-0.yaml

  2. ポリシーをクラスターに適用し、準備ができていることを確認します。

    kubectl apply -f cpol-mutate-certificates-0.yaml
    kubectl get cpol

    ClusterPolicy の準備ができると、出力は次のようになります。

    NAME ADMISSION BACKGROUND VALIDATE ACTION READY AGE MESSAGE
    mutate-certificates true true Audit True 0s Ready
  3. 次に、"test-revision" Certificate を調べます。

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    name: test-revision
    namespace: default
    spec:
    dnsNames:
    - example.com
    issuerRef:
    group: cert-manager.io
    kind: ClusterIssuer
    name: not-my-corp-issuer
    secretName: test-revision-cert

    🔗 cert-test-revision.yaml

    証明書のDNS名、保存場所(secretName)、証明書のリクエストに使用するイシュアー(issuerRef)のみを指定した、現在可能な限り最小限の設定になっていることがわかります。

  4. 次のコマンドを使用して、証明書をドライラン適用し、元のリソースと比較(diff)して、ClusterPolicy からのデフォルト値がどのように適用されるかを確認します。

    kubectl apply -f cert-test-revision.yaml --dry-run=server -o yaml | diff -uZ cert-test-revision.yaml -

    このコマンドは、この例のような出力を返すはずです。

    --- cert-test-revision.yaml 2024-01-08 12:14:59.225074232 +0000
    +++ - 2024-01-12 17:37:51.076593214 +0000
    @@ -1,8 +1,14 @@
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    + annotations:
    + kubectl.kubernetes.io/last-applied-configuration: |
    + {"apiVersion":"cert-manager.io/v1","kind":"Certificate","metadata":{"annotations":{},"name":"test-revision","namespace":"default"},"spec":{"dnsNames":["example.com"],"issuerRef":{"group":"cert-manager.io","kind":"ClusterIssuer","name":"not-my-corp-issuer"},"secretName":"test-revision-cert"}}
    + creationTimestamp: "2024-01-12T17:37:51Z"
    + generation: 1
    name: test-revision
    namespace: default
    + uid: 9f9a4f0a-4aa7-427d-ae4b-c1716fed8246
    spec:
    dnsNames:
    - example.com
    @@ -10,4 +16,10 @@
    group: cert-manager.io
    kind: ClusterIssuer
    name: not-my-corp-issuer
    + privateKey:
    + algorithm: ECDSA
    + encoding: PKCS1
    + rotationPolicy: Always
    + size: 521
    + revisionHistoryLimit: 2
    secretName: test-revision-cert

    privateKey および revisionHistoryLimit フィールドのデフォルト設定が正常に完了しました!

  5. エンドユーザーとして必要なものを設定できることを検証するために、これらのデフォルト設定されたすべてのフィールドを上書きしてみましょう。これをテストするために、"test-revision-override" Certificate を使用します。

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    name: test-revision-override
    namespace: default
    spec:
    dnsNames:
    - example.com
    issuerRef:
    group: cert-manager.io
    kind: ClusterIssuer
    name: not-my-corp-issuer
    privateKey:
    algorithm: RSA
    encoding: PKCS8
    rotationPolicy: Never
    size: 4096
    revisionHistoryLimit: 44
    secretName: test-revision-override-cert

    🔗 cert-test-revision-override.yaml

    以前と同様に、ドライラン適用し、出力を入力ファイルと比較(diff)します。

    kubectl apply -f cert-test-revision-override.yaml --dry-run=server -o yaml | diff -uZ cert-test-revision-override.yaml -

    出力では、Certificate 自体の仕様に変更がないことがわかります。Certificate には、ClusterPolicy ルールが影響を与えるすべてのフィールドがすでに定義されていました。

    --- cert-test-revision-override.yaml 2024-01-05 14:45:14.972562067 +0000
    +++ - 2024-01-12 17:39:57.217028745 +0000
    @@ -1,8 +1,14 @@
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    + annotations:
    + kubectl.kubernetes.io/last-applied-configuration: |
    + {"apiVersion":"cert-manager.io/v1","kind":"Certificate","metadata":{"annotations":{},"name":"test-revision-override","namespace":"default"},"spec":{"dnsNames":["example.com"],"issuerRef":{"group":"cert-manager.io","kind":"ClusterIssuer","name":"not-my-corp-issuer"},"privateKey":{"algorithm":"RSA","encoding":"PKCS8","rotationPolicy":"Never","size":4096},"revisionHistoryLimit":44,"secretName":"test-revision-override-cert"}}
    + creationTimestamp: "2024-01-12T17:39:57Z"
    + generation: 1
    name: test-revision-override
    namespace: default
    + uid: 83a6ddbc-6903-479e-802d-e11149985338
    spec:
    dnsNames:
    - example.com

2 - 必須フィールドのデフォルト設定

⚠️ このセクションは、すぐに使用するには cert-manager v1.14.x 以降が必要です。詳細については、付録セクションを参照してください。

ここで、Kyverno ClusterPolicy を設定して、Certificate フィールドのいずれかにデフォルト値を適用できます。これには、必須フィールドも含まれます。この例の ClusterPolicy では、次の2つのことを行います。

  • 関連する issuerRef フィールドをデフォルトで "our-corp-issuer" ClusterIssuer を使用するように設定します。
  • デフォルトの secretName を、"-cert" が付加された Certificate オブジェクトの名前に設定します。

ℹ️ これらのルールが、3番目と4番目の ユースケースにどのように対応しているかを確認してください。

  1. 次に、両方のフィールドをデフォルト値で設定する ClusterPolicy リソースを示します。

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
    name: mutate-certificates
    spec:
    failurePolicy: Fail
    rules:
    # Set a sane default for the history field if not already present
    - name: set-revisionHistoryLimit
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    # +(...) This is the clever syntax for if not already set
    +(revisionHistoryLimit): 2
    # Set rotation to always if not already set
    - name: set-privateKey-rotationPolicy
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    privateKey:
    +(rotationPolicy): Always
    # Set private key details for algorithm and size
    - name: set-privateKey-details
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    privateKey:
    +(algorithm): ECDSA
    +(size): 521
    +(encoding): PKCS1
    # Set a secretName when one is not provided
    - name: set-default-secret-name
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    # You can read more about this syntax in the Kyverno documentation:
    # https://kyverno.io/docs/writing-policies/variables/#variables-from-admission-review-requests
    +(secretName): "{{request.object.metadata.name}}-cert"
    # Set a default for issuerRef fields
    - name: set-default-issuer-ref
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    +(issuerRef):
    name: our-corp-issuer
    kind: ClusterIssuer
    group: cert-manager.io

    🔗 cpol-mutate-certificates-1.yaml

    この ClusterPolicy は、以前適用したポリシーの拡張です。

  2. このポリシーを適用します。

    kubectl apply -f cpol-mutate-certificates-1.yaml

    既存の ClusterPolicy が変更されたことがわかります。

    clusterpolicy.kyverno.io/mutate-certificates configured

    ClusterPolicy を取得して、"Ready" であることを検証します。

    kubectl get cpol

    このコマンドは、この例のような出力を返すはずです。

    NAME ADMISSION BACKGROUND VALIDATE ACTION READY AGE MESSAGE
    mutate-certificates true true Audit True 6m21s Ready
  3. ポリシー内のすべてのルールが有効であることを検証するように設計された "test-minimal" Certificate を見てみましょう。

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    name: test-minimal
    namespace: default
    spec:
    dnsNames:
    - example.com

    🔗 cert-test-minimal.yaml

  4. ドライラン適用し、diff して、すべてのデフォルトがこの最小限の Certificate に適用されていることを検証します。

    kubectl apply -f cert-test-minimal.yaml --dry-run=server -o yaml | diff -uZ cert-test-minimal.yaml -

    このコマンドは、この例のような出力を返すはずです。

    --- cert-test-minimal.yaml 2024-01-05 14:45:07.140668401 +0000
    +++ - 2024-01-12 17:44:08.110290752 +0000
    @@ -1,8 +1,25 @@
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    + annotations:
    + kubectl.kubernetes.io/last-applied-configuration: |
    + {"apiVersion":"cert-manager.io/v1","kind":"Certificate","metadata":{"annotations":{},"name":"test-minimal","namespace":"default"},"spec":{"dnsNames":["example.com"]}}
    + creationTimestamp: "2024-01-12T17:44:08Z"
    + generation: 1
    name: test-minimal
    namespace: default
    + uid: 792d29c7-8cf3-4f3a-9f12-4fba396e0d6e
    spec:
    dnsNames:
    - example.com
    + issuerRef:
    + group: cert-manager.io
    + kind: ClusterIssuer
    + name: our-corp-issuer
    + privateKey:
    + algorithm: ECDSA
    + encoding: PKCS1
    + rotationPolicy: Always
    + size: 521
    + revisionHistoryLimit: 2
    + secretName: test-minimal-cert

    spec.issuerRef および spec.secretName フィールドの値が自動的に入力されていることがわかります。これは、Kyverno ClusterPolicy が、指定された Certificate リソースに適用されたことを示しています。

  5. 設定を強制していないことを完全に確実にするために、デフォルトルールがある Certificate の各プロパティを明示的に設定しましょう。"test-revision-override" Certificate を使用します。

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    name: test-revision-override
    namespace: default
    spec:
    dnsNames:
    - example.com
    issuerRef:
    group: cert-manager.io
    kind: ClusterIssuer
    name: not-my-corp-issuer
    privateKey:
    algorithm: RSA
    encoding: PKCS8
    rotationPolicy: Never
    size: 4096
    revisionHistoryLimit: 44
    secretName: test-revision-override-cert

    🔗 cert-test-revision-override.yaml

  6. ドライラン適用し、このファイルと比較(diff)します。

    kubectl apply -f cert-test-revision-override.yaml --dry-run=server -o yaml | diff -uZ cert-test-revision-override.yaml -

    このコマンドは、この例のような出力を返すはずです。

    --- cert-test-revision-override.yaml 2024-01-05 14:45:14.972562067 +0000
    +++ - 2024-01-12 17:45:48.261997150 +0000
    @@ -1,8 +1,14 @@
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    + annotations:
    + kubectl.kubernetes.io/last-applied-configuration: |
    + {"apiVersion":"cert-manager.io/v1","kind":"Certificate","metadata":{"annotations":{},"name":"test-revision-override","namespace":"default"},"spec":{"dnsNames":["example.com"],"issuerRef":{"group":"cert-manager.io","kind":"ClusterIssuer","name":"not-my-corp-issuer"},"privateKey":{"algorithm":"RSA","encoding":"PKCS8","rotationPolicy":"Never","size":4096},"revisionHistoryLimit":44,"secretName":"test-revision-override-cert"}}
    + creationTimestamp: "2024-01-12T17:45:48Z"
    + generation: 1
    name: test-revision-override
    namespace: default
    + uid: d0ad7abe-c703-45f7-acf9-634b3a263cfa
    spec:
    dnsNames:
    - example.com

    このコマンドから、Certificate の仕様フィールドが変更されていないことがわかります。メタデータセクションのみが変更されており、これはポリシーが適用されたが、値がすでに指定されているため、デフォルトを設定しなかったことを示しています。これにより、必要に応じてクラスターのデフォルトを上書きできる柔軟性が維持されていることがわかります。

3 - Ingressアノテーションによるデフォルト設定

多くの cert-manager ユーザーは Certificate リソースを直接作成するのではなく、ingress-shim 機能を使用しています。cert-manager は、サポートされているアノテーションIngress 仕様に基づいて Certificate リソースを作成します。このユースケースでも ClusterPolicy を使用してデフォルトを適用する方法を見てみましょう。

  1. この例の Ingress リソースには、cert-manager.io/cluster-issuer アノテーションがあります。このアノテーションは、cert-manager に issuerRef フィールドが our-corp-issuer という名前の ClusterIssuer を指す Certificate を作成するように指示します。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    cert-manager.io/cluster-issuer: "our-corp-issuer"
    name: defaults-example
    namespace: default
    spec:
    ingressClassName: nginx
    rules:
    - host: app.example.com
    http:
    paths:
    - backend:
    service:
    name: app
    port:
    number: 80
    path: /
    pathType: ImplementationSpecific
    tls:
    - hosts:
    - app.example.com
    secretName: defaults-example-certificate-tls

    🔗 ingress.yaml

  2. このアノテーションと関連する ingress.spec.tls 構成がすべて必要なので、リソースを適用します。

    kubectl apply -f ingress.yaml
  3. ここで、Certificate リソースが自動的に生成されたことを検証します。

    kubectl get cert defaults-example-certificate-tls -o yaml

    このコマンドは、この例のような出力を返すはずです。

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    creationTimestamp: "2024-01-12T17:47:04Z"
    generation: 1
    name: defaults-example-certificate-tls
    namespace: default
    ownerReferences:
    - apiVersion: networking.k8s.io/v1
    blockOwnerDeletion: true
    controller: true
    kind: Ingress
    name: defaults-example
    uid: bea33a55-a9ed-4664-a56a-a679eb8272c3
    resourceVersion: "584260"
    uid: 43ced989-723b-4eac-bad0-f8bead6976df
    spec:
    dnsNames:
    - app.example.com
    issuerRef:
    group: cert-manager.io
    kind: ClusterIssuer
    name: our-corp-issuer
    privateKey:
    algorithm: ECDSA
    encoding: PKCS1
    rotationPolicy: Always
    size: 521
    revisionHistoryLimit: 2
    secretName: defaults-example-certificate-tls
    usages:
    - digital signature
    - key encipherment
    status:
    conditions:
    - lastTransitionTime: "2024-01-12T17:47:04Z"
    message: Issuing certificate as Secret does not exist
    observedGeneration: 1
    reason: DoesNotExist
    status: "True"
    type: Issuing
    - lastTransitionTime: "2024-01-12T17:47:04Z"
    message: Issuing certificate as Secret does not exist
    observedGeneration: 1
    reason: DoesNotExist
    status: "False"
    type: Ready
    nextPrivateKeySecretName: defaults-example-certificate-tls-nbjws
  4. オプションで、Kyverno アドミッションコントローラーコンテナーのログを表示して、"mutate-certificates" ClusterPolicy が適用されていることを検証できます。

    kubectl logs -n kyverno-system $(kubectl get pod -n kyverno-system -l app.kubernetes.io/component=admission-controller -o jsonpath='{.items[0].metadata.name}') -c kyverno --tail 3

    このコマンドは、この例のような出力を返すはずです。

    I0112 17:47:04.425863 1 mutation.go:113] webhooks/resource/mutate "msg"="mutation rules from policy applied successfully" "clusterroles"=["cert-manager-controller-approve:cert-manager-io","cert-manager-controller-certificates","cert-manager-controller-certificatesigningrequests","cert-manager-controller-challenges","cert-manager-controller-clusterissuers","cert-manager-controller-ingress-shim","cert-manager-controller-issuers","cert-manager-controller-orders","system:basic-user","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "gvk"={"group":"cert-manager.io","version":"v1","kind":"Certificate"} "gvr"={"group":"cert-manager.io","version":"v1","resource":"certificates"} "kind"="Certificate" "name"="defaults-example-certificate-tls" "namespace"="default" "operation"="UPDATE" "policy"="mutate-certificates" "resource.gvk"={"Group":"cert-manager.io","Version":"v1","Kind":"Certificate"} "roles"=["kube-system:cert-manager:leaderelection"] "rules"=["set-revisionHistoryLimit","set-privateKey-rotationPolicy","set-privateKey-details"] "uid"="6f93bd8d-29ca-4eab-8e96-065ea82a1bf2" "user"={"username":"system:serviceaccount:cert-manager:cert-manager","uid":"21cbad67-9d2e-44ee-bb02-7fef9aa2e502","groups":["system:serviceaccounts","system:serviceaccounts:cert-manager","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["cert-manager-648cd49b44-z6g8s"],"authentication.kubernetes.io/pod-uid":["4bd741fa-a8ec-48a1-82d5-26c5b7acce5e"]}}
    I0112 17:47:04.458402 1 mutation.go:113] webhooks/resource/mutate "msg"="mutation rules from policy applied successfully" "clusterroles"=["cert-manager-controller-approve:cert-manager-io","cert-manager-controller-certificates","cert-manager-controller-certificatesigningrequests","cert-manager-controller-challenges","cert-manager-controller-clusterissuers","cert-manager-controller-ingress-shim","cert-manager-controller-issuers","cert-manager-controller-orders","system:basic-user","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "gvk"={"group":"cert-manager.io","version":"v1","kind":"Certificate"} "gvr"={"group":"cert-manager.io","version":"v1","resource":"certificates"} "kind"="Certificate" "name"="defaults-example-certificate-tls" "namespace"="default" "operation"="UPDATE" "policy"="mutate-certificates" "resource.gvk"={"Group":"cert-manager.io","Version":"v1","Kind":"Certificate"} "roles"=["kube-system:cert-manager:leaderelection"] "rules"=["set-revisionHistoryLimit","set-privateKey-rotationPolicy","set-privateKey-details"] "uid"="ec61a3c9-df0a-4daf-8bc3-227dc80348a9" "user"={"username":"system:serviceaccount:cert-manager:cert-manager","uid":"21cbad67-9d2e-44ee-bb02-7fef9aa2e502","groups":["system:serviceaccounts","system:serviceaccounts:cert-manager","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["cert-manager-648cd49b44-z6g8s"],"authentication.kubernetes.io/pod-uid":["4bd741fa-a8ec-48a1-82d5-26c5b7acce5e"]}}
    I0112 17:47:09.477776 1 mutation.go:113] webhooks/resource/mutate "msg"="mutation rules from policy applied successfully" "clusterroles"=["cert-manager-controller-approve:cert-manager-io","cert-manager-controller-certificates","cert-manager-controller-certificatesigningrequests","cert-manager-controller-challenges","cert-manager-controller-clusterissuers","cert-manager-controller-ingress-shim","cert-manager-controller-issuers","cert-manager-controller-orders","system:basic-user","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "gvk"={"group":"cert-manager.io","version":"v1","kind":"Certificate"} "gvr"={"group":"cert-manager.io","version":"v1","resource":"certificates"} "kind"="Certificate" "name"="defaults-example-certificate-tls" "namespace"="default" "operation"="UPDATE" "policy"="mutate-certificates" "resource.gvk"={"Group":"cert-manager.io","Version":"v1","Kind":"Certificate"} "roles"=["kube-system:cert-manager:leaderelection"] "rules"=["set-revisionHistoryLimit","set-privateKey-rotationPolicy","set-privateKey-details"] "uid"="c4384662-cb2a-49a0-8e83-e590942ec48d" "user"={"username":"system:serviceaccount:cert-manager:cert-manager","uid":"21cbad67-9d2e-44ee-bb02-7fef9aa2e502","groups":["system:serviceaccounts","system:serviceaccounts:cert-manager","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["cert-manager-648cd49b44-z6g8s"],"authentication.kubernetes.io/pod-uid":["4bd741fa-a8ec-48a1-82d5-26c5b7acce5e"]}}

    最後の行を例として使用すると、次のことがわかります。

    "kind"="Certificate" "name"="defaults-example-certificate-tls" "namespace"="default" "operation"="UPDATE" "policy"="mutate-certificates" "resource.gvk"={"Group":"cert-manager.io","Version":"v1","Kind":"Certificate"} "roles"=["kube-system:cert-manager:leaderelection"] "rules"=["set-revisionHistoryLimit","set-privateKey-rotationPolicy","set-privateKey-details"]

    policy キーは、ポリシーが適用されていることを示しています。rules セクションでは、5つのルールのうち3つが生成された "defaults-example-certificate-tls" Certificate リソースに適用されていることを識別できます。

Ingress リソースを使用する場合は、証明書をロードする secretName を常に指定する必要があります。これは Ingress 仕様の必須部分であるため、このユースケースではデフォルト設定は不要です。

ユーザーがIngressリソースで指定する必要がある追加のYAMLは、アノテーションだけです。

cert-manager.io/cluster-issuer: "our-corp-issuer"

このアノテーションは、cert-managerがこのIngressに対して動作するためのトリガーとして機能すると同時に、Certificate.spec.issuerRefフィールドの設定値としても機能します。この1行だけで、ユーザーがCertificateリソースを完全に作成する必要がなくなります。これにより、このIngressの背後でアプリケーションを保護するために必要なYAMLの総量が削減されます。

まとめ

これは、クラスターのCertificateリソースのデフォルトをいかに簡単に設定できるかを示す、かなり単純な例です。ClusterPolicyが設定を「強制」するのではなく、デフォルトオプションを設定および拡張するために使用できることを示しました。Certificateのユーザーは、必要に応じて任意の値を上書きする柔軟性を維持しながら、YAMLを削減できます。

5つのルールのみを持つ単純なClusterPolicyが、Certificateリソースを作成するユーザーエクスペリエンスをどのように変更できるかを示しました。

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: test-revision-override
namespace: default
spec:
dnsNames:
- example.com
issuerRef:
group: cert-manager.io
kind: ClusterIssuer
name: not-my-corp-issuer
privateKey:
algorithm: RSA
encoding: PKCS8
rotationPolicy: Never
size: 4096
revisionHistoryLimit: 44
secretName: test-revision-override-cert

🔗 cert-test-revision-override.yaml

代わりに、ユーザーにとって重要な設定のみを指定する必要がある場合。

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: test-minimal
namespace: default
spec:
dnsNames:
- example.com

🔗 cert-test-minimal.yaml

このポリシーにより、目標を達成し、ユーザーが最小限のCertificateリソースを送信できるようにしました。これにより、仕様に含まれる単一のフィールド、dnsNamesエントリのみを使用した5番目のユースケースが完了しました。指定された他のすべてのフィールドは、通常プラットフォーム管理者によって設定されるClusterPolicyを持つKyvernoを使用して自動的にデフォルト設定されました。

クリーンアップ

このチュートリアルのためにkindクラスターを作成した場合は、単に実行できます。

kind delete cluster --name defaults

それ以外の場合は、このチュートリアルでデプロイされたすべてのリソースを削除するには

# Assuming you are running from this directly or saved all the files to yamls/
kubectl delete -f ingress.yaml
kubectl delete -f cpol-mutate-certificates-1.yaml
helm uninstall kyverno -n kyverno-system
helm uninstall cert-manager -n cert-manager
helm uninstall ingress-nginx -n ingress-nginx

付録

cert-managerのバージョンの要件

cert-managerのミューティングWebhookの動作は、v1.14.x以降から変更されました。変更の詳細については、PR #6311を参照してください。手動での修正手順は、PR #6311のこのコメントにあります。

プリセット機能リクエスト

「デフォルト」または「プリセット」の設定に関する背景情報をさらに読むには、issue 2239を参照してください。このチュートリアルは、その問題の調査から生まれました。

cert-managerチームは、要求されたソリューションは、他の、より一般的なオープンソースポリシーツールを使用することで実現できると判断しました。Kyvernoはその一例に過ぎず、Gatekeeperを代替ツールとして使用しても同様の結果を得ることができます。