Join our Newsletter — 33% off our NHI Course
Home› Guides› cert-manager security guide: Harden issuers, approval and private…
Guide Cloud & Workload Identity

cert-manager security guide: Harden issuers, approval and private key handling

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 28 October 2026 11 min read
On this page

cert-manager mints the TLS and mTLS identities of a Kubernetes cluster, so whoever can create a Certificate against a powerful issuer can obtain a trusted identity for any name that issuer will sign. In most clusters cert-manager runs with defaults: every request to a built-in Issuer or ClusterIssuer is auto-approved, a ClusterIssuer serves every namespace, and CA keys and DNS provider credentials sit in Secrets in the cert-manager namespace. That is fine for public ACME certificates on a single-team cluster and dangerous for an internal CA that backs service-to-service authentication. This guide covers the cert-manager trust model, issuer design, approval policy, private key settings, installation hardening, monitoring and a phased rollout. It is for platform and PKI engineers. Read the ACME and Automated Certificate Management Guide and the Machine Identity, PKI and Certificate Lifecycle Guide for the wider context.

Key takeaways

  • Auto-approval is the default. cert-manager approves every CertificateRequest for cert-manager.io Issuers and ClusterIssuers unless you set disableAutoApproval and deploy a policy approver such as approver-policy.
  • A ClusterIssuer is a cluster-wide signing service. Any namespace whose users can create Certificates can request names from it; reserve ClusterIssuers for public ACME and use namespaced Issuers for internal CAs.
  • The cluster resource namespace holds the crown jewels. ClusterIssuer CA keys, ACME account keys and DNS API tokens live as Secrets in cert-manager by default; treat read access there as access to your PKI.
  • Rotate keys on every issuance. Since v1.18 the default privateKey.rotationPolicy is Always; older installs and explicit Never settings keep one private key for years.
  • Monitor expiry from metrics, not tickets. certmanager_certificate_expiration_timestamp_seconds and certmanager_certificate_ready_status catch failed renewals before an outage.

How cert-manager issues certificates and where trust sits

A Certificate resource describes the desired certificate. The controller generates a private key into the target Secret, creates a CertificateRequest carrying the CSR, waits for it to be Approved, and the issuer signs it. The Approved and Denied conditions are permanent and mutually exclusive, and the webhook uses the SubjectAccessReview API to check that whoever sets them holds the approve verb. cert-manager records the requesting username and groups on each request and rejects attempts to change them; for requests created from a Certificate the requester is cert-manager itself.

Component or assetWhy it mattersWho should reach it
ControllerCreates and modifies Secrets cluster-wide and caches TLS Secrets in memoryNo human exec; dedicated nodes
cainjectorInjects CA bundles into webhooks and CRDs; also caches certificate dataNo human exec
WebhookValidates resources and approval changesAPI server only
CA key Secret for a CA issuerSigns any certificate the issuer allowsController only; break-glass for humans
ACME account key and DNS01 credentialsProve control of your domains to a public CAController only
approve on signersLets a principal approve or deny requestsThe approver deployment only

Issuer design

An Issuer is namespaced and cannot issue Certificates in other namespaces; a ClusterIssuer can issue across all namespaces and reads its referenced Secrets from the cluster resource namespace (cert-manager unless the controller runs with --cluster-resource-namespace). In-tree issuer types are SelfSigned, CA, Vault, CyberArk and ACME (HTTP01 and DNS01).

Issuer typeTypical useMain riskRecommended scope
ACME (public CA)Internet-facing ingressDNS01 token that can edit whole zones; HTTP01 challenge hijack via ingressClusterIssuer is acceptable, with a policy limiting names per namespace
CAInternal mTLS, webhooksCA private key stored in a Kubernetes SecretNamespaced Issuer per trust domain; prefer an intermediate, never a root
Vault or CyberArkEnterprise PKI with external policyThe issuer's auth credential to the PKINamespaced, with role limits enforced in the PKI too
SelfSignedBootstrapping a CACreates untracked trust anchorsRestrict to the platform namespace
  • Keep the CA key out of the cluster where possible: an external issuer backed by Vault, a cloud private CA or an HSM means a cluster compromise yields signing access only while the attacker holds the issuer credential, not a copy of the key. See the AWS Certificate Manager and Private CA Guide.
  • Scope DNS01 credentials: give the DNS solver a token or IAM role limited to the specific zones or records it must change, never an account-wide DNS administrator.
  • Name constraints are not checked by built-in issuers: the CA and SelfSigned issuers do not check SANs against a CA's name constraints, so clients may reject certificates in a TLS handshake. Use policy to limit names, not the CA certificate alone.

Approval policy: replacing auto-approval

approver-policy evaluates CertificateRequestPolicy resources (policy.cert-manager.io/v1alpha1, cluster-scoped). A policy applies to a request only if it is both selected by its selector and bound by RBAC to the requester with the use verb on certificaterequestpolicies. If any matching policy permits the request it is approved; if matching policies exist but none permit it, it is denied; with no matching policy the request is left unprocessed.

Policy fieldBehaviourExample use
allowedLists permitted attributes; omitted fields are deny alldnsNames limited to *.team-a.svc.cluster.local; isCA not allowed
constraintsLimits; omitted constraints are allow allmaxDuration: 720h, privateKey.algorithm: ECDSA, minSize: 256
selector.issuerRefWhich issuers the policy coversThe internal CA Issuer only
selector.namespacematchNames or matchLabelsNamespaces labelled for team-a
  • Turn off the built-in approver: set the Helm value disableAutoApproval=true (v1.15.0 and later) and, if some external issuers should stay auto-approved, list them in approveSignerNames. An empty list approves everything.
  • Bind the right subject: for Certificate resources the requester is the cert-manager controller service account, so bind policies to it and use the namespace selector to distinguish tenants.
  • Restrict the approve verb: grant approve on signers in cert-manager.io only to the approver, with resource names such as issuers.cert-manager.io/<namespace>.<name>. The verb covers both approving and denying.

Private keys, lifetimes and Secrets

SettingDefaultRecommendation
privateKey.rotationPolicyAlways from v1.18 (previously Never)Keep Always; audit for explicit Never
duration90 days (minimum 1 hour)Shorter for internal mTLS, aligned with policy maxDuration
renewBefore / renewBeforePercentageRenew at two thirds of lifetimePrefer renewBeforePercentage to avoid renewal loops
usagesDigital signature, key encipherment, server authAdd client auth only where mTLS clients need it
--enable-certificate-owner-refOff: the Secret survives deletion of the CertificateEnable, or clean up orphaned key Secrets
revisionHistoryLimit1 from v1.18Keep low so old requests do not accumulate
keystores.pkcs12Not created unless setUse passwordSecretRef and the Modern2023 profile when Java clients need PKCS#12
  • Reissue, do not delete: use cmctl renew to rotate keys; the docs advise against deleting the Secret.
  • Do not use ca.crt as a trust store: it changes on renewal. Distribute trust bundles separately.
  • Protect the Secret: the key Secret is base64 in etcd like any other. See the Kubernetes Secrets Security Guide for encryption at rest and RBAC on Secrets.

Where identity fits

Every certificate cert-manager issues for mTLS is a workload identity, and every issuer credential (CA key, ACME account key, DNS token, Vault role) is a non-human identity with the power to create more identities. Inventory them with owners and lifetimes like any other machine credential. ATT&CK tracks the attacker side as T1649 Steal or Forge Authentication Certificates; see the MITRE ATT&CK T1649 Steal or Forge Authentication Certificates Guide and the Kubernetes NHI Security Guide.

Hardening the installation

  • NetworkPolicy: enable networkPolicy.enabled: true but tighten it. The project calls the chart defaults over-permissive (inbound to all listening ports; outbound TCP 443, 6443, TCP/UDP 53 and TCP 80). Allow metrics on TCP 9402 only from your collector.
  • Dedicated nodes: because the controller and cainjector cache TLS Secrets in memory, run them on tainted node pools with nodeSelector and tolerations.
  • Reduce cainjector reach: where it serves only cert-manager's own webhook, run it with --namespace=cert-manager and --enable-certificates-data-source=false.
  • Service account tokens: set automountServiceAccountToken: false on pods and service accounts and mount a read-only projected token explicitly, as in the project's values.best-practice.yaml.
  • Availability: two controller and cainjector replicas, three or more webhook replicas, a PodDisruptionBudget with minAvailable: 1 and priorityClassName: system-cluster-critical, because a dead webhook blocks certificate changes.
  • Stay supported: the project supports at least two releases, each for about four months, and only the latest patch of each.

Detection and measurement

cert-manager exposes Prometheus metrics on port 9402 with the certmanager_ prefix, and the cert-manager-mixin project bundles alerts and dashboards.

SignalSourceAlert when
certmanager_certificate_expiration_timestamp_secondsMetricsLess than one third of lifetime left and no recent renewal
certmanager_certificate_ready_statusMetricsCondition not True for longer than an hour
certmanager_certificate_renewal_timestamp_secondsMetricsRenewal time passed without a new certificate
certmanager_controller_sync_error_count, certmanager_http_acme_client_request_countMetricsSustained errors or ACME rate-limit responses
CertificateRequests with DeniedKubernetes APIAny denial for a namespace that should not request that name
Reads of issuer Secrets, new Issuers or ClusterIssuersKubernetes audit logAny principal other than the controller or platform admins

Metrics that show the programme is working:

  1. Certificates expiring within 7 days that are not Ready (target 0).
  2. Percentage of issuers covered by an approver-policy rule (target 100% of internal issuers).
  3. Certificates with rotationPolicy: Never (trending to 0).
  4. CA keys held in Kubernetes Secrets rather than an external PKI or HSM.
  5. Median certificate lifetime for internal mTLS.

Phased rollout

  1. Inventory: list Issuers, ClusterIssuers, their types, where their keys and credentials live, and which namespaces use them.
  2. Harden the install: apply the best-practice Helm values, NetworkPolicy and dedicated nodes in staging; confirm issuance still works, including ACME HTTP01 through your ingress (v1.18 changed the challenge Ingress PathType to Exact).
  3. Write approver policies: deploy approver-policy alongside the default approver first and write CertificateRequestPolicy rules for each issuer.
  4. Switch approval: set disableAutoApproval=true in staging, watch for requests left unprocessed (no matching policy), fix rules, then repeat in production.
  5. Move internal CAs out: replace CA issuers holding root or intermediate keys in Secrets with an external issuer where feasible.
  6. Rollback: re-enable auto-approval with the Helm value; issued certificates and their Secrets are unaffected, and pending requests proceed.

Framework mapping

PracticeNIST CSF 2.0NIST SP 800-53 r5MITRE ATT&CK
Certificate issuance and workload authenticationPR.AA-03SC-17, IA-5T1649 Steal or Forge Authentication Certificates
Issuer key and credential protectionPR.AA-01SC-12T1552.004 Private Keys
Approval policy and least privilegePR.AA-05AC-6T1587.003 Digital Certificates
Installation hardeningPR.PS-01CM-6, CM-7None specific
Expiry and issuance monitoringDE.CM-09AU-6None specific

Common failure patterns

  • Internal CA as a ClusterIssuer with auto-approval: any team can mint a certificate for another team's service name and impersonate it over mTLS.
  • Root CA key in a Secret: a SelfSigned bootstrap left the root in cert-manager, readable by anyone with Secret read in that namespace or etcd access.
  • Account-wide DNS credentials: the DNS01 token can rewrite any record in the provider account, which is far more than certificate issuance needs.
  • Static private keys: rotationPolicy: Never carried over from older versions, so a stolen key stays valid across every renewal.
  • Silent renewal failure: rate limits, a broken ingress challenge or a removed DNS permission go unnoticed until the certificate expires. See the Certificate Expiry Outages and 47-Day TLS Certificates Guide.

Practitioner checklist

  • Set disableAutoApproval=true and enforce issuer rules with approver-policy.
  • Use namespaced Issuers for internal CAs; keep ClusterIssuers for public ACME.
  • Restrict Secret read in the cluster resource namespace to the controller and break-glass admins.
  • Scope DNS01 credentials to the zones they serve.
  • Keep privateKey.rotationPolicy: Always and cap durations with policy.
  • Apply the best-practice Helm values: tight NetworkPolicy, dedicated nodes, explicit projected tokens.
  • Alert on expiry, not-Ready certificates and renewal errors from cert-manager metrics.
  • Stay on a supported release and review release notes for default changes.

Standards and references

Related NHI Mgmt Group resources: ACME and Automated Certificate Management Guide · Machine Identity, PKI and Certificate Lifecycle Guide · Kubernetes NHI Security Guide · Certificate Revocation Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 28 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org