新機能: プロジェクトの最新情報はこちらで入手できますTwitterMastodon

証明書リソース

apiVersion: cert-manager.io/v1
kind: Certificate

cert-managerでは、Certificate リソースは、証明書要求の人間が読める定義を表します。cert-managerは、この入力を使用して秘密鍵とCertificateRequest リソースを生成し、Issuer または ClusterIssuer から署名付き証明書を取得します。署名付き証明書と秘密鍵は、指定されたSecret リソースに格納されます。cert-managerは、証明書が期限切れになる前に自動更新されること、および要求された場合に再発行されることを保証します。

証明書を発行するには、まずIssuer または ClusterIssuer リソースを構成する必要があります。

証明書リソースの作成

Certificate リソースは、証明書署名要求の生成に使用されるフィールドを指定します。この要求は、参照している発行者タイプによって処理されます。Certificates は、certificate.spec.issuerRef フィールドを指定することで、どの発行者から証明書を取得するかを指定します。

example.comwww.example.com のDNS名、spiffe://cluster.local/ns/sandbox/sa/example URI サブジェクト代替名を持つ、90日間有効で期限切れの15日前に更新されるCertificate リソースの例を以下に示します。Certificate リソースが持つ可能性のあるすべてのオプションの網羅的なリストが含まれていますが、ラベル付きのフィールドのサブセットのみが必要です。

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com
namespace: sandbox
spec:
# Secret names are always required.
secretName: example-com-tls
# secretTemplate is optional. If set, these annotations and labels will be
# copied to the Secret named example-com-tls. These labels and annotations will
# be re-reconciled if the Certificate's secretTemplate changes. secretTemplate
# is also enforced, so relevant label and annotation changes on the Secret by a
# third party will be overwriten by cert-manager to match the secretTemplate.
secretTemplate:
annotations:
my-secret-annotation-1: "foo"
my-secret-annotation-2: "bar"
labels:
my-secret-label: foo
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
# keystores allows adding additional output formats. This is an example for reference only.
keystores:
pkcs12:
create: true
passwordSecretRef:
name: example-com-tls-keystore
key: password
profile: Modern2023
duration: 2160h # 90d
renewBefore: 360h # 15d
isCA: false
usages:
- server auth
- client auth
subject:
organizations:
- cert-manager
# Avoid using commonName for DNS names in end-entity (leaf) certificates. Unless you have a specific
# need for it in your environment, use dnsNames exclusively to avoid issues with commonName.
# Usually, commonName is used to give human-readable names to CA certificates and can be avoided for
# other certificates.
commonName: example.com
# The literalSubject field is exclusive with subject and commonName. It allows
# specifying the subject directly as a string. This is useful for when the order
# of the subject fields is important or when the subject contains special types
# which can be specified by their OID.
#
# literalSubject: "O=jetstack, CN=example.com, 2.5.4.42=John, 2.5.4.4=Doe"
# At least one of commonName (possibly through literalSubject), dnsNames, uris, emailAddresses, ipAddresses or otherNames is required.
dnsNames:
- example.com
- www.example.com
uris:
- spiffe://cluster.local/ns/sandbox/sa/example
emailAddresses:
- john.doe@cert-manager.io
ipAddresses:
- 192.168.0.5
# Needs cert-manager 1.14+ and "OtherNames" feature flag
otherNames:
# Should only supply oid of ut8 valued types
- oid: 1.3.6.1.4.1.311.20.2.3 # User Principal Name "OID"
utf8Value: upn@example.local
# Issuer references are always required.
issuerRef:
name: ca-issuer
# We can reference ClusterIssuers by changing the kind here.
# The default value is Issuer (i.e. a locally namespaced Issuer)
kind: Issuer
# This is optional since cert-manager will default to this value however
# if you are using an external issuer, change this to that issuer group.
group: cert-manager.io

署名付き証明書は、発行者が要求された証明書を正常に発行すると、Certificate と同じ名前空間にある example-com-tls という名前のSecret リソースに格納されます。

secretTemplate が存在する場合、このプロパティに設定されたアノテーションとラベルはexample-com-tls シークレットにコピーされます。両方のプロパティはオプションです。

Certificate は、sandbox 名前空間(Certificate リソースと同じ名前空間)にある ca-issuer という名前の発行者を使用して発行されます。

注:すべての名前空間でCertificate リソースから参照できるIssuer を作成する場合は、ClusterIssuer リソースを作成し、certificate.spec.issuerRef.kind フィールドをClusterIssuer に設定する必要があります。

注:renewBeforeduration フィールドは、Go time.Duration 文字列形式を使用して指定する必要があります。この形式では、d(日)サフィックスは使用できません。webhookコンポーネントをインストールせずにこれを行うと、cert-managerが正しく機能しなくなる可能性があります #1269

注:renewBefore フィールドをduration に非常に近い値に設定すると、Certificate が常に更新期間内にある更新ループが発生する可能性があります。一部のIssuers は、クロックスキューの問題を修正するために、発行時刻の前に発行されたX.509証明書にnotBefore フィールドを設定し、これにより、証明書の有効期間が証明書の全期間よりも短くなります。たとえば、Let's Encryptは発行時刻の1時間前に設定するため、証明書の実際の*有効期間*は89日23時間になります(*全期間*は90日のままです)。

Certificate リソースでサポートされているフィールドの完全なリストは、APIリファレンスドキュメントにあります。

ターゲットシークレット

証明書が中間CAによって発行され、Issuer が発行された証明書のチェーンを提供できる場合、tls.crt の内容は、要求された証明書とその後の証明書チェーンになります。

さらに、認証局が既知の場合、対応するCA証明書はca.crtキーを使用してシークレットに格納されます。たとえば、ACME発行者ではCAは不明であり、ca.crtはシークレットに存在しません。発行時のca.crtの値は、証明書を使用しているアプリケーションの信頼ストアにコピーできます。ただし、ca.crtの値をアプリケーションの信頼ストアに直接マウントしないでください。証明書が更新されると更新されるためです(詳細については証明書の信頼を参照してください)。

cert-managerは、TLSが安全に実行されている状況では役に立たないため、意図的にルート証明書をtls.crtに追加していません。詳細については、次の説明が含まれているRFC 5246セクション7.4.2を参照してください。

証明書検証にはルートキーを個別に配布する必要があるため、ルート証明機関を指定する自己署名証明書は、リモート側が検証のために既にルートキーを保有していることを前提として、チェーンから省略しても構いません。

X.509キー使用法と拡張キー使用法

cert-managerは、いくつかのカスタムキー使用法拡張キー使用法を持つ証明書の要求をサポートしています。cert-managerはこの要求を尊重しようとしますが、一部の発行者は、要求を削除したり、デフォルトを追加したり、完全に無視したりすることがあります。CASelfSigned Issuerは、常に要求された使用法に一致する証明書を返します。

使用法が設定されていない場合、cert-managerはデジタル署名キー暗号化サーバー認証というデフォルトの要求済み使用法を設定します。現在の証明書が現在のキー使用法セットと一致しない場合、cert-managerは新しい証明書の要求を試みません。

サポートされているキー使用法の完全なリストは、APIリファレンスドキュメントにあります。

追加の証明書出力形式

additionalOutputFormatsは、Certificate specのフィールドで、発行された証明書とその秘密鍵の追加の補足形式を指定できます。現在、サポートされている追加の出力形式はCombinedPEMDERの2つです。両方の出力形式を同じCertificateで指定できます。

apiVersion: cert-manager.io/v1
kind: Certificate
spec:
...
secretName: my-cert-tls
additionalOutputFormats:
- type: CombinedPEM
- type: DER
# Results in:
apiVersion: v1
kind: Secret
metadata:
name: my-cert-tls
type: kubernetes.io/tls
data:
ca.crt: <PEM CA certificate>
tls.key: <PEM private key>
tls.crt: <PEM signed certificate chain>
tls-combined.pem: <PEM private key + "\n" + PEM signed certificate chain>
key.der: <DER binary format of private key>

CombinedPEM

CombinedPEMタイプは、結果のCertificateのSecret tls-combined.pemに新しいキーエントリを作成します。このエントリには、PEMエンコードされた秘密鍵、それに続く少なくとも1つの改行文字、それに続くPEMエンコードされた署名済み証明書チェーンが含まれます。

<private key> + "\n" + <signed certificate chain>
apiVersion: v1
kind: Secret
metadata:
name: my-cert-tls
type: kubernetes.io/tls
data:
tls-combined.pem: <PEM private key + "\n" + PEM signed certificate chain>
...

DER

DERタイプは、結果のCertificateのSecret key.derに新しいキーエントリを作成します。このエントリには、秘密鍵のDERバイナリ形式が含まれます。

apiVersion: v1
kind: Secret
metadata:
name: my-cert-tls
type: kubernetes.io/tls
data:
key.der: <DER binary format of private key>
...

名前制約付き証明書の作成

ルートまたは中間CA証明書には名前制約を設定できます。名前制約は、証明パス内の後続の証明書のすべてのサブジェクト名が配置される必要がある名前空間を示します。詳細については、https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10を参照してください。

⛔️ この機能は、cert-managerコントローラーとWebhookコンポーネントの--feature-gatesフラグに追加することでのみ有効になります。

--feature-gates=NameConstraints=true

名前制約を持つCA証明書を作成するには、次の構成を使用します。

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ca-cert-example
spec:
secretName: example-ca-key-pair
isCA: true
issuerRef:
name: selfsigned
kind: ClusterIssuer
commonName: "example1.com"
dnsNames:
- example1.com
nameConstraints:
critical: true
permitted:
dnsDomains: ["example1.com", "example2.com"]
ipRanges: ["10.10.0.0/16"]
emailAddress: ["example@example.org"]
excluded:
ipRanges: ["10.10.0.0/24"]

cert-managerの組み込みCAおよびSelfSigned Issuerと共に使用する場合、SAN(DNS名、IPアドレス、URI、およびメールアドレス)は証明書自身の名前制約と、証明書が属する証明書チェーンに含まれる名前制約のいずれともチェックされません。

証明書は正常に発行される可能性がありますが、TLSハンドシェイク中にクライアントによって拒否される可能性があります。

発行トリガー

有効期限による再発行(更新)

cert-managerはCertificateを自動的に更新します。発行されたX.509証明書の期間と、「renewBefore」値(証明書の有効期限の何時間前に更新するかを指定する)に基づいて、Certificateをいつ更新するかを計算します。

spec.durationspec.renewBefore/spec.renewBeforePercentageフィールドは、CertificateのX.509証明書の期間と「renewBefore」値を指定するために使用できます。spec.durationのデフォルト値は90日です。一部の発行者は、設定された期間の証明書のみを発行するように構成されている可能性があるため、実際の期間は異なる場合があります。spec.renewBeforeは絶対的な期間を指定し、spec.renewBeforePercentageは発行された証明書の実際の期間を使用して有効な「renewBefore」を計算します。spec.renewBeforePercentageの使用をお勧めします。実際の期間が予想よりも短い場合に、更新ループを防ぐことができます。spec.durationの最小値は1時間、有効なspec.renewBeforeの最小値は5分です。spec.duration > spec.renewBeforeとする必要があります。

X.509証明書が発行されると、cert-managerはCertificateの更新時間を計算します。デフォルトでは、X.509証明書の期間の2/3になります。spec.renewBeforeまたはspec.renewBeforePercentageが設定されている場合、有効なspec.renewBefore時間分、有効期限前に設定されます。cert-managerはCertificatestatus.RenewalTimeを更新が試行される時間に設定します。

ユーザー操作による再発行

証明書オブジェクトは、次の状況で再発行されます。

  • 証明書の仕様書の以下のフィールドのいずれかが変更された場合:commonNamednsNamesipAddressesurisemailAddressessubjectisCAusagesduration、またはissuerRef;より詳細な説明は、FAQページにあります。
  • 再発行が以下の方法で手動でトリガーされた場合
    cmctl renew cert-1
    上記の命令にはcmctlが必要です。

証明書リソースに関連付けられたシークレットリソースを削除することは、秘密鍵を手動でローテーションするための推奨される解決策ではありません。秘密鍵を手動でローテーションする推奨される方法は、以下のコマンドを使用して証明書リソースの再発行をトリガーすることです(cmctlが必要です)。

cmctl renew cert-1

発行動作:発行中の仮証明書

イングレスシムを使用して証明書を要求する場合イングレスシムの使用、使用されている場合、コンポーネントingress-gceは、サービスを提供する際に、署名済み証明書の発行を待っている間、仮証明書が存在することを必要とします。これを容易にするために、以下のアノテーションが

cert-manager.io/issue-temporary-certificate: "true"

証明書に存在する場合、署名済み証明書が発行されるまで、自己署名された仮証明書がSecretに存在します。

イングレスに以下のアノテーションを追加すると、「issue-temporary-certificate」が証明書に自動的に設定されます。

acme.cert-manager.io/http01-edit-in-place: "true"

発行動作:秘密鍵のローテーション

デフォルトでは、秘密鍵は自動的にローテーションされません。rotationPolicy: Alwaysの設定を使用すると、証明書オブジェクトに関連付けられた秘密鍵シークレットは、証明書が再発行されるとすぐにローテーションされるように構成できます(発行トリガーを参照)。

rotationPolicy: Alwaysを使用すると、cert-managerは、証明書オブジェクトが正しく署名されるまで待ってから、シークレット内のtls.keyファイルを上書きします。

この設定を使用すると、アプリケーションがマウントされたtls.crttls.keyの変更を検出してそれらを正常にリロードするか、自動的に再起動できる場合、ダウンタイムはありません

アプリケーションが起動時に一度だけ秘密鍵と署名済み証明書を読み込む場合、新しい証明書はアプリケーションによってすぐに提供されません。そのため、kubectl rollout restartでポッドを手動で再起動するか、waveを実行することで自動化します。Waveは、マウントされたシークレットが変更されるたびにデプロイメントの再起動を確実に実行するシークレットコントローラーです。

秘密鍵の再利用

組み込みのVenafiイシューアーなどの一部のイシューアーは、秘密鍵の再利用を許可しない場合があります。この場合、各証明書オブジェクトに対してrotationPolicy: Always設定を明示的に構成する必要があります。

次の例では、証明書にrotationPolicy: Alwaysが設定されています。

apiVersion: cert-manager.io/v1
kind: Certificate
spec:
secretName: my-cert-tls
privateKey:
rotationPolicy: Always # 🔰 Here.

rotationPolicy設定

rotationPolicyの可能な値は次のとおりです。

説明
Never(デフォルト)cert-managerは、各発行で既存の秘密鍵を再利用します。
Always(推奨)cert-managerは、各発行で新しい秘密鍵を生成します。

rotationPolicy: Neverを使用すると、ターゲットシークレットリソースにまだ存在しない場合にのみ秘密鍵が生成されます(tls.keyキーを使用)。それ以降のすべての発行では、この秘密鍵が再利用されます。これは、以前のリリースとの互換性を維持するためにデフォルトです。

rotationPolicy: Alwaysを使用すると、アクションが証明書オブジェクトの再発行をトリガーするたびに新しい秘密鍵が生成されます(上記の秘密鍵のローテーションをトリガーするアクションを参照)。証明書オブジェクトの作成時に秘密鍵シークレットが既に存在する場合、ローテーションメカニズムには最初の発行も含まれるため、既存の秘密鍵は使用されません。

👉 証明書リソースにrotationPolicy: Alwaysを構成することをお勧めします。証明書と秘密鍵の両方を同時にローテーションすることで、公開された秘密鍵を使用して証明書を発行するリスクを防ぎます。秘密鍵を定期的に更新するもう1つの利点は、緊急時に秘密鍵のローテーションを実行できるという確信を持つことができることです。一般的に、キーをできるだけ頻繁にローテーションして、キーの侵害に関連するリスクを軽減することは良い習慣です。

証明書が削除されたときのシークレットのクリーンアップ

デフォルトでは、cert-managerは、対応するCertificateリソースが削除されたときに、署名済み証明書を含むSecretリソースを削除しません。これは、Certificateを削除しても、現在その証明書に依存しているサービスは停止しませんが、証明書は更新されなくなります。Secretはもう必要ない場合は、手動で削除する必要があります。

Certificateが削除されたときにSecretを自動的に削除する方が良い場合は、コントローラーに--enable-certificate-owner-refフラグを渡すようにインストールを構成する必要があります。

開発者向けの内部動作図

[1] https://cert-manager.dokyumento.jp/docs/usage/certificaterequest