NEW: Get project updates onTwitterandMastodon

SelfSigned

⚠️ SelfSigned issuers are generally useful for bootstrapping a PKI locally, which is a complex topic for advanced users. To be used safely in production, running a PKI introduces complex planning requirements around rotation, trust store distribution and disaster recovery.

If you're not planning to run your own PKI, use a different issuer type.

The SelfSigned issuer doesn't represent a certificate authority as such, but instead denotes that certificates will "sign themselves" using a given private key. In other words, the private key of the certificate will be used to sign the certificate itself.

This Issuer type is useful for bootstrapping a root certificate for a custom PKI (Public Key Infrastructure), or for otherwise creating simple ad-hoc certificates for a quick test.

There are important caveats - including security issues - to consider with SelfSigned issuers; in general you'd likely want to use a CA issuer rather than a SelfSigned issuer. That said, SelfSigned issuers are really useful for initially bootstrapping a CA issuer.

Note: a CertificateRequest that references a self-signed certificate must also contain the cert-manager.io/private-key-secret-name annotation since the private key corresponding to the CertificateRequest is required to sign the certificate. This annotation is added automatically by the Certificate controller.

Deployment

Since the SelfSigned issuer has no dependency on any other resource, it is the simplest to configure. Only the SelfSigned stanza is required to be present in the issuer spec, with no other configuration required:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
namespace: sandbox
spec:
selfSigned: {}
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-cluster-issuer
spec:
selfSigned: {}

Once deployed, you should be able to see immediately that the issuer is ready for signing:

$ kubectl get issuers -n sandbox -o wide selfsigned-issuer
NAME READY STATUS AGE
selfsigned-issuer True 2m
$ kubectl get clusterissuers -o wide selfsigned-cluster-issuer
NAME READY STATUS AGE
selfsigned-cluster-issuer True 3m

Bootstrapping CA Issuers

One of the ideal use cases for SelfSigned issuers is to bootstrap a custom root certificate for a private PKI, including with the cert-manager CA issuer.

The YAML below will create a SelfSigned issuer, issue a root certificate and use that root as a CA issuer:

apiVersion: v1
kind: Namespace
metadata:
name: sandbox
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-selfsigned-ca
namespace: sandbox
spec:
isCA: true
commonName: my-selfsigned-ca
secretName: root-secret
privateKey:
algorithm: ECDSA
size: 256
issuerRef:
name: selfsigned-issuer
kind: ClusterIssuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: my-ca-issuer
namespace: sandbox
spec:
ca:
secretName: root-secret

Alternatively, if you are looking to use ClusterIssuer for signing Certificates anywhere in your cluster with the SelfSigned Certificate CA, use the YAML below (slight modification to the last step):

apiVersion: v1
kind: Namespace
metadata:
name: sandbox
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-selfsigned-ca
namespace: cert-manager
spec:
isCA: true
commonName: my-selfsigned-ca
secretName: root-secret
privateKey:
algorithm: ECDSA
size: 256
issuerRef:
name: selfsigned-issuer
kind: ClusterIssuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: my-ca-issuer
spec:
ca:
secretName: root-secret

The "selfsigned-issuer" ClusterIssuer is used to issue the Root CA Certificate. Then, "my-ca-issuer" ClusterIssuer is used to issue but also sign certificates using the newly created Root CA Certificate, which is what you will use for future certificates cluster-wide.

CRL Distribution Points

You may also optionally specify CRL Distribution Points as an array of strings, each of which identifies the location of a CRL in which the revocation status of issued certificates can be checked:

...
spec:
selfSigned:
crlDistributionPoints:
- "http://example.com"

Caveats

Trust

Clients consuming SelfSigned certificates have no way to trust them without already having the certificates beforehand, which can be hard to manage when the client is in a different namespace to the server.

This limitation can be tackled by using trust-manager to distribute ca.crt to other namespaces.

There is no secure alternative to solving the problem of distributing trust stores; it's possible to "TOFU" (trust-on-first-use) a certificate, but that approach is vulnerable to man-in-the-middle attacks.

Certificate Validity

One side-effect of a certificate being self-signed is that its Subject DN and its Issuer DN are identical. The X.509 RFC 5280, section 4.1.2.4 requires that:

The issuer field MUST contain a non-empty distinguished name (DN).

However, self-signed certs don't have a subject DN set by default. Unless you manually set a certificate's Subject DN, the Issuer DN will be empty and the certificate will technically be invalid.

Validation of this specific area of the spec is patchy and varies between TLS libraries, but there's always the risk that a library will improve its validation - entirely within spec - in the future and break your app if you're using a certificate with an empty Issuer DN.

To avoid this, be sure to set a Subject for SelfSigned certs. This can be done by setting the spec.subject on a cert-manager Certificate object which will be issued by a SelfSigned issuer.

Starting in version 1.3, cert-manager will emit a Kubernetes warning event of type BadConfig if it detects that a certificate is being created by a SelfSigned issuer which has an empty Issuer DN.