@@ -52,6 +53,7 @@ export default function Sidebar({ router, routes, versions }) {
version={version}
versions={versions}
setSidebarCollapsed={setSidebarCollapsed}
+ setParentOpen={() => {}}
/>
diff --git a/components/docs/VersionSelect.jsx b/components/docs/VersionSelect.jsx
index 255c4d1060..40738b7612 100644
--- a/components/docs/VersionSelect.jsx
+++ b/components/docs/VersionSelect.jsx
@@ -13,7 +13,8 @@ function labelFromVersion(version) {
export default function VersionSelect({
version,
versions,
- setSidebarCollapsed
+ setSidebarCollapsed,
+ setParentOpen
}) {
const [selectedVersion, setSelectedVersion] = useState(version)
@@ -36,6 +37,7 @@ export default function VersionSelect({
href="docs"
caption="latest"
setSidebarCollapsed={setSidebarCollapsed}
+ setParentOpen={setParentOpen}
/>
@@ -46,6 +48,7 @@ export default function VersionSelect({
href={version}
caption={labelFromVersion(version)}
setSidebarCollapsed={setSidebarCollapsed}
+ setParentOpen={setParentOpen}
/>
@@ -55,6 +58,7 @@ export default function VersionSelect({
href="https://release-next--cert-manager-website.netlify.app/docs/"
caption="next release"
setSidebarCollapsed={setSidebarCollapsed}
+ setParentOpen={setParentOpen}
/>
diff --git a/content/docs/cli/acmesolver.md b/content/docs/cli/acmesolver.md
index baee31aff4..799941ec2d 100644
--- a/content/docs/cli/acmesolver.md
+++ b/content/docs/cli/acmesolver.md
@@ -2,6 +2,7 @@
title: acmesolver CLI reference
description: "cert-manager acmesolver CLI documentation"
---
+
```
HTTP server used to solve ACME challenges.
diff --git a/content/docs/cli/cainjector.md b/content/docs/cli/cainjector.md
index 0bcdf50014..757eb98bde 100644
--- a/content/docs/cli/cainjector.md
+++ b/content/docs/cli/cainjector.md
@@ -2,8 +2,8 @@
title: cainjector CLI reference
description: "cert-manager cainjector CLI documentation"
---
-```
+```
cert-manager CA injector is a Kubernetes addon to automate the injection of CA data into
webhooks and APIServices from cert-manager certificates.
@@ -12,34 +12,41 @@ CA data from the referenced certificates, which can then be used to serve API
servers and webhook servers.
Usage:
- ca-injector [flags]
+ cainjector [flags]
Flags:
- --add_dir_header If true, adds the file directory to the header of the log messages
- --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
- --enable-profiling Enable profiling for cainjector
- --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
- AllAlpha=true|false (ALPHA - default=false)
- AllBeta=true|false (BETA - default=false)
- -h, --help help for ca-injector
- --kubeconfig string Paths to a kubeconfig. Only required if out-of-cluster.
- --leader-elect If true, cainjector will perform leader election between instances to ensure no more than one instance of cainjector operates at a time (default true)
- --leader-election-lease-duration duration The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. This is only applicable if leader election is enabled. (default 1m0s)
- --leader-election-namespace string Namespace used to perform leader election. Only used if leader election is enabled (default "kube-system")
- --leader-election-renew-deadline duration The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. This is only applicable if leader election is enabled. (default 40s)
- --leader-election-retry-period duration The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled. (default 15s)
- --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
- --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
- --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
- --log_file string If non-empty, use this log file (no effect when -logtostderr=true)
- --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
- --logtostderr log to standard error instead of files (default true)
- --namespace string If set, this limits the scope of cainjector to a single namespace. If set, cainjector will not update resources with certificates outside of the configured namespace.
- --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
- --profiler-address string Address of the Go profiler (pprof) if enabled. This should never be exposed on a public interface. (default "localhost:6060")
- --skip_headers If true, avoid header prefixes in the log messages
- --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
- --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
- -v, --v Level number for the log level verbosity
- --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
+ --add_dir_header If true, adds the file directory to the header of the log messages (DEPRECATED: this flag may be removed in the future)
+ --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --enable-apiservices-injectable Inject CA data to annotated APIServices. This functionality is not required if cainjector is only used as cert-manager's internal component and setting it to false might reduce memory consumption (default true)
+ --enable-certificates-data-source Enable configuring cert-manager.io Certificate resources as potential sources for CA data. Requires cert-manager.io Certificate CRD to be installed. This data source can be disabled to reduce memory consumption if you only use cainjector as part of cert-manager's installation (default true)
+ --enable-customresourcedefinitions-injectable Inject CA data to annotated CustomResourceDefinitions. This functionality is not required if cainjecor is only used as cert-manager's internal component and setting it to false might slightly reduce memory consumption (default true)
+ --enable-mutatingwebhookconfigurations-injectable Inject CA data to annotated MutatingWebhookConfigurations. This functionality is required for cainjector to work correctly as cert-manager's internal component (default true)
+ --enable-profiling Enable profiling for controller.
+ --enable-validatingwebhookconfigurations-injectable Inject CA data to annotated ValidatingWebhookConfigurations. This functionality is required for cainjector to correctly function as cert-manager's internal component (default true)
+ --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
+ AllAlpha=true|false (ALPHA - default=false)
+ AllBeta=true|false (BETA - default=false)
+ ServerSideApply=true|false (ALPHA - default=false)
+ -h, --help help for cainjector
+ --kubeconfig string Paths to a kubeconfig. Only required if out-of-cluster.
+ --leader-elect If true, cainjector will perform leader election between instances to ensure no more than one instance of cainjector operates at a time
+ --leader-election-lease-duration duration The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. This is only applicable if leader election is enabled.
+ --leader-election-namespace string Namespace used to perform leader election. Only used if leader election is enabled
+ --leader-election-renew-deadline duration The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. This is only applicable if leader election is enabled.
+ --leader-election-retry-period duration The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled.
+ --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+ --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) (DEPRECATED: this flag may be removed in the future)
+ --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --log_file string If non-empty, use this log file (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) (DEPRECATED: this flag may be removed in the future)
+ --logging-format string Sets the log format. Permitted formats: "json" (gated by LoggingBetaOptions), "text". (default "text")
+ --logtostderr log to standard error instead of files (default true) (DEPRECATED: this flag may be removed in the future)
+ --namespace string If set, this limits the scope of cainjector to a single namespace. If set, cainjector will not update resources with certificates outside of the configured namespace.
+ --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --profiler-address string The host and port that Go profiler should listen on, i.e localhost:6060. Ensure that profiler is not exposed on a public address. Profiler will be served at /debug/pprof. (default "localhost:6060")
+ --skip_headers If true, avoid header prefixes in the log messages (DEPRECATED: this flag may be removed in the future)
+ --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2) (DEPRECATED: this flag may be removed in the future)
+ -v, --v Level number for the log level verbosity
+ --vmodule pattern=N,... comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)
```
diff --git a/content/docs/cli/cmctl.md b/content/docs/cli/cmctl.md
index dff83b3bc2..ca992f37ca 100644
--- a/content/docs/cli/cmctl.md
+++ b/content/docs/cli/cmctl.md
@@ -2,8 +2,8 @@
title: cmctl CLI reference
description: "cert-manager cmctl CLI documentation"
---
-```
+```
cmctl is a CLI tool manage and configure cert-manager resources for Kubernetes
Usage: cmctl [command]
@@ -11,6 +11,7 @@ Usage: cmctl [command]
Available Commands:
approve Approve a CertificateRequest
check Check cert-manager components
+ completion Generate completion scripts for the cert-manager CLI
convert Convert cert-manager config files between different API versions
create Create cert-manager resources
deny Deny a CertificateRequest
@@ -25,6 +26,9 @@ Available Commands:
Flags:
-h, --help help for cmctl
--log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+ --logging-format string Sets the log format. Permitted formats: "json" (gated by LoggingBetaOptions), "text". (default "text")
+ -v, --v Level[=2] number for the log level verbosity
+ --vmodule pattern=N,... comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)
Use "cmctl [command] --help" for more information about a command.
```
diff --git a/content/docs/cli/controller.md b/content/docs/cli/controller.md
index 768ffb05cc..7da64fa882 100644
--- a/content/docs/cli/controller.md
+++ b/content/docs/cli/controller.md
@@ -2,8 +2,8 @@
title: controller CLI reference
description: "cert-manager controller CLI documentation"
---
-```
+```
cert-manager is a Kubernetes addon to automate the management and issuance of
TLS certificates from various issuing sources.
@@ -11,21 +11,23 @@ It will ensure certificates are valid and up to date periodically, and attempt
to renew certificates at an appropriate time before expiry.
Usage:
- cert-manager-controller [flags]
+ controller [flags]
Flags:
- --acme-http01-solver-image string The docker image to use to solve ACME HTTP01 challenges. You most likely will not need to change this parameter unless you are testing a new feature or developing cert-manager. (default "quay.io/jetstack/cert-manager-acmesolver:canary")
+ --acme-http01-solver-image string The docker image to use to solve ACME HTTP01 challenges. You most likely will not need to change this parameter unless you are testing a new feature or developing cert-manager. (default "quay.io/jetstack/cert-manager-acmesolver:v1.13.2")
--acme-http01-solver-nameservers strings A list of comma separated dns server endpoints used for ACME HTTP01 check requests. This should be a list containing host and port, for example 8.8.8.8:53,8.8.4.4:53
--acme-http01-solver-resource-limits-cpu string Defines the resource limits CPU size when spawning new ACME HTTP01 challenge solver pods. (default "100m")
--acme-http01-solver-resource-limits-memory string Defines the resource limits Memory size when spawning new ACME HTTP01 challenge solver pods. (default "64Mi")
--acme-http01-solver-resource-request-cpu string Defines the resource request CPU size when spawning new ACME HTTP01 challenge solver pods. (default "10m")
--acme-http01-solver-resource-request-memory string Defines the resource request Memory size when spawning new ACME HTTP01 challenge solver pods. (default "64Mi")
--acme-http01-solver-run-as-non-root Defines the ability to run the http01 solver as root for troubleshooting issues (default true)
- --add_dir_header If true, adds the file directory to the header of the log messages
- --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
+ --add_dir_header If true, adds the file directory to the header of the log messages (DEPRECATED: this flag may be removed in the future)
+ --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
--auto-certificate-annotations strings The annotation consumed by the ingress-shim controller to indicate a ingress is requesting a certificate (default [kubernetes.io/tls-acme])
--cluster-issuer-ambient-credentials Whether a cluster-issuer may make use of ambient credentials for issuers. 'Ambient Credentials' are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the ClusterIssuer API object. When this flag is enabled, the following sources for credentials are also used: AWS - All sources the Go SDK defaults to, notably including any EC2 IAM roles available via instance metadata. (default true)
--cluster-resource-namespace string Namespace to store resources owned by cluster scoped resources such as ClusterIssuer in. This must be specified if ClusterIssuers are enabled. (default "kube-system")
+ --concurrent-workers int The number of concurrent workers for each controller. (default 5)
+ --config string Path to a file containing a ControllerConfiguration object used to configure the controller
--controllers strings A list of controllers to enable. '--controllers=*' enables all on-by-default controllers, '--controllers=foo' enables just the controller named 'foo', '--controllers=*,-foo' disables the controller named 'foo'.
All controllers: issuers, clusterissuers, certificates-metrics, ingress-shim, gateway-shim, orders, challenges, certificaterequests-issuer-acme, certificaterequests-approver, certificaterequests-issuer-ca, certificaterequests-issuer-selfsigned, certificaterequests-issuer-vault, certificaterequests-issuer-venafi, certificates-trigger, certificates-issuing, certificates-key-manager, certificates-request-manager, certificates-readiness, certificates-revision-manager (default [*])
--copied-annotation-prefixes strings Specify which annotations should/shouldn't be copiedfrom Certificate to CertificateRequest and Order, as well as from CertificateSigningRequest to Order, by passing a list of annotation key prefixes.A prefix starting with a dash(-) specifies an annotation that shouldn't be copied. Example: '*,-kubectl.kuberenetes.io/'- all annotationswill be copied apart from the ones where the key is prefixed with 'kubectl.kubernetes.io/'. (default [*,-kubectl.kubernetes.io/,-fluxcd.io/,-argocd.argoproj.io/])
@@ -33,7 +35,7 @@ Flags:
--default-issuer-kind string Kind of the Issuer to use when the tls is requested but issuer kind is not specified on the ingress resource. (default "Issuer")
--default-issuer-name string Name of the Issuer to use when the tls is requested but issuer name is not specified on the ingress resource.
--dns01-check-retry-period duration The duration the controller should wait between a propagation check. Despite the name, this flag is used to configure the wait period for both DNS01 and HTTP01 challenge propagation checks. For DNS01 challenges the propagation check verifies that a TXT record with the challenge token has been created. For HTTP01 challenges the propagation check verifies that the challenge token is served at the challenge URL.This should be a valid duration string, for example 180s or 1h (default 10s)
- --dns01-recursive-nameservers strings A list of comma separated dns server endpoints used for DNS01 check requests. This should be a list containing host and port, for example 8.8.8.8:53,8.8.4.4:53
+ --dns01-recursive-nameservers : A list of comma separated dns server endpoints used for DNS01 and DNS-over-HTTPS (DoH) check requests. This should be a list containing entries of the following formats: : or `https://`. For example: `8.8.8.8:53,8.8.4.4:53` or `https://1.1.1.1/dns-query,https://8.8.8.8/dns-query`. To make sure ALL DNS requests happen through DoH, `dns01-recursive-nameservers-only` should also be set to true.
--dns01-recursive-nameservers-only When true, cert-manager will only ever query the configured DNS resolvers to perform the ACME DNS01 self check. This is useful in DNS constrained environments, where access to authoritative nameservers is restricted. Enabling this option could cause the DNS01 self check to take longer due to caching performed by the recursive nameservers.
--enable-certificate-owner-ref Whether to set the certificate resource as an owner of secret where the tls certificate is stored. When this flag is enabled, the secret will be automatically removed when the certificate resource is deleted.
--enable-profiling Enable profiling for controller.
@@ -41,14 +43,16 @@ Flags:
AdditionalCertificateOutputFormats=true|false (ALPHA - default=false)
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
+ DisallowInsecureCSRUsageDefinition=true|false (BETA - default=true)
ExperimentalCertificateSigningRequestControllers=true|false (ALPHA - default=false)
ExperimentalGatewayAPISupport=true|false (ALPHA - default=false)
LiteralCertificateSubject=true|false (ALPHA - default=false)
+ SecretsFilteredCaching=true|false (BETA - default=true)
ServerSideApply=true|false (ALPHA - default=false)
- StableCertificateRequestName=true|false (ALPHA - default=false)
+ StableCertificateRequestName=true|false (BETA - default=true)
UseCertificateRequestBasicConstraints=true|false (ALPHA - default=false)
ValidateCAA=true|false (ALPHA - default=false)
- -h, --help help for cert-manager-controller
+ -h, --help help for controller
--issuer-ambient-credentials Whether an issuer may make use of ambient credentials. 'Ambient Credentials' are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the Issuer API object. When this flag is enabled, the following sources for credentials are also used: AWS - All sources the Go SDK defaults to, notably including any EC2 IAM roles available via instance metadata.
--kube-api-burst int the maximum burst queries-per-second of requests sent to the Kubernetes apiserver (default 50)
--kube-api-qps float32 indicates the maximum queries-per-second requests to the Kubernetes apiserver (default 20)
@@ -59,20 +63,21 @@ Flags:
--leader-election-renew-deadline duration The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. This is only applicable if leader election is enabled. (default 40s)
--leader-election-retry-period duration The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled. (default 15s)
--log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
- --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
- --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
- --log_file string If non-empty, use this log file (no effect when -logtostderr=true)
- --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
- --logtostderr log to standard error instead of files (default true)
+ --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) (DEPRECATED: this flag may be removed in the future)
+ --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --log_file string If non-empty, use this log file (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) (DEPRECATED: this flag may be removed in the future)
+ --logging-format string Sets the log format. Permitted formats: "json" (gated by LoggingBetaOptions), "text". (default "text")
+ --logtostderr log to standard error instead of files (default true) (DEPRECATED: this flag may be removed in the future)
--master string Optional apiserver host address to connect to. If not specified, autoconfiguration will be attempted.
--max-concurrent-challenges int The maximum number of challenges that can be scheduled as 'processing' at once. (default 60)
--metrics-listen-address string The host and port that the metrics endpoint should listen on. (default "0.0.0.0:9402")
--namespace string If set, this limits the scope of cert-manager to a single namespace and ClusterIssuers are disabled. If not specified, all namespaces will be watched
- --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
+ --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
--profiler-address string The host and port that Go profiler should listen on, i.e localhost:6060. Ensure that profiler is not exposed on a public address. Profiler will be served at /debug/pprof. (default "localhost:6060")
- --skip_headers If true, avoid header prefixes in the log messages
- --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
- --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
+ --skip_headers If true, avoid header prefixes in the log messages (DEPRECATED: this flag may be removed in the future)
+ --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2) (DEPRECATED: this flag may be removed in the future)
-v, --v Level number for the log level verbosity
- --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
+ --vmodule pattern=N,... comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)
```
diff --git a/content/docs/cli/webhook.md b/content/docs/cli/webhook.md
index f4d6ef30c3..8adb4add42 100644
--- a/content/docs/cli/webhook.md
+++ b/content/docs/cli/webhook.md
@@ -2,15 +2,20 @@
title: webhook CLI reference
description: "cert-manager webhook CLI documentation"
---
+
```
-Webhook component providing API validation, mutation and conversion functionality for cert-manager (canary) ()
+cert-manager is a Kubernetes addon to automate the management and issuance of
+TLS certificates from various issuing sources.
+
+The webhook component provides API validation, mutation and conversion
+functionality for cert-manager.
Usage:
webhook [flags]
Flags:
- --add-dir-header If true, adds the file directory to the header of the log messages
- --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
+ --add_dir_header If true, adds the file directory to the header of the log messages (DEPRECATED: this flag may be removed in the future)
+ --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
--api-server-host string Optional apiserver host address to connect to. If not specified, autoconfiguration will be attempted.
--config string Path to a file containing a WebhookConfiguration object used to configure the webhook
--dynamic-serving-ca-secret-name string name of the secret used to store the CA that signs serving certificates certificates
@@ -18,34 +23,31 @@ Flags:
--dynamic-serving-dns-names strings DNS names that should be present on certificates generated by the dynamic serving CA
--enable-profiling Enable profiling for webhook.
--feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
- AdditionalCertificateOutputFormats=true|false (ALPHA - default=false)
- AllAlpha=true|false (ALPHA - default=false)
- AllBeta=true|false (BETA - default=false)
- ExperimentalCertificateSigningRequestControllers=true|false (ALPHA - default=false)
- ExperimentalGatewayAPISupport=true|false (ALPHA - default=false)
- LiteralCertificateSubject=true|false (ALPHA - default=false)
- ServerSideApply=true|false (ALPHA - default=false)
- StableCertificateRequestName=true|false (ALPHA - default=false)
- UseCertificateRequestBasicConstraints=true|false (ALPHA - default=false)
- ValidateCAA=true|false (ALPHA - default=false)
- --healthz-port int port number to listen on for insecure healthz connections (default 6080)
+ AdditionalCertificateOutputFormats=true|false (ALPHA - default=false)
+ AllAlpha=true|false (ALPHA - default=false)
+ AllBeta=true|false (BETA - default=false)
+ DisallowInsecureCSRUsageDefinition=true|false (BETA - default=true)
+ LiteralCertificateSubject=true|false (ALPHA - default=false)
+ --healthz-port int32 port number to listen on for insecure healthz connections (default 6080)
-h, --help help for webhook
--kubeconfig string optional path to the kubeconfig used to connect to the apiserver. If not specified, in-cluster-config will be used
- --log-backtrace-at traceLocation when logging hits line file:N, emit a stack trace (default :0)
- --log-dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
- --log-file string If non-empty, use this log file (no effect when -logtostderr=true)
- --log-file-max-size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
- --logtostderr log to standard error instead of files (default true)
- --one-output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
+ --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+ --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) (DEPRECATED: this flag may be removed in the future)
+ --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --log_file string If non-empty, use this log file (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) (DEPRECATED: this flag may be removed in the future)
+ --logging-format string Sets the log format. Permitted formats: "json" (gated by LoggingBetaOptions), "text". (default "text")
+ --logtostderr log to standard error instead of files (default true) (DEPRECATED: this flag may be removed in the future)
+ --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
--profiler-address string Address of the Go profiler (pprof). This should never be exposed on a public interface. If this flag is not set, the profiler is not run. (default "localhost:6060")
- --secure-port int port number to listen on for secure TLS connections (default 6443)
- --skip-headers If true, avoid header prefixes in the log messages
- --skip-log-headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
- --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
+ --secure-port int32 port number to listen on for secure TLS connections (default 6443)
+ --skip_headers If true, avoid header prefixes in the log messages (DEPRECATED: this flag may be removed in the future)
+ --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true) (DEPRECATED: this flag may be removed in the future)
+ --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2) (DEPRECATED: this flag may be removed in the future)
--tls-cert-file string path to the file containing the TLS certificate to serve with
--tls-cipher-suites strings Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be use. Possible values: TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_RC4_128_SHA
--tls-min-version string Minimum TLS version supported. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13
--tls-private-key-file string path to the file containing the TLS private key to serve with
-v, --v Level number for the log level verbosity
- --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
+ --vmodule pattern=N,... comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)
```
diff --git a/content/docs/concepts/acme-orders-challenges.md b/content/docs/concepts/acme-orders-challenges.md
index 80c31606e4..f4e1d3e2a5 100644
--- a/content/docs/concepts/acme-orders-challenges.md
+++ b/content/docs/concepts/acme-orders-challenges.md
@@ -20,9 +20,9 @@ In order to complete these challenges, cert-manager introduces two
validation can be found on the Let's Encrypt website
[here](https://letsencrypt.org/how-it-works/). An order represents a single
certificate request which will be created automatically once a new
-[`CertificateRequest`](./certificaterequest.md) resource referencing an ACME
+[`CertificateRequest`](../usage/certificaterequest.md) resource referencing an ACME
issuer has been created. `CertificateRequest` resources are created
-automatically by cert-manager once a [`Certificate`](./certificate.md) resource
+automatically by cert-manager once a [`Certificate`](../usage/certificate.md) resource
is created, has its specification changed, or needs renewal.
As an end-user, you will never need to manually create an `Order` resource.
diff --git a/content/docs/concepts/webhook.md b/content/docs/concepts/webhook.md
index 1bcbbee769..05345edf43 100644
--- a/content/docs/concepts/webhook.md
+++ b/content/docs/concepts/webhook.md
@@ -35,7 +35,7 @@ cert-manager controller and CA injector components.
In order for the API server to communicate with the webhook component, the
webhook requires a TLS certificate that the apiserver is configured to trust.
-The [`cainjector`](./ca-injector.md) creates `secret/cert-manager-webhook-ca`, a self-signed root CA certificate which is used to sign certificates for the webhook pod.
+The webhook creates `secret/cert-manager-webhook-ca` in the namespace where the webhook is deployed. This secret contains a self-signed root CA certificate which is used to sign certificates for the webhook pod in order to fulfill this requirement.
Then the webhook can be configured with either
@@ -73,7 +73,7 @@ For these reasons, after installing cert-manager and when performing post-instal
you will need to check for temporary API configuration errors and retry.
You could also add a post-installation check which performs `kubectl --dry-run` operations on the cert-manager API.
-Or you could add a post-installation check which automatically retries the [Installation Verification](../installation/verify.md) steps until they succeed.
+Or you could add a post-installation check which automatically retries the [Installation Verification](../installation/kubectl.md#verify) steps until they succeed.
### Other Webhook Problems
diff --git a/content/docs/configuration/acme/README.md b/content/docs/configuration/acme/README.md
index 51a9014ac1..47eb22c9ee 100644
--- a/content/docs/configuration/acme/README.md
+++ b/content/docs/configuration/acme/README.md
@@ -367,11 +367,9 @@ spec:
```
-## Alternative Certificate Chains
-
{/* The empty link below preserves old links to #alternative-certificate-chain", which matched the old title of this section */}
-
-
+
+## Alternative Certificate Chains
It's possible to choose alternative certificate chains when fetching a certificate from an ACME server. This allows issuers to gracefully roll people over to a new root certificate during a transition period; the most famous example was the Let's Encrypt ["ISRG Root" changeover](https://community.letsencrypt.org/t/transition-to-isrgs-root-delayed-until-jan-11-2021/125516).
diff --git a/content/docs/configuration/acme/dns01/README.md b/content/docs/configuration/acme/dns01/README.md
index b9240f8045..d952eef568 100644
--- a/content/docs/configuration/acme/dns01/README.md
+++ b/content/docs/configuration/acme/dns01/README.md
@@ -180,6 +180,8 @@ Links to these supported providers along with their documentation are below:
- [`cert-manager-webhook-yandex-cloud`](https://github.com/malinink/cert-manager-webhook-yandex-cloud)
- [`cert-manager-webhook-netcup`](https://github.com/aellwein/cert-manager-webhook-netcup)
- [`cert-manager-webhook-pdns`](https://github.com/zachomedia/cert-manager-webhook-pdns)
+- [`cert-manager-webhook-zilore`](https://gitlab.com/zilore/cert-manager-webhook-zilore)
+- [`stackit-cert-manager-webhook`](https://github.com/stackitcloud/stackit-cert-manager-webhook)
You can find more information on how to configure webhook providers [here](./webhook.md).
diff --git a/content/docs/configuration/acme/dns01/google.md b/content/docs/configuration/acme/dns01/google.md
index 460239de80..b9b6db839a 100644
--- a/content/docs/configuration/acme/dns01/google.md
+++ b/content/docs/configuration/acme/dns01/google.md
@@ -45,7 +45,8 @@ gcloud projects add-iam-policy-binding $PROJECT_ID \
> * `dns.resourceRecordSets.*`
> * `dns.changes.*`
> * `dns.managedZones.list`
-
+>
+> In case you do not use the `dns.admin` role, you will also need to make sure that the Service Account used by your GKE cluster (e.g. the Compute Engine default service account) has the `https://www.googleapis.com/auth/cloud-platform` access scope assigned to it. See [Access scopes in GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/access-scopes).
## Use Static Credentials
Follow the instructions in the following sections to deploy cert-manager using
diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md
index f18bbf128c..e441b3b0c3 100644
--- a/content/docs/configuration/acme/dns01/route53.md
+++ b/content/docs/configuration/acme/dns01/route53.md
@@ -56,7 +56,7 @@ not have to store permanent credentials in a secret.
cert-manager supports two ways of specifying credentials:
-- explicit by providing a `accessKeyID` and `secretAccessKey`
+- explicit by providing an `accessKeyID` or an `accessKeyIDSecretRef`, and a `secretAccessKeySecretRef`
- or implicit (using [metadata
service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)
or [environment variables or credentials
@@ -168,7 +168,13 @@ spec:
dns01:
route53:
region: eu-central-1
+ # The AWS access key ID can be specified using the literal accessKeyID parameter
+ # or retrieved from a secret using the accessKeyIDSecretRef
+ # If using accessKeyID, omit the accessKeyIDSecretRef parameter and vice-versa
accessKeyID: AKIAIOSFODNN7EXAMPLE
+ accessKeyIDSecretRef:
+ name: prod-route53-credentials-secret
+ key: access-key-id
secretAccessKeySecretRef:
name: prod-route53-credentials-secret
key: secret-access-key
diff --git a/content/docs/configuration/acme/http01/README.md b/content/docs/configuration/acme/http01/README.md
index e8663f6fdd..2e3e8242af 100644
--- a/content/docs/configuration/acme/http01/README.md
+++ b/content/docs/configuration/acme/http01/README.md
@@ -101,7 +101,8 @@ solver, potentially incurring additional cost.
-
`serviceType`
+
+### `serviceType`
In rare cases it might be not possible/desired to use `NodePort` as type for the
HTTP01 challenge response service, e.g. because of Kubernetes limit
@@ -348,7 +349,8 @@ spec:
After the Certificate is issued, the HTTPRoute is deleted.
-
`labels`
+
+### `labels`
These labels are copied into the temporary HTTPRoute created by cert-manager for
solving the HTTP-01 challenge. These labels must match one of the Gateway
@@ -357,7 +359,8 @@ resources on your cluster. The matched Gateway have a listener on port 80.
Note that when the labels do not match any Gateway on your cluster, cert-manager
will create the temporary HTTPRoute challenge and nothing will happen.
-
`serviceType`
+
+### `serviceType`
This field has the same meaning as the
[`http01.ingress.serviceType`](#ingress-service-type).
diff --git a/content/docs/configuration/ca.md b/content/docs/configuration/ca.md
index fffb6f2401..c2a21a34f4 100644
--- a/content/docs/configuration/ca.md
+++ b/content/docs/configuration/ca.md
@@ -15,7 +15,7 @@ private key are stored inside the cluster as a Kubernetes `Secret`.
Certificates issued by a CA issuer will not be publicly trusted and so are unlikely to be trusted
by your applications without further configuration.
-Consider [trust-manager](../projects/trust-manager/README.md) for distributing your CA certificate safely
+Consider [trust-manager](../trust/trust-manager/README.md) for distributing your CA certificate safely
across your cluster!
## Deployment
diff --git a/content/docs/configuration/issuers.md b/content/docs/configuration/issuers.md
new file mode 100644
index 0000000000..ce1940b679
--- /dev/null
+++ b/content/docs/configuration/issuers.md
@@ -0,0 +1,119 @@
+---
+title: Issuers
+description: 'cert-manager configuration: Issuers'
+---
+
+The following list contains all known cert-manager issuer integrations.
+
+
+
+[production:venafi-enhanced-issuer]: https://platform.jetstack.io/documentation/academy/issue-and-approve-certificates-with-venafi-control-plane
+[production:acme-issuer]: ../tutorials/getting-started-aks-letsencrypt/README.md
+
+[//]: # (Configuration docs)
+
+[config:venafi-enhanced-issuer]: https://docs.venafi.cloud/vaas/k8s-components/t-vei-install/
+[config:acme-issuer]: ./acme.md
+
+[config:aws-privateca-issuer]: https://github.com/cert-manager/aws-privateca-issuer
+[config:selfsigned-issuer]: ./selfsigned.md
+[config:ca-issuer]: ./ca.md
+[config:vault-issuer]: ./vault.md
+[config:venafi-issuer]: ./venafi.md
+[config:step-issuer]: https://github.com/smallstep/step-issuer
+[config:origin-ca-issuer]: https://github.com/cloudflare/origin-ca-issuer
+[config:ncm-issuer]: https://github.com/nokia/ncm-issuer
+[config:tcs-issuer]: https://github.com/intel/trusted-certificate-issuer
+[config:google-cas-issuer]: https://github.com/jetstack/google-cas-issuer
+[config:ejbca-issuer]: https://github.com/Keyfactor/ejbca-cert-manager-issuer
+[config:command-issuer]: https://github.com/Keyfactor/command-cert-manager-issuer
+[config:horizon-issuer]: https://github.com/evertrust/horizon-issuer
+
+[config:kms-issuer]: https://github.com/Skyscanner/kms-issuer
+[config:freeipa-issuer]: https://github.com/guilhem/freeipa-issuer
+[config:adcs-issuer]: https://github.com/nokia/adcs-issuer
+[config:cfssl-issuer]: https://gerrit.wikimedia.org/r/plugins/gitiles/operations/software/cfssl-issuer
+
+[//]: # (Release pages)
+
+[release:venafi-enhanced-issuer]: https://platform.jetstack.io/documentation/installation/venafi-enhanced-issuer/
+[release:cert-manager]: ../releases/README.md
+
+[release:aws-privateca-issuer]: https://github.com/cert-manager/aws-privateca-issuer/releases
+[release:step-issuer]: https://github.com/smallstep/step-issuer/releases
+[release:origin-ca-issuer]: https://github.com/cloudflare/origin-ca-issuer/releases
+[release:ncm-issuer]: https://github.com/nokia/ncm-issuer/releases
+[release:tcs-issuer]: https://github.com/intel/trusted-certificate-issuer/releases
+[release:google-cas-issuer]: https://github.com/jetstack/google-cas-issuer/releases
+[release:ejbca-issuer]: https://github.com/Keyfactor/ejbca-cert-manager-issuer/tags
+[release:command-issuer]: https://github.com/Keyfactor/command-cert-manager-issuer/releases
+[release:horizon-issuer]: https://github.com/evertrust/horizon-issuer/releases
+
+[release:kms-issuer]: https://github.com/Skyscanner/kms-issuer/releases
+[release:freeipa-issuer]: https://github.com/guilhem/freeipa-issuer/releases
+[release:adcs-issuer]: https://github.com/nokia/adcs-issuer/releases
+[release:cfssl-issuer]: https://gerrit.wikimedia.org/r/plugins/gitiles/operations/software/cfssl-issuer/+refs
+
+- The issuers are sorted by their tier and then alphabetically.
+- "in-tree" issuers are issuers that are shipped with cert-manager itself.
+- These issuers are known to support and honor [approval](https://cert-manager.io/docs/concepts/certificaterequest/#approval).
+
+If you've created an issuer which you'd like to share,
+[raise a Pull Request](https://github.com/cert-manager/website/pulls) to have it added here!
+
+## Issuer Tier system
+
+The cert-manager project has a tier system for issuers. This is to help users
+understand the maturity of the issuer.
+The tiers are 🥇, 🥈 and 🥉.
+
+NOTE: The cert-manager maintainers can decide to change the criteria and number
+of tiers at any time.
+
+### 🥇 Tier (Production-ready)
+
+- 🥈 Tier criteria.
+- The issuer has an end-to-end tutorial on how to set it up with cert-manager for use in production.
+At the time of checking[^1], the used cert-manager version has to be still supported (see [Supported Releases](../releases/README.md)).
+An end-to-end tutorial must include:
+ 1. a short explanation on how to install cert-manager (including the used version and a link to [https://cert-manager.io/docs/installation/](../installation/))
+ 2. all required steps to install the issuer
+ 3. an explanation on how to configure the issuer's Custom Resources
+ 4. an explanation on how to issue a certificate using the issuer (using a Certificate resource)
+
+### 🥈 Tier (Maintained)
+
+- The issuer has had a release in the last 12 months (at the time of checking all issuers[^2]).
+
+### 🥉 Tier (Unmaintained)
+
+Other
+
+[^1]: checked on 12th of October 2023
+[^2]: checked on 12th of October 2023
+
+## Building New External Issuers
+
+If you're interested in building a new external issuer, check the [development documentation](../contributing/external-issuers.md).
diff --git a/content/docs/configuration/selfsigned.md b/content/docs/configuration/selfsigned.md
index bfc2b39b2b..76c92a530e 100644
--- a/content/docs/configuration/selfsigned.md
+++ b/content/docs/configuration/selfsigned.md
@@ -117,6 +117,48 @@ spec:
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):
+
+```yaml
+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](https://en.wikipedia.org/wiki/Certificate_revocation_list)
@@ -139,7 +181,7 @@ 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](../projects/trust-manager/README.md) to distribute `ca.crt`
+This limitation can be tackled by using [trust-manager](../trust/trust-manager/README.md) to distribute `ca.crt`
to other namespaces.
There is no secure alternative to solving the problem of distributing trust stores; it's possible
diff --git a/content/docs/configuration/vault.md b/content/docs/configuration/vault.md
index c5d6df0923..f2b15b5435 100644
--- a/content/docs/configuration/vault.md
+++ b/content/docs/configuration/vault.md
@@ -369,9 +369,14 @@ Kubernetes 1.24 and above.
## Verifying the issuer Deployment
Once the Vault issuer has been deployed, it will be marked as ready if the
-configuration is valid. Replace `issuers` here with `clusterissuers` if that is what has
+configuration is valid. Replace `issuers` below with `clusterissuers` if that is what has
been deployed.
+The Vault issuer tests your Vault instance by querying the `v1/sys/health`
+endpoint, to ensure your Vault instance is unsealed and initialized before
+requesting certificates. The result of that query will populate the `STATUS`
+column.
+
```bash
$ kubectl get issuers vault-issuer -n sandbox -o wide
NAME READY STATUS AGE
@@ -379,4 +384,4 @@ vault-issuer True Vault verified 2m
```
Certificates are now ready to be requested by using the Vault issuer named
-`vault-issuer` within the `sandbox` namespace.
\ No newline at end of file
+`vault-issuer` within the `sandbox` namespace.
diff --git a/content/docs/configuration/venafi.md b/content/docs/configuration/venafi.md
index 93498b0ace..29cbbd04c7 100644
--- a/content/docs/configuration/venafi.md
+++ b/content/docs/configuration/venafi.md
@@ -100,7 +100,7 @@ vaas-issuer True Venafi issuer started 2m
You are now ready to issue certificates using the newly provisioned Venafi
`Issuer` and Venafi as a Service.
-Read the [Issuing Certificates](../usage/certificate.md) document for
+Read the [Requesting Certificates](../usage/certificate.md) document for
more information on how to create Certificate resources.
@@ -139,7 +139,7 @@ credentials.
### Access Token Authentication
-1. [Set up token authentication](https://docs.venafi.com/Docs/21.1/TopNav/Content/SDK/AuthSDK/t-SDKa-Setup-OAuth.php).
+1. [Set up token authentication](https://docs.venafi.com/Docs/23.1/TopNav/Content/SDK/AuthSDK/t-SDKa-Setup-OAuth.php).
NOTE: Do not select "Refresh Token Enabled" and set a *long* "Token Validity (days)".
@@ -147,7 +147,7 @@ credentials.
E.g. `k8s-xyz-automation`
-3. [Create a new application integration](https://docs.venafi.com/Docs/21.1/TopNav/Content/API-ApplicationIntegration/t-APIAppIntegrations-creatingNew-Aperture.php)
+3. [Create a new application integration](https://docs.venafi.com/Docs/21.4/TopNav/Content/API-ApplicationIntegration/t-APIAppIntegrations-creatingNew-Aperture.php)
Create an application integration with name and ID `cert-manager`.
Set the "API Access Settings" to `Certificates: Read,Manage,Revoke`.
@@ -256,7 +256,7 @@ $ kubectl describe issuer tpp-issuer --namespace='NAMESPACE OF YOUR ISSUER RESOU
You are now ready to issue certificates using the newly provisioned Venafi
`Issuer` and Trust Protection Platform.
-Read the [Issuing Certificates](../usage/certificate.md) document for
+Read the [Requesting Certificates](../usage/certificate.md) document for
more information on how to create Certificate resources.
## Issuer specific annotations
diff --git a/content/docs/contributing/README.md b/content/docs/contributing/README.md
index 2c51a0a0b1..aec6b21254 100644
--- a/content/docs/contributing/README.md
+++ b/content/docs/contributing/README.md
@@ -13,26 +13,56 @@ some details on how to build, test and run cert-manager for development purposes
## Meetings
-All cert-manager meetings are open for everyone to join!
+All cert-manager meetings are open for everyone to join; if you have a question or a suggestion or just want to chat,
+please feel free to come along and get involved!
-To get invites you can subscribe to [our mailing list](https://groups.google.com/forum/#!forum/cert-manager-dev).
+To get invites you can subscribe to [our mailing list](https://groups.google.com/forum/#!forum/cert-manager-dev) and
+you should receive calendar invites by mail shortly after joining. The complexities of calendars mean that some invites
+might be sent multiple times depending on your email and calendar providers and you might get some invites for past
+or future meetings which have been rescheduled or edited. Sorry about that!
-We have 2 regular repeating meetings:
-
-* daily stand-up meetings [on Google Meet](https://meet.google.com/eum-fyvt-xpa) at [10:30 London time](http://www.thetimezoneconverter.com/?t=10:30&tz=Europe/London) every weekday
-* bi-weekly developer meetings [on Google Meet](https://meet.google.com/iga-jwvx-nye) at [17:00 London time](http://www.thetimezoneconverter.com/?t=17:00&tz=Europe/London) (for dates, check calendar invites or [meeting notes](https://docs.google.com/document/d/1Tc5t6ylY9dhXAan1OjOoldeaoys1Yh4Ir710ATfBa5U))
+We have 2 regular repeating meetings: our quick daily check-in and an hour-long community meeting every two weeks.
If you're having any issues joining our meetings, ensure that you're part of the [`cert-manager-dev`](https://groups.google.com/forum/#!forum/cert-manager-dev) Google group, and always feel free to ask in [Slack](./#slack) for help!
+
+🔰 All of our meetings happen on London (UK) time; you can add London to the world clocks on your phone to avoid confusion!
+
+When daylight savings time changes in London might be different to when it changes for you if you live in a place that either
+doesn't have DST or which changes on a different schedule like North America or Australia!
+
+
+### Daily Check-In
+
+Our daily check-in meetings [happen on Google Meet](https://meet.google.com/eum-fyvt-xpa) at [10:30 London time](http://www.thetimezoneconverter.com/?t=10:30&tz=Europe/London) every weekday.
+
+The format is a 5 minute social chat, followed by a quick round-robin status report and ending with any longer form talking points.
+
+The status report is a stand-up where we talk about work done yesterday, work coming up and highlight any blockers.
+We'll try to keep to a **strict time limit** during these status reports of around 1 minute per person.
+
+Please don't be offended if someone steps in when you run out of time and moves the reports along to the next person - the idea
+is for everyone to be succinct so it's clear what's being worked on and who is blocked.
+
+We finish with talking points, which are open-ended discussions on any topic related to cert-manager or its sub-projects.
+We'll ensure that anyone outside of the core maintainer team who has a talking point goes first.
+
+### Community Meetings
+
+Our bi-weekly (i.e. every two weeks) community meetings happen [on Google Meet](https://meet.google.com/iga-jwvx-nye) at [17:00 London time](http://www.thetimezoneconverter.com/?t=17:00&tz=Europe/London) (for dates, check calendar invites or [meeting notes](https://docs.google.com/document/d/1Tc5t6ylY9dhXAan1OjOoldeaoys1Yh4Ir710ATfBa5U)).
+
+These meetings are an hour-long chat about cert-manager topics. It's a great way to get involved with contributing for the
+first time; to get answers to any questions you might have; or to propose a new feature which needs some explanation.
+
+If you want to discuss something, please add it to the [meeting notes](https://docs.google.com/document/d/1Tc5t6ylY9dhXAan1OjOoldeaoys1Yh4Ir710ATfBa5U)
+before the meeting. The meeting chair will try to get to everything that was on the notes before the meeting started.
+
+We try to record these meetings and put them on YouTube so they can be checked later - if you don't want to appear on video please keep
+your camera off!
+
## Slack
We have two cert-manager channels on [Kubernetes Slack](https://slack.k8s.io) which we use to chat:
* [`cert-manager`](https://kubernetes.slack.com/messages/cert-manager): for all users of cert-manager; use this one for any usage related questions
* [`cert-manager-dev`](https://kubernetes.slack.com/messages/cert-manager-dev): for collaboration between cert-manager contributors and maintainers; please only use this for code related questions
-
-## Google Season of Docs 2022
-
-The cert-manager team are participating in [Google Season of Docs 2022](https://developers.google.com/season-of-docs)!
-
-Check out our [2022 Project Proposals](./google-season-of-docs/2022/README.md) if you want to get involved!
diff --git a/content/docs/contributing/api-compatibility.md b/content/docs/contributing/api-compatibility.md
new file mode 100644
index 0000000000..e65567fcf7
--- /dev/null
+++ b/content/docs/contributing/api-compatibility.md
@@ -0,0 +1,22 @@
+---
+title: API compatibility
+description: cert-manager API compatibility guarantees
+---
+
+cert-manager aims to abide by the same API compatibility policy as upstream Kubernetes APIs as documented in the [Kubernetes Deprecation Policy](https://kubernetes.io/docs/reference/using-api/deprecation-policy/#deprecating-parts-of-the-api).
+
+This is to ensure a smooth upgrade and downgrade experience for users, i.e to make sure that users' cert-manager custom resources keep functioning in the same way
+after an upgrade or downgrade of cert-manager.
+
+In some cases, we may need to require users to take actions before upgrading or may need to diverge from the API compatibility promise but we'll treat this as an absolute
+last resort. In general the main criteria by which we'd determine whether a change is acceptable would be user value.
+
+For example in the event of a truly critical bug, a fix that breaks the API compatibility promise by changing the default behavior of an API field _might_ be acceptable. As of yet, though, there has never been a need for such a change.
+
+## Alpha / Beta API Versions
+
+As in upstream Kubernetes, We don't commit to preserving alpha or beta API versions indefinitely.
+
+In cert-manager v1.7 [all alpha and beta API versions prior to `v1` were removed](https://github.com/cert-manager/cert-manager/pull/4635).
+
+NB: The Kubernetes deprecation policy notes that API removal introduces an issue with objects stored at the removed versions. To fix this, we wrote a [custom tool](https://cert-manager.io/docs/releases/upgrading/remove-deprecated-apis/) that users could run once to migrate their resources.
diff --git a/content/docs/contributing/building.md b/content/docs/contributing/building.md
index 010abbcf49..92fd7a996f 100644
--- a/content/docs/contributing/building.md
+++ b/content/docs/contributing/building.md
@@ -7,8 +7,11 @@ cert-manager is built and tested using [make](https://www.gnu.org/software/make/
where possible and keeping system dependencies to a minimum. The cert-manager build system can provision most of its dependencies - including Go -
automatically if required.
-cert-manager's build system fully supports developers who use `Linux amd64`, `macOS amd64` and `macOS arm64`. Other operating systems and architectures may
-work, but are largely untested.
+cert-manager's build system fully supports developers who use `Linux amd64`, `macOS amd64` and `macOS arm64`.
+
+It also has limited support for `Linux arm64`, although that platform is largely untested and isn't fully supported.
+
+Other operating systems and architectures may work but will likely require hacks and workarounds to develop on.
## Prerequisites
@@ -67,6 +70,29 @@ go version go1.AB.C linux/amd64
go binary used for above version information: go
```
+### Go Workspaces
+
+In short: Some development tools will complain about cert-manager's module layout; to help with this, generate a
+`go.work` file using `make go-workspace`.
+
+The cert-manager repository as of cert-manager 1.12 contains multiple Go modules, in a setup where only the core module `github.com/cert-manager/cert-manager`
+is expected to be imported by third party modules. There are separate modules (which we call submodules), all of which have replace statements for the core
+cert-manager module.
+
+This setup is intentional to convey that these submodules are not intended to be imported by third parties, and to ensure that each submodule always uses
+whatever the cert-manager core module version is at the same commit - but this structure can have the side effect that certain development tools and scripts
+will not work as expected.
+
+As an example, `go test ./...` will by default only affect the core module. To test, say, the controller, you'd need to use `cd cmd/controller && go test ./...`.
+
+This can be avoided through the use of go workspaces, which will handle local replacements for you and work better with editors such as VS Code.
+
+You can run `make go-workspace` to generate a `go.work` file which should enable `go test ./...` to work across the
+whole repo, and which should help editors to understand the module structure.
+
+Note that go workspaces are not used when testing pull requests in CI. If you see errors in CI which you can't replicate
+locally, try building with the `GOWORK` environment variable set to `off` or deleting the `go.work` file.
+
### Parallelism
The cert-manager Makefile is designed to be highly parallel wherever possible. Any build and test commands should be able to be executed in parallel using
@@ -104,6 +130,8 @@ There are make targets to help with this; see [Developing with Kind](./kind.md)
First of all: If you want to test using `go test`, feel free! For unit tests (which we define as any test outside of the `test/` directory), `go test` will
work on a fresh checkout.
+Note that the cert-manager repo is split into multiple modules and unless you're using go workspaces `go test ./...` won't actually run all tests. See [Go Workspaces](./building.md#go-workspaces) above for more details.
+
Integration tests may require some external tools to be set up first, so to run the integration tests inside `test/` you might need to run:
```bash
diff --git a/content/docs/contributing/contributing-flow.md b/content/docs/contributing/contributing-flow.md
index 4706a0d169..7dc1c0d02a 100644
--- a/content/docs/contributing/contributing-flow.md
+++ b/content/docs/contributing/contributing-flow.md
@@ -73,11 +73,51 @@ To let people know that your PR is still a work in progress, we usually add a
`WIP:` prefix to the title of the PR. Prow will then automatically set the label
`do-not-merge/work-in-progress`.
+### Release Note Guidelines
+
+The `release-note` code block in the PR description aims at explaining to the
+end-user whether they should care about this change and whether they will be
+affected. It is OK to have multiple sentences as long as it is written in good
+English (subject verb complement, ends with a dot).
+
+A release note block shouldn't just paraphrase the commit message. For example,
+the end-user doesn't know what "comparisons" are and which custom resources are
+affected:
+
+~~~markdown
+```release-note
+Adds missing comparisons for certain fields which were incorrectly skipped if a LiteralSubject was set
+```
+~~~
+
+A better release note block gives context and specifically tells the end-user
+how they will be affected:
+
+~~~markdown
+```release-note
+When using the `literalSubject` on a Certificate, the IPs, URIs, DNS names, and email addresses subject segments are now properly compared.
+```
+~~~
+
+New lines in the release note block translate to hard line breaks, which means
+it is not possible to soft-wrap the release note. A new line can be useful for
+lists:
+
+~~~markdown
+```release-note
+cainjector:
+- New flags were added to the cainjector binary. They can be used to modify what injectable kinds are enabled. If cainjector is only used as a cert-manager's internal component it is sufficient to only enable validatingwebhookconfigurations and mutatingwebhookconfigurations injectable resources; disabling the rest can improve memory consumption. By default all are enabled.
+- The `--watch-certs` flag was renamed to `--enable-certificates-data-source`.
+```
+~~~
+
+If this PR introduces a breaking change, the release note block must start with
+`**BREAKING:**` (note the bold text).
### Cherry Picking
If the pull request contains a critical bug fix then this should be cherry picked in to the current stable cert-manager branch
-and [released as a patch release](../installation/supported-releases.md#support-policy).
+and [released as a patch release](../releases/README.md#support-policy).
To trigger the cherry-pick process, add a comment to the GitHub PR.
For example:
diff --git a/content/docs/contributing/crds.md b/content/docs/contributing/crds.md
index 1cce203032..586a68d218 100644
--- a/content/docs/contributing/crds.md
+++ b/content/docs/contributing/crds.md
@@ -56,7 +56,7 @@ While cert-manager doesn't fully use Kubebuilder, CRDs can make use of special K
## Making Changes to APIs
-Please see our [API compatibility promise](../installation/api-compatibility.md) for details on which types of changes to APIs are acceptable.
+Please see our [API compatibility promise](../contributing/api-compatibility.md) for details on which types of changes to APIs are acceptable.
Generally, the gist is that new fields can be added but that existing fields cannot be removed.
diff --git a/content/docs/contributing/e2e.md b/content/docs/contributing/e2e.md
index 5037b28fa4..9e6b9e7409 100644
--- a/content/docs/contributing/e2e.md
+++ b/content/docs/contributing/e2e.md
@@ -137,7 +137,7 @@ The master branch of cert-manager can also be tested against different cloud pro
The infrastructure used to run the e2e tests on cloud providers is present in the [cert-manager/test-infra](https://github.com/cert-manager/test-infra) repository. More cloud providers can be added by creating infrastructure for them using [Terraform](https://www.terraform.io/).
-Apart from that, tests for the existing infrastructure can be customized by editing their respective prow jobs present in the [Jetstack testing repository](https://github.com/jetstack/testing/tree/master/config/jobs/cert-manager) repository. Values like the cert-manager version or the cloud provider version are present as variables in Terraform so their values can be changed when using `terraform apply` in the prow jobs, for example, for the [EKS prow job](https://github.com/jetstack/testing/blob/master/config/jobs/cert-manager/cert-manager-periodics.yaml#L524) the cert-manager version being tested can be changed using
+Apart from that, tests for the existing infrastructure can be customized by editing their respective prow jobs present in the [Jetstack testing repository](https://github.com/cert-manager/testing/tree/master/config/jobs/cert-manager) repository. Values like the cert-manager version or the cloud provider version are present as variables in Terraform so their values can be changed when using `terraform apply` in the prow jobs, for example, for the [EKS prow job](https://github.com/cert-manager/testing/blob/master/config/jobs/cert-manager/cert-manager-periodics.yaml#L524) the cert-manager version being tested can be changed using
```console
terraform apply -var="cert_manager_version=v1.3.3" -auto-approve
diff --git a/content/docs/contributing/external-issuers.md b/content/docs/contributing/external-issuers.md
index 4169a95f89..b7f141a4f9 100644
--- a/content/docs/contributing/external-issuers.md
+++ b/content/docs/contributing/external-issuers.md
@@ -10,8 +10,8 @@ Since the number of potential issuers is larger than what could reasonably be su
main cert-manager repository, cert-manager also supports out-of-tree external issuers, and treats
them the same as in-tree issuer types.
-This document is for people looking to _create_ external issuers. For more information on how to
-install and configure external issuer types, read the [configuration documentation](../configuration/external.md).
+This document is for people looking to _create_ external issuers.
+For a list of example external issuers, see the [issuers page](../configuration/issuers.md).
## General Overview
@@ -49,20 +49,13 @@ on how to write an external issuer using Kubebuilder and controller-runtime.
## Approval
Before signing a certificate, Issuers **must** also ensure that the `CertificateRequest` is
-[`Approved`](../concepts/certificaterequest.md#approval).
+[`Approved`](../usage/certificaterequest.md#approval).
If the `CertificateRequest` is not `Approved`, the issuer **must** not process it. Issuers are not
responsible for approving `CertificateRequests` and should refuse to proceed if they find a certificate
that is not approved.
-### Supporting Legacy cert-manager Releases
-
-Certificate approval was added to cert-manager in `v1.3`. In order to support older versions of cert-manager,
-external issuers may choose to sign `CertificateRequests` that will never have an approval
-condition set, but this should be feature-gated and disabled by default.
-
-If you're creating a new External Issuer today, we'd strongly recommend that you do not support such old
-versions of cert-manager.
+If a `CertificateRequest` created for an issuance associated with a `Certificate` gets [`Denied`](../usage/certificaterequest.md#approval), the issuance will be failed by cert-manager's issuing controller.
## Conditions
@@ -72,7 +65,7 @@ status of that resource to a ready state, as this is what is used to signal to h
controllers - such as the `Certificate` controller - that the resource is ready to be consumed.
Conversely, if the `CertificateRequest` fails, it is as important to mark the resource as such, as this will
-also be used as a signal to higher order controllers. Valid condition states are listed under [concepts](../concepts/certificaterequest.md#conditions).
+also be used as a signal to higher order controllers. Valid condition states are listed under [concepts](../usage/certificaterequest.md#conditions).
## Implementation
diff --git a/content/docs/contributing/featuregates.md b/content/docs/contributing/featuregates.md
index 4e6f332967..50e3e1bb8b 100644
--- a/content/docs/contributing/featuregates.md
+++ b/content/docs/contributing/featuregates.md
@@ -1,31 +1,34 @@
---
-Title: Implementing feature gates
-description: 'cert-manager contributing guide: Implementing feature gates'
+title: cert-manager feature gates
+description: 'cert-manager contributing guide: Feature gates'
---
-As of v1 release cert-manager is considered stable. We aim to follow Kubernetes API compatibility policy when making API changes, see [API compatibility](../installation/api-compatibility.md) to avoid breaking users' existing cert-manager installations.
+As of v1 release cert-manager is considered stable. We aim to follow Kubernetes API compatibility policy when making API changes, see [API compatibility](../contributing/api-compatibility.md) to avoid breaking users' existing cert-manager installations.
This means that as developers we are somewhat limited in regards to changing existing behavior, i.e renaming or removing API elements or changing their behavior.
New functionality that is not yet stable[^1] can still be added, but it needs to be placed behind a feature gate.
+## Enabling/ disabling feature gates
+
+Feature gates can be enabled or disabled using CLI flags or config files, more info can be found in [configuring components](../installation/configuring-components.md).
+
## Feature gated API fields
-Feature gated API fields are implemented using `--feature-gates` flags of cert-manager [webhook](../cli/webhook.md) and [controller](../cli/controller.md).
+Feature gated API fields are implemented using `--feature-gates` flags of cert-manager [webhook](../cli/webhook.md), [cainjector](../cli/cainjector.md) and [controller](../cli/controller.md).
A feature gated API field is always visible to the user (i.e when running `kubectl explain `), but is only functional if the relevant feature is explicitly enabled via feature flags for both the webhook and controller.
If a user attempts to apply a resource with the feature gated field set to a non-nil value, but the feature gate is not enabled, the resource will get rejected by the webhook validation.
This mechanism differs from [the one that Kubernetes uses for feature gated API field implementation](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md#new-field-in-existing-api-version) where the field will be simply set to nil if the feature gate is disabled. We chose to use webhook validation instead to make debugging easier for users who are attempting to use the feature gated field, but have forgotten to enable the feature gate.
-
### Implementation
- Implement the new field and document that it is feature gated and in order to use it the controller and webhook feature gates need enabling
-- Add a new [webhook feature gate](https://github.com/cert-manager/cert-manager/blob/3a055cc2f56c1c2874807af4a8f84d0a1c46ccb4/internal/webhook/feature/features.go#L25-L39) for the field
+- Add a new [webhook feature gate](https://github.com/cert-manager/cert-manager/blob/7c7e8f4ce6c1abba18025d3d00be368066801a63/internal/webhook/feature/features.go#L31-L64) for the field
- Update webhook validation checks for the relevant resource kind to ensure that if the feature gated field is set, but the webhook feature gate is not enabled, the resource gets rejected
-- Add a new [controller feature gate](https://github.com/cert-manager/cert-manager/blob/2417132b3cd017b5f0974006e03c2b8a540efe3f/internal/controller/feature/features.go#L26-L54) for the field
+- Add a new [controller feature gate](https://github.com/cert-manager/cert-manager/blob/7c7e8f4ce6c1abba18025d3d00be368066801a63/internal/controller/feature/features.go#L32-L121) for the field
- Ensure that any control loops that use the feature, check that the feature gate is actually enabled. (This is required to cover edge cases such as if the webhook runs a version of cert-manager where the feature is in GA whereas controller runs an older version where the feature is still in experimental state)
-- Ensure that the feature gate is added to cert-manager installation scripts for CI and local tests in [make](https://github.com/cert-manager/cert-manager/blob/134398e939bb2b1401697eaf589405ad469cd609/make/e2e-setup.mk#L165) and [bazel](https://github.com/cert-manager/cert-manager/blob/fd747b42b9ab4b6409b61b7946e8dc14d532e950/devel/addon/certmanager/install.sh#L26) scripts
+- Ensure that the feature gate is added to cert-manager installation scripts for CI and local tests in [make](https://github.com/cert-manager/cert-manager/blob/7c7e8f4ce6c1abba18025d3d00be368066801a63/make/e2e-setup.mk#L197) and [bash](https://github.com/cert-manager/cert-manager/blob/7c7e8f4ce6c1abba18025d3d00be368066801a63/make/e2e.sh#L80) scripts
- Default cert-manger e2e CI tests run with all feature gates for all components enabled. There is an additional optional e2e test that runs with all feature gates disabled. You can trigger that for your PR with `/test pull-cert-manager-e2e-feature-gates-disabled` to verify that all works as expected both with and without the new feature gate.
### Potential issues
@@ -36,9 +39,7 @@ This mechanism differs from [the one that Kubernetes uses for feature gated API
### References
-- cert-manager's [API compatibility promise](../installation/api-compatibility.md)
-
-- An example implementation of an alpha field is [`AdditionalOutputFormats` field on `Certificate` spec](https://github.com/cert-manager/cert-manager/blob/dbad3d98f3d7d85cadb4bd2c2493faf8b666b313/internal/apis/certmanager/types_certificate.go#L169-L174)
+- cert-manager's [API compatibility promise](../contributing/api-compatibility.md)
- [Kubernetes definition of feature stages](https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-stages)
diff --git a/content/docs/contributing/google-season-of-docs/2022/improve-navigation-and-structure.md b/content/docs/contributing/google-season-of-docs/2022/improve-navigation-and-structure.md
index 8f23636af3..496ef1be33 100644
--- a/content/docs/contributing/google-season-of-docs/2022/improve-navigation-and-structure.md
+++ b/content/docs/contributing/google-season-of-docs/2022/improve-navigation-and-structure.md
@@ -165,6 +165,60 @@ We would like them to quickly and easily find the information they need.
By making it easier for each group to find the information they need we aim to reduce the number of support queries.
+## Audiences
+
+### New User
+
+Has never used cert-manager and may never have used Kubernetes.
+Wants to find out what cert-manager can offer.
+May have heard about cert-manager in another tutorial.
+May want to know what are the alternatives to cert-manager and the trade offs.
+Needs to install cert-manager quickly so that they evaluate it on their laptop.
+Needs to learn basic configuration of cert-manager.
+Needs to understand what are the next steps.
+
+### Ongoing User
+
+A programmer who wants to deploy a TLS protected APP.
+Knows that cert-manager has been installed by their cluster administrator.
+Has an existing Issuer or ClusterIssuer.
+Needs to know how to create a Certificate which is appropriate for their application. E.g.
+* Create a certificate for their PostgreSQL database
+* Create an certificate for their Ingress / Gateway
+Needs to know how to debug why their certificate hasn’t renewed
+Needs to understand the error messages on cert-manager Certificates and Certificate requests
+Needs to know which errors they can fix and which errors require assistance from their cluster administrator.
+
+### Cluster Administrator
+
+Knows Kubernetes.
+Has a long running cert-manager installation.
+Wants to know how to configure it and upgrade it for optimum performance.
+Wants to optimize for large numbers of certificates.
+Wants to upgrade from older versions.
+Wants to monitor cert-manager performance
+Wants to set up alerts to notify them when cert-manager goes wrong.
+May want to configure cert-manager for multiple cloud providers.
+May want to get cert-manager working with some other cluster scoped system like Istio or Knative.
+
+### Integrator
+
+May want to allow cert-manager users to make use of a custom Certificate service.
+May want to integrate cert-manager with a DNS API for ACME DNS01.
+May want to depend on cert-manager for managing TLS certificates for a higher level system.
+Needs to learn how to write plugins / extensions for cert-manager.
+Needs links to state-of-the-art examples of plugins and extensions.
+
+### New Contributor
+
+Wants to report a bug in cert-manager.
+Wants to fix a bug in cert-manager.
+Wants to suggest a feature for cert-manager.
+Wants to implement a feature for cert-manager.
+Needs to learn how to navigate the cert-manager code.
+Learn cert-manager coding standards and house style.
+Needs to know how to run the tests for cert-manager.
+
## Scope
The scope of this project is as follows:
diff --git a/content/docs/contributing/google-season-of-docs/README.md b/content/docs/contributing/google-season-of-docs/README.md
index bde3b77e43..cb43f69aa8 100644
--- a/content/docs/contributing/google-season-of-docs/README.md
+++ b/content/docs/contributing/google-season-of-docs/README.md
@@ -1,8 +1,8 @@
---
title: Google Season of Docs
-description: Google season of docs 2022 proposal
+description: cert-manager and Google Season of Docs
---
-The cert-manager organization has registered for the Google Season of Docs!
+The cert-manager project participated in Google Season of Docs 2022
-Check out our [2022](./2022/README.md) proposals!
+If you're interested in what happened, you can check out our [2022 proposals!](./2022/README.md).
diff --git a/content/docs/contributing/importing.md b/content/docs/contributing/importing.md
index cb4e488936..2c39a247e3 100644
--- a/content/docs/contributing/importing.md
+++ b/content/docs/contributing/importing.md
@@ -30,14 +30,13 @@ aware of this need! We'll always try to avoid breakage where we can.
## Module Import Paths
-The original cert-manager repository was created on GitHub as `https://github.com/jetstack/cert-manager`, and was later
-migrated to `https://github.com/cert-manager/cert-manager`.
+For all supported versions of cert-manager, the module import path is `github.com/cert-manager/cert-manager`.
-This means the Go module import path you need depends on the version of cert-manager you're trying to use.
+Historically, the cert-manager repository was created on GitHub as `https://github.com/jetstack/cert-manager`, and was later
+migrated to `https://github.com/cert-manager/cert-manager`.
-For cert-manager 1.8 and later, use the new path:
-`github.com/cert-manager/cert-manager`
+This means that the Go module import path you need may be different if you're trying to use an older version of cert-manager.
+For cert-manager 1.8 and later, use the new path listed above.
-For cert-manager 1.7 and earlier, including all point releases, use the old path:
-`github.com/jetstack/cert-manager`
\ No newline at end of file
+For cert-manager versions older than 1.8 use the old path: `github.com/jetstack/cert-manager`
diff --git a/content/docs/projects/README.md b/content/docs/contributing/projects.md
similarity index 68%
rename from content/docs/projects/README.md
rename to content/docs/contributing/projects.md
index 9479756cb5..cd396b08e7 100644
--- a/content/docs/projects/README.md
+++ b/content/docs/contributing/projects.md
@@ -8,24 +8,23 @@ that extend the project's functionality, and complement the core cert-manager fe
These tools help with security, compliance and control.
-- [istio-csr](./istio-csr.md): Secure Istio service mesh with istio-csr which is
+- [istio-csr](https://github.com/cert-manager/istio-csr) ([docs](../usage/istio-csr.md)): Secure Istio service mesh with istio-csr which is
an agent that allows for [Istio](https://istio.io) workload and control plane
components to be secured using cert-manager.
-- [approver-policy](./approver-policy.md):
+- [approver-policy](https://github.com/cert-manager/approver-policy) ([docs](../policy/approval/approver-policy/README.md)):
a cert-manager **approver** that will automatically approve or deny
certificate requests based on defined policy.
-- [csi-driver](./csi-driver.md):
+- [csi-driver](https://github.com/cert-manager/csi-driver) ([docs](../usage/csi-driver.md)):
a Container Storage Interface (CSI) driver plugin for Kubernetes to work along
cert-manager. The goal for this plugin is to seamlessly request and mount
certificate key pairs to pods. This is useful for facilitating mTLS, or
otherwise securing connections of pods with guaranteed present certificates
whilst having all of the features that cert-manager provides.
-- [csi-driver-spiffe](./csi-driver-spiffe.md):
+- [csi-driver-spiffe](https://github.com/cert-manager/csi-driver-spiffe) ([docs](../usage/csi-driver-spiffe.md)):
another CSI driver plugin to work along cert-manager. This CSI driver
transparently delivers [SPIFFE](https://spiffe.io/)
[SVIDs](https://spiffe.io/docs/latest/spiffe-about/spiffe-concepts/#spiffe-verifiable-identity-document-svid)
in the form of X.509 certificate key pairs to mounting Kubernetes Pods. The
end result is all and any Pod running in Kubernetes can securely request their
SPIFFE identity document from a Trust Domain with minimal configuration.
-- [trust-manager](./trust-manager/README.md): the easiest way to manage TLS trust bundles in Kubernetes and OpenShift clusters.
-- [trust-manager API reference](./trust-manager/api-reference.md): full documentation of the trust-manager CRD(s)
+- [trust-manager](https://github.com/cert-manager/trust-manager) ([docs](../trust/trust-manager/README.md)): the easiest way to manage TLS trust bundles in Kubernetes and OpenShift clusters.
diff --git a/content/docs/contributing/release-process.md b/content/docs/contributing/release-process.md
index b772c59567..f0a5b0bd68 100644
--- a/content/docs/contributing/release-process.md
+++ b/content/docs/contributing/release-process.md
@@ -6,7 +6,7 @@ description: 'cert-manager contributing: Release process'
This document aims to outline the process that should be followed for
cutting a new release of cert-manager. If you would like to know more about
current releases and the timeline for future releases, take a look at the
-[Supported Releases](../installation/supported-releases.md) page.
+[Supported Releases](../releases/README.md) page.
## Prerequisites
@@ -128,8 +128,10 @@ some of these goals are missed, in order to keep up release velocity.
page if a step is missing or if it is outdated.
-1. Make sure to note which type of release you are doing. That will be helpful
- in the next steps.
+1. Remind yourself of our release terminology by looking at the following table.
+ This will allow you to know which steps to skip by looking the header of the
+ step, e.g., **(final release only)** means that this step must only be
+ performed when doing a final release.
| Type of release | Example of git tag |
|------------------------------------|--------------------|
@@ -141,15 +143,166 @@ page if a step is missing or if it is outdated.
| (optional) patch pre-release[^1] | `v1.3.1-beta.0` |
| patch release (or "point release") | `v1.3.1` |
-[^1]: One or more "patch pre-releases" may be created to allow voluntary community testing of a bug fix or security fix before the fix is made generally available. The suffix `-beta` must be used for patch pre-releases.
+ [^1]: One or more "patch pre-releases" may be created to allow voluntary community testing of a bug fix or security fix before the fix is made generally available. The suffix `-beta` must be used for patch pre-releases.
-2. **(final release only)** Make sure that a PR with the new upgrade
+2. Set the 4 environment variables by copying the following snippet in your
+ shell table:
+
+ ```bash
+ export RELEASE_VERSION="v1.3.0-alpha.0"
+ export START_TAG="v1.2.0"
+ export END_REV="release-1.3"
+ export BRANCH="release-1.3"
+ ```
+
+ > **Note:** To help you fill in the correct values, use the following
+ > examples:
+ >
+ > | Variable | Example 1 | Example 2 | Example 2 | Example 3 | Example 4 |
+ > | ----------------- | ---------------- | ---------------- | ---------------- | ------------- | ------------- |
+ > | | initial alpha | subsequent alpha | beta release | final release | patch release |
+ > | `RELEASE_VERSION` | `v1.3.0-alpha.0` | `v1.3.0-alpha.1` | `v1.3.0-beta.0` | `v1.3.0` | `v1.3.1` |
+ > | `START_TAG` | `v1.2.0` | `v1.3.0-alpha.0` | `v1.3.0-alpha.1` | `v1.2.0`\* | `v1.3.0` |
+ > | `END_REV` | `master` | `master` | `release-1.3` | `release-1.3` | `release-1.3` |
+ > | `BRANCH` | `master` | `master` | `release-1.3` | `release-1.3` | `release-1.3` |
+ >
+ > \*Do not use a patch here (e.g., no `v1.2.3`). It must be `v1.2.0`:
+ > you must use the latest tag that belongs to the release branch you are
+ > releasing on; in the above example, the release branch is
+ > `release-1.3`, and the latest tag on that branch is `v1.2.0`.
+
+ > **Note:** The 4 variables are described in [the README of the
+ `release-notes`
+ tool](https://github.com/kubernetes/release/blob/master/cmd/release-notes/README.md#options).
+ For your convenience, the following table summarizes what you need to know:
+ >
+ > | Variable | Description |
+ > | ----------------- | --------------------------------------- |
+ > | `RELEASE_VERSION` | The git tag |
+ > | `START_TAG`\* | The git tag of the "previous"\* release |
+ > | `END_REV` | Name of your release branch (inclusive) |
+ > | `BRANCH` | Name of your release branch |
+
+3. **(final release only)** Prepare the Website "Upgrade Notes" PR.
+
+ Make sure that a PR with the new upgrade
document is ready to be merged on
[cert-manager/website](https://github.com/cert-manager/website). See for
example, see
- [upgrading-1.0-1.1](https://cert-manager.io/docs/installation/upgrading/upgrading-1.0-1.1/).
+ [upgrading-1.0-1.1](https://cert-manager.io/docs/releases/upgrading/upgrading-1.0-1.1.md).
+
+4. **(final + patch releases)** Prepare the Website "Release Notes" PR.
+
+ **⚠️ This step can be done ahead of time.**
+
+ The steps below need to happen using `master` (**final release**) or
+ `release-1.x` (**patch release**). The PR will be merged after the release.
+
+ Go to the section "Generate `github-release-description.md`" using the
+ instructions further below (Ctrl+F and look for
+ `github-release-description.md`).
+ 2. Remove the "Dependencies" section.
+ 3. For each bullet point in the Markdown file, read the changelog entry and
+ check that it follows the [release-note guidelines](../contributing/contributing-flow.md#release-note-guidelines).
+ If you find a changelog entry that doesn't follow the guidelines, then:
+ - Go to that PR and edit the PR description to change the contents of the
+ `release-note` block.
+ - Go back to the release notes page, and copy the same change into
+ `release-notes.md` (or re-generate the file).
+
+ and copy the same change into `release-notes.md` (or re-generate the
+ file).
+ 4. Add the section "Major themes" and "Community" by taking example on the
+ previous release note pages.
+ 5. Replace the GitHub issue numbers and GitHub handles (e.g., `#1234` or
+ `@maelvls`) with actual links using the following command:
+
+ ```bash
+ sed -E \
+ -e 's$#([0-9]+)$[#\1](https://github.com/cert-manager/cert-manager/pull/\1)$g' \
+ -e 's$@(\w+)$[@\1](https://github.com/\1)$g' \
+ github-release-description.md >release-notes.md
+ ```
+
+ 6. Move `release-notes.md` to the website repo:
+
+ ```bash
+ # From the cert-manager repo.
+ mv release-notes.md ../website/content/docs/release-notes-1.X.md
+ ```
+
+ 7. Add an entry to `content/docs/manifest.json`:
+
+ ```diff
+ {
+ "title": "Release Notes",
+ "routes": [
+ + {
+ + "title": "v1.12",
+ + "path": "/docs/release-notes/release-notes-1.12.md"
+ + },
+ ```
+
+ 8. Add a line to the file `content/docs/release-notes/README.md`.
+
+5. **(final + patch release)** Prepare the Website "Bump Versions" PR.
+
+ **⚠️ This step can be done ahead of time.**
+
+ In that PR:
+
+ 1. (**final release**) Update the section "Supported releases" in the
+ [supported-releases](../releases/README.md) page.
+ 2. (**final release**) Update the section "How we determine supported
+ Kubernetes versions" on the
+ [supported-releases](../releases/README.md) page.
+ 3. (**final release**) Bump the version that appears in
+ `scripts/gendocs/generate-new-import-path-docs`. For example:
+
+ ```diff
+ -LATEST_VERSION="v1.11-docs"
+ +LATEST_VERSION="v1.12-docs"
+
+ -genversionwithcli "release-1.11" "$LATEST_VERSION"
+ +genversionwithcli "release-1.12" "$LATEST_VERSION"
+ ```
+
+ 4. (**final + patch release of the latest minor version**) Bump all versions
+ present in installation instructions. To update these versions:
-3. Check that the `origin` remote is correct. To do that, run the following
+ ```bash
+ sed -i.bak 's/1.12.[0-9]/1.12.4/g' content/docs/installation/{README.md,code-signing.md,helm.md,kubectl.md,operator-lifecycle-manager.md}
+ rm -f **/*.bak
+ ```
+
+ To check that all mentions of that version are gone, run:
+
+ ```bash
+ grep -R -n -F 'v1.11.[0-9]' content/docs/installation
+ ```
+
+ 5. (**final release only**) Freeze the `docs/` folder by creating a copy ,
+ removing the pages from that copy that don't make sense to be versioned,
+ and updating the `manifest.json` file:
+
+ ```bash
+ cp -r content/docs content/v1.12-docs
+ rm -rf content/v1.12-docs/{installation/supported-releases,installation/upgrading,release-notes}
+ sed -i.bak 's|docs|v1.12-docs|g' content/v1.12-docs/manifest.json
+ cat content/v1.12-docs/manifest.json \
+ | jq 'del(.. | select(.path? | select(.) | test(".*(installation/supported-releases.md|installation/upgrading|release-notes).*")))' \
+ | jq 'del(.. | select(.routes? == []))' >/tmp/manifest \
+ && mv /tmp/manifest content/v1.12-docs/manifest.json
+ ```
+
+ 6. (**final + patch releases**) Update the [API docs](https://cert-manager.io/docs/reference/api-docs/) and [CLI docs](https://cert-manager.io/docs/cli//):
+
+ ```bash
+ # From the website repository, on the master branch.
+ ./scripts/gendocs/generate
+ ```
+
+6. Check that the `origin` remote is correct. To do that, run the following
command and make sure it returns the upstream
`https://github.com/cert-manager/cert-manager.git`:
@@ -161,11 +314,11 @@ page if a step is missing or if it is outdated.
It should show:
```text
- origin https://github.com/jetstack/cert-manager (fetch)
- origin https://github.com/jetstack/cert-manager (push)
+ origin https://github.com/cert-manager/cert-manager (fetch)
+ origin https://github.com/cert-manager/cert-manager (push)
```
-4. Place yourself on the correct branch:
+7. Place yourself on the correct branch:
- **(initial alpha and subsequent alpha)**: place yourself on the `master`
branch:
@@ -192,7 +345,7 @@ page if a step is missing or if it is outdated.
permission, you will have to open a PR to merge master into the release
branch), and wait for the PR checks to become green.
- - **(subsequent beta, patch release and final release)**: place yourself on
+ - **(subsequent beta, patch release and final release)**: place yourself on
the release branch:
```bash
@@ -218,146 +371,175 @@ page if a step is missing or if it is outdated.
We don't fast-forward for patch releases and final releases; instead, we
prepare these releases using the `/cherry-pick release-1.0` command.
- > Note about branch protection: The release branches are protected by [GitHub branch protection](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule), which is [configured automatically by Prow](https://github.com/jetstack/testing/blob/500b990ad1278982b10d57bf8fbca383040d2fe8/config/config.yaml#L27-L36).
+ > Note about branch protection: The release branches are protected by [GitHub branch protection](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule), which is [configured automatically by Prow](https://github.com/cert-manager/testing/blob/500b990ad1278982b10d57bf8fbca383040d2fe8/config/config.yaml#L27-L36).
> This prevents anyone *accidentally* pushing changes directly to these branches, even repository administrators.
> If you need, for some reason, to fast forward the release branch,
> you should delete the branch protection for that release branch, using the [GitHub branch protection web UI](https://github.com/cert-manager/cert-manager/settings/branches).
> This is only a temporary change to allow you to update the branch.
> [Prow will re-apply the branch protection within 24 hours](https://docs.prow.k8s.io/docs/components/optional/branchprotector/#updating).
-5. Create the tag for the new release locally and push it upstream:
+8. Create the required tags for the new release locally and push it upstream (starting the cert-manager build):
```bash
- RELEASE_VERSION=v1.8.0-beta.0
+ echo $RELEASE_VERSION
git tag -m"$RELEASE_VERSION" $RELEASE_VERSION
# be sure to push the named tag explicitly; you don't want to push any other local tags!
git push origin $RELEASE_VERSION
```
- **GitHub permissions**: `git push` will only work if you have the
- `admin` GitHub permission on the cert-manager repo to create or push to
- the branch, see [prerequisites](#prerequisites). If you do not have this
- permission, you will have to open a PR to merge master into the release
- branch), and wait for the PR checks to become green.
+ > **Note**: `git push` will only work if you have the `admin` GitHub
+ > permission on the cert-manager repo to create or push to the branch, see
+ > [prerequisites](#prerequisites). If you do not have this permission, you
+ > will have to open a PR to merge master into the release branch), and
+ > wait for the PR checks to become green.
+
+ > **Note 2:** For recent versions of cert-manager, the tag being pushed will trigger a Google Cloud Build job to start,
+ > kicking off a build using the steps in `gcb/build_cert_manager.yaml`. Users with access to
+ > the cert-manager-release project on GCP should be able to view logs in [GCB build history](https://console.cloud.google.com/cloud-build/builds?project=cert-manager-release).
-6. Generate and edit the release notes:
+9. **(1.12 and above)** In this step, we make sure the Go module
+ `github.com/cert-manager/cert-manager/cmd/ctl` can be imported by
+ third-parties.
- 1. Use the following two tables to understand how to fill in the four
- environment variables needed for the next step. These four environment
- variables are documented on the
- [README](https://github.com/kubernetes/release/blob/master/cmd/release-notes/README.md#options)
- for the Kubernetes `release-notes` tool.
+ First, create a temporary branch.
+
+ ```bash
+ # Must be run from the cert-manager repo folder.
+ git checkout -b "update-cmd/ctl/$RELEASE_VERSION"
+ ```
- | Variable | Description |
- | ----------------- | --------------------------------------- |
- | `RELEASE_VERSION` | The git tag |
- | `START_TAG`\* | The git tag of the "previous"\* release |
- | `END_REV` | Name of your release branch (inclusive) |
- | `BRANCH` | Name of your release branch |
+ Second, update the `cmd/ctl`'s `go.mod` with the tag we just created:
- Examples for each release type (e.g., initial alpha release):
+ ```bash
+ # Must be run from the cert-manager repo folder.
+ cd cmd/ctl
+ go get github.com/cert-manager/cert-manager@$RELEASE_VERSION
+ cd ../..
+
+ find . -name go.mod -not -path ./_bin/\* -exec dirname '{}' \; | xargs -L1 -I@ sh -c 'cd @; go mod tidy'
+ git add **/go.mod **/go.sum
+ git commit -m"Update cmd/ctl's go.mod to $RELEASE_VERSION"
+ ```
- | Variable | Example 1 | Example 2 | Example 2 | Example 3 | Example 4 |
- | ----------------- | ---------------- | ---------------- | ---------------- | ------------- | ------------- |
- | | | | | | |
- | | initial alpha | subsequent alpha | beta release | final release | patch release |
- | `RELEASE_VERSION` | `v1.3.0-alpha.0` | `v1.3.0-alpha.1` | `v1.3.0-beta.0` | `v1.3.0` | `v1.3.1` |
- | `START_TAG`\* | `v1.2.0` | `v1.3.0-alpha.0` | `v1.3.0-alpha.1` | `v1.2.0`\*\* | `v1.3.0` |
- | `END_REV` | `master` | `master` | `release-1.3` | `release-1.3` | `release-1.3` |
- | `BRANCH` | `master` | `master` | `release-1.3` | `release-1.3` | `release-1.3` |
+ Third, create a tag for the `cmd/ctl` module:
- > \*The git tag of the "previous" release (`START_TAG`) depends on which
- > type of release you count on doing. Look at the above examples to
- > understand a bit more what those are.
+ ```bash
+ # Must be run from the cert-manager repo folder.
+ git tag -m"cmd/ctl/$RELEASE_VERSION" "cmd/ctl/$RELEASE_VERSION"
+ git push origin "cmd/ctl/$RELEASE_VERSION"
+ ```
- > \*\*Do not use a patch here (e.g., no `v1.2.3`). It must be `v1.2.0`:
- > you must use the latest tag that belongs to the release branch you are
- > releasing on; in the above example, the release branch is
- > `release-1.3`, and the latest tag on that branch is `v1.2.0`.
+ > **Note:** the reason we need to do this is explained on Stack Overflow:
+ [how-are-versions-of-a-sub-module-managed][]
- After finding out the value for each of the 4 environment variables, set
- the variables in your shell (for example, following the example 1):
+ [how-are-versions-of-a-sub-module-managed]: https://stackoverflow.com/questions/60601011/how-are-versions-of-a-sub-module-managed/60601402#60601402
- ```bash
- export RELEASE_VERSION="v1.3.0-alpha.0"
- export START_TAG="v1.2.0"
- export END_REV="release-1.3"
- export BRANCH="release-1.3"
- ```
+ Then, push the branch to your fork of cert-manager. For example:
- 2. Generate `release-notes.md` at the root of your cert-manager repo folder
- with the following command:
+ ```bash
+ # Must be run from the cert-manager repo folder.
+ gh repo fork --remote-name fork
+ git push -u fork "update-cmd/ctl/$RELEASE_VERSION"
+ ```
- ```bash
- # Must be run from the cert-manager folder.
- export GITHUB_TOKEN=*your-token*
- git fetch origin $BRANCH
- export START_SHA="$(git rev-list --reverse --ancestry-path $(git merge-base $START_TAG $BRANCH)..$BRANCH | head -1)"
- release-notes --debug --repo-path cert-manager \
- --org cert-manager --repo cert-manager \
- --required-author "jetstack-bot" \
- --output release-notes.md
- ```
+ Then, open a PR to merge that change and go back to the release branch with
+ the following commands:
-
- The GitHub token **does not need any scope**. The token is required
- only to avoid rate-limits imposed on anonymous API users.
-
+ ```bash
+ gh pr create \
+ --title "[Release $RELEASE_VERSION] Update cmd/cmctl's go.mod to $RELEASE_VERSION" \
+ --body-file - --base $BRANCH < **Note:** This step is about creating the description that will be
+ > copy-pasted into the GitHub release page. The creation of the "Release
+ > Note" page on the website is done in a previous step.
- 1. In this example we stage a release using the `v1.8.0-beta.0` git ref:
+ 1. Check that all the 4 environment variables are ready:
```bash
- # Must be run from the "cert-manager/release" repo folder.
- cmrel makestage --ref=$RELEASE_VERSION
+ echo $RELEASE_VERSION
+ echo $START_TAG
+ echo $END_REV
+ echo $BRANCH
```
- This step takes ~5 minutes. It will build all container images and create
- all the manifest files, sign Helm charts and upload everything to a storage
- bucket on Google Cloud. These artifacts will then be published and released
- in the next steps.
+ 2. Generate `github-release-description.md` with the following command:
+
+ ```bash
+ # Must be run from the cert-manager folder.
+ export GITHUB_TOKEN=*your-token*
+ git fetch origin $BRANCH
+ export START_SHA="$(git rev-list --reverse --ancestry-path $(git merge-base $START_TAG $BRANCH)..$BRANCH | head -1)"
+ release-notes --debug --repo-path cert-manager \
+ --org cert-manager --repo cert-manager \
+ --required-author "jetstack-bot" \
+ --markdown-links=false \
+ --output github-release-description.md
+ ```
+
+
+ The GitHub token **does not need any scope**. The token is required
+ only to avoid rate-limits imposed on anonymous API users.
+
+
+ 3. Add a one-sentence summary at the top.
+
+ 4. **(final release only)** Write the "Community" section, following the example of past releases such as [v1.12.0](https://github.com/cert-manager/cert-manager/releases/tag/v1.12.0). If there are any users who didn't make code contributions but helped in other ways (testing, PR discussion, etc), be sure to thank them here!
- 2. While the build is running, send a first Slack message to
- `#cert-manager-dev`:
+11. Check that the build that was automatically triggered when you pushed the
+ tag is complete and send Slack messages about the release:
+
+ 1. Send a first Slack message to `#cert-manager-dev`:
Releasing 1.2.0-alpha.2 🧵
-
- 🔰 Please have a quick look at the build log as it might contain some unredacted
- data that we forgot to redact. We try to make sure the sensitive data is
- properly redacted but sometimes we forget to update this.
-
-
- 3. Send a second Slack message in reply to this first message with the
- Cloud Build job link that `cmrel` displayed in "View logs at". For
- example, the message would look like:
+ 2. Check that the build completed in the
+ [GCB Build History](https://console.cloud.google.com/cloud-build/builds?project=cert-manager-release).
+
+
+ 🔰 Please have a quick look at the build log as it might contain some unredacted
+ data that we forgot to hide. We try to make sure the sensitive data is
+ properly redacted but sometimes we forget to update this.
+
+
+ > **NOTE (1.10 and earlier):** If you're releasing an older version of
+ > cert-manager then the automatic build will failed because the GCB
+ > config for that build wasn't backported. In this case, you'll need to
+ > trigger the build manually using `cmrel`, which takes about 5 minutes:
+ >
+ > ```bash
+ > # Must be run from the "cert-manager/release" repo folder.
+ > cmrel makestage --ref=$RELEASE_VERSION
+ > ```
+
+ 3. Copy the build logs URL and send a second Slack message in reply to this
+ first message with the Cloud Build job link. For example, the message
+ might look like:
-8. Run `cmrel publish`:
+12. Run `cmrel publish`:
1. Do a `cmrel publish` dry-run to ensure that all the staged resources are
valid. Run the following command:
@@ -384,17 +566,17 @@ page if a step is missing or if it is outdated.
cmrel publish --nomock --release-name "$RELEASE_VERSION"
```
-
4. While the build is running, send a fourth Slack message in reply to the first message:
@@ -402,7 +584,7 @@ page if a step is missing or if it is outdated.
Follow the cmrel publish build: https://console.cloud.google.com/cloud-build/builds/b6fef12b-2e81-4486-9f1f-d00592351789?project=1021342095237
-9. Publish the GitHub release:
+13. Publish the GitHub release:
1. Visit the draft GitHub release and paste in the release notes that you
generated earlier. You will need to manually edit the content to match
@@ -417,11 +599,11 @@ page if a step is missing or if it is outdated.
4. Click "Publish" to make the GitHub release live.
-10. Merge the pull request containing the Helm chart:
+14. Merge the pull request containing the Helm chart:
- The Helm charts for cert-manager are served using Cloudflare pages
- and the Helm chart files and metadata are stored in the [Jetstack charts repository](https://github.com/jetstack/jetstack-charts).
- The `cmrel publish --nomock` step (above) will have created a PR in this repository which you now have to review and merge, as follows:
+ The Helm charts for cert-manager are served using Cloudflare pages
+ and the Helm chart files and metadata are stored in the [Jetstack charts repository](https://github.com/jetstack/jetstack-charts).
+ The `cmrel publish --nomock` step (above) will have created a PR in this repository which you now have to review and merge, as follows:
1. [Visit the pull request](https://github.com/jetstack/jetstack-charts/pulls)
2. Review the changes
@@ -429,10 +611,25 @@ page if a step is missing or if it is outdated.
4. Merge the PR
5. Check that the [cert-manager Helm chart is visible on ArtifactHUB](https://artifacthub.io/packages/helm/cert-manager/cert-manager).
-11. **(final release only)** Add the new final release to the
- [supported-releases](../installation/supported-releases.md) page.
+15. **(final + patch releases)** Merge the 4 Website PRs:
+
+ 1. Merge the PRs "Release Notes", "Upgrade Notes", and "Freeze And Bump
+ Versions" that you have created previously.
+ 2. Create the PR "Merge release-next into master" by [clicking
+ here][ff-release-next].
+
+ If you see the label `dco-signoff: no`, add a comment on the PR with:
+
+ ```text
+ /override dco
+ ```
+
+ This command is necessary because some the merge commits have been
+ written by the bot and do not have a DCO signoff.
+
+ [ff-release-next]: https://github.com/cert-manager/website/compare/master...release-next?quick_pull=1&title=%5BPost-Release%5D+Merge+release-next+into+master&body=%3C%21--%0A%0AThe+command+%22%2Foverride+dco%22+is+necessary+because+some+the+merge+commits%0Ahave+been+written+by+the+bot+and+do+not+have+a+DCO+signoff.%0A%0A--%3E%0A%0A%2Foverride+dco
-12. Open a PR for a [Homebrew](https://brew.sh) formula update for `cmctl`.
+16. Open a PR for a [Homebrew](https://github.com/Homebrew/homebrew-core/pulls) formula update for `cmctl`.
Assuming you have `brew` installed, you can use the `brew bump-formula-pr`
command to do this. You'll need the new tag name and the commit hash of that
@@ -449,7 +646,7 @@ page if a step is missing or if it is outdated.
against https://github.com/homebrew/homebrew-core has been opened, continue
with further release steps.
-13. Post a Slack message as an answer to the first message. Toggle the check
+17. Post a Slack message as an answer to the first message. Toggle the check
box "Also send to `#cert-manager-dev`" so that the message is well
visible. Also cross-post the message on `#cert-manager`.
@@ -457,7 +654,7 @@ page if a step is missing or if it is outdated.
https://github.com/cert-manager/cert-manager/releases/tag/v1.0.0 🎉
-14. **(final release only)** Show the release to the world:
+18. **(final release only)** Show the release to the world:
1. Send an email to
[`cert-manager-dev@googlegroups.com`](https://groups.google.com/g/cert-manager-dev)
@@ -470,25 +667,17 @@ page if a step is missing or if it is outdated.
3. Send a toot from the cert-manager Mastodon account! Login details are in Jetstack's 1password (for now).
([Example toot](https://infosec.exchange/@CertManager/109666434738850493))
-15. Proceed to the post-release steps:
+19. Proceed to the post-release "testing and release" steps:
1. **(initial beta only)** Create a PR on
[cert-manager/release](https://github.com/cert-manager/release) in order to
- add the new release to our list of periodic ProwJobs. Use [this PR](https://github.com/jetstack/testing/pull/774/) as an example.
+ add the new release to our list of periodic ProwJobs. Use [this PR](https://github.com/cert-manager/testing/pull/774/) as an example.
2. **(initial beta only)** Run `cmrel generate-prow --branch='*' -o file` with the new version from the previous step and
- open a PR to [cert-manager/testing](https://github.com/jetstack/testing) adding the generated prow configs.
- Use [this PR](https://github.com/jetstack/testing/pull/766) as an example.
-
- 3. If needed, open a PR to
- [`cert-manager/website`](https://github.com/cert-manager/website) in
- order to:
-
- - Update the section "How we determine supported Kubernetes versions" on
- the [supported-releases](../installation/supported-releases.md) page.
- - Add any new release notes, if needed.
+ open a PR to [cert-manager/testing](https://github.com/cert-manager/testing) adding the generated prow configs.
+ Use [this PR](https://github.com/cert-manager/testing/pull/766) as an example.
- 4. **(final release only)** Create a PR on
+ 3. **(final release only)** Create a PR on
[cert-manager/release](https://github.com/cert-manager/release),
removing the now unsupported release version (2 versions back) in this file:
@@ -498,43 +687,22 @@ page if a step is missing or if it is outdated.
This will remove the periodic ProwJobs for this version as they're no longer needed.
- 5. **(final release only)** Run `cmrel generate-prow --branch='*' -o file` with the new version from the previous step and
- open a PR to [jetstack/testing](https://github.com/jetstack/testing) adding the generated prow configs.
+ 4. **(final release only)** Run `cmrel generate-prow --branch='*' -o file` with the new version from the previous step and
+ open a PR to [jetstack/testing](https://github.com/cert-manager/testing) adding the generated prow configs.
- 6. **(final release only)** Open a PR to [`jetstack/testing`](https://github.com/jetstack/testing)
- and update the [milestone_applier](https://github.com/jetstack/testing/blob/3110b68e082c3625bf0d26265be2d29e41da14b2/config/plugins.yaml#L69)
+ 5. **(final release only)** Open a PR to [`jetstack/testing`](https://github.com/cert-manager/testing)
+ and update the [milestone_applier](https://github.com/cert-manager/testing/blob/3110b68e082c3625bf0d26265be2d29e41da14b2/config/plugins.yaml#L69)
config so that newly raised PRs on master are applied to a new milestone
for the next release. E.g. if master currently points at the `v1.10` milestone, change it to point at `v1.11`.
If the [milestone](https://github.com/cert-manager/cert-manager/milestones) for the next release doesn't exist,
create it first. If you consider the milestone for the version you just released to be complete, close it.
- 7. **(final release only)** Open a PR to
- [`cert-manager/website`](https://github.com/cert-manager/website) in
- order to:
-
- - Update the section "Supported releases" in the
- [supported-releases](../installation/supported-releases.md) page.
- - Update the section "How we determine supported Kubernetes versions" on
- the [supported-releases](../installation/supported-releases.md) page.
- In the table, set "n/a" for the line where "next periodic" is since
- these tests will be disabled until we do our first alpha.
- - Update the [API docs](../reference/api-docs.md) and [CLI docs](../cli/README.md) by running `scripts/gendocs/generate`
- and commit any changes to a branch and create a PR to merge those into
- `master` or `release-next` depending on whether this is a minor or
- patch release.
-
- 8. Ensure that any installation commands in
- [`cert-manager/website`](https://github.com/cert-manager/website) install
- the latest version. This should be done after every release, including
- patch releases as we want to encourage users to always install the latest
- patch. In addition, ensure that release notes for the latest version are added.
-
- 9. Open a PR against the Krew index such as [this one](https://github.com/kubernetes-sigs/krew-index/pull/1724),
+ 6. Open a PR against the Krew index such as [this one](https://github.com/kubernetes-sigs/krew-index/pull/1724),
bumping the versions of our kubectl plugins. This is likely only worthwhile if
cmctl / kubectl plugin functionality has changed significantly or after the first release of a new major version.
- 10. Create a new OLM package and publish to OperatorHub
+ 7. Create a new OLM package and publish to OperatorHub
cert-manager can be [installed](https://cert-manager.io/docs/installation/operator-lifecycle-manager/) using Operator Lifecycle Manager (OLM)
so we need to create OLM packages for each cert-manager version and publish them to both
diff --git a/content/docs/devops-tips/backup.md b/content/docs/devops-tips/backup.md
new file mode 100644
index 0000000000..6fa08ef954
--- /dev/null
+++ b/content/docs/devops-tips/backup.md
@@ -0,0 +1,200 @@
+---
+title: Backup and Restore Resources
+description: 'cert-manager tutorials: Backing up your cert-manager installation'
+---
+
+If you need to uninstall cert-manager, or transfer your installation to a new
+cluster, you can backup all of cert-manager's configuration in order to later
+re-install.
+
+## Backing up cert-manager resource configuration
+
+The following commands will back up the configuration of `cert-manager`
+resources. Doing that might be useful before upgrading `cert-manager`. As
+this backup does not include the `Secrets` containing the X.509
+certificates, restoring to a cluster that does not already have those
+`Secret` objects will result in the certificates being reissued.
+
+### Backup
+
+To backup all of your cert-manager configuration resources, run:
+
+```bash
+kubectl get --all-namespaces -oyaml issuer,clusterissuer,cert > backup.yaml
+```
+
+If you are transferring data to a new cluster, you may also need to copy across
+additional `Secret` resources that are referenced by your configured Issuers, such
+as:
+
+#### CA Issuers
+
+- The root CA `Secret` referenced by `issuer.spec.ca.secretName`
+
+#### Vault Issuers
+
+- The token authentication `Secret` referenced by
+ `issuer.spec.vault.auth.tokenSecretRef`
+- The AppRole configuration `Secret` referenced by
+ `issuer.spec.vault.auth.appRole.secretRef`
+
+#### ACME Issuers
+
+- The ACME account private key `Secret` referenced by `issuer.acme.privateKeySecretRef`
+- Any `Secret`s referenced by DNS providers configured under the
+ `issuer.acme.dns01.providers` and `issuer.acme.solvers.dns01` fields.
+
+### Restore
+
+In order to restore your configuration, you can `kubectl apply` the files
+created above after installing cert-manager, with the exception of the
+`uid` and `resourceVersion` fields that do not need to be restored:
+
+```bash
+kubectl apply -f <(awk '!/^ *(resourceVersion|uid): [^ ]+$/' backup.yaml)
+```
+
+## Full cluster backup and restore
+
+This section refers to backing up and restoring 'all' Kubernetes resources in a
+cluster — including some `cert-manager` ones — for scenarios such as disaster
+recovery, cluster migration etc.
+
+*Note*: We have tested this process on simple Kubernetes test clusters with a limited set of Kubernetes releases. To avoid data loss, please test both the backup and the restore strategy on your own cluster before depending upon it in production. If you encounter any errors, please open a GitHub issue or a PR to document variations on this process for different Kubernetes environments.
+
+### Avoiding unnecessary certificate reissuance
+
+#### Order of restore
+
+If `cert-manager` does not find a Kubernetes `Secret` with an X.509 certificate
+for a `Certificate`, reissuance will be triggered. To avoid unnecessary
+reissuance after a restore, ensure that `Secret`s are restored before
+`Certificate`s. Similarly, `Secret`s should be restored before `Ingress`es if you
+are using [`ingress-shim`](../usage/ingress.md).
+
+#### Excluding some cert-manager resources from backup
+
+`cert-manager` has a number of custom resources that are designed to represent a
+point-in-time operation. An example would be a `CertificateRequest` that
+represents a one-time request for an X.509 certificate. The status of these
+resources can depend on other ephemeral resources (such as a temporary `Secret`
+holding a private key) so `cert-manager` might not be able to correctly recreate
+the state of these resources at a later point.
+
+In most cases backup and restore tools will not restore the statuses of custom resources,
+so including such one-time resources in a backup can result in an unnecessary reissuance
+after a restore as without the status fields `cert-manager` will not be able to tell that,
+for example, an `Order` has already been fulfilled.
+To avoid unnecessary reissuance, we recommend that `Order`s and `Challenge`s are excluded
+from the backup. We also don't recommend backing up `CertificateRequest`s, see [Backing up CertificateRequests](#backing-up-certificaterequests)
+
+### Restoring Ingress Certificates
+
+A `Certificate` created for an `Ingress` via [`ingress-shim`](../usage/ingress.md) will have an [owner
+reference](https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/#owners-and-dependents)
+pointing to the `Ingress` resource. `cert-manager` uses the owner reference to
+verify that the `Certificate` 'belongs' to that `Ingress` and will not attempt to
+create/correct it for an existing `Certificate`. After a full
+cluster recreation, a restored owner reference would probably be incorrect
+(`Ingress` UUID will have changed). The incorrect owner reference could lead
+to a situation where updates to the `Ingress` (i.e a new DNS name) are not
+applied to the `Certificate`.
+
+To avoid this issue, in most cases `Certificate`s created via `ingress-shim`
+should be excluded from the backup. Given that the restore happens
+in the correct order (`Secret` with the X.509 certificate restored before
+the `Ingress`) `cert-manager` will be able to create a new `Certificate`
+for the `Ingress` and determine that the existing `Secret` is for that `Certificate`.
+
+### Velero
+
+We have tested backup and restore with `velero` `v1.12.2` and `cert-manager` version `v1.13.2`.
+
+A few potential edge cases:
+
+- Ensure that the backups include `cert-manager` CRDs.
+ For example, we have seen that if `--exclude-namespaces` flag is passed to
+ `velero backup create`, CRDs for which there are no actual resources to be
+ included in the backup might also not be included in backup unless
+ `--include-cluster-resources=true` flag is also passed to the backup command.
+
+- Velero does not restore statuses of custom resources, so you should probably
+ exclude `Order`s, `Challenge`s and `CertificateRequest`s from the backup, see
+ [Excluding some cert-manager resources from backup](#excluding-some-cert-manager-resources-from-backup).
+
+- Velero's [default restore order](https://github.com/vmware-tanzu/velero/blob/a318e1da995a390c9f10e4aef7df356594944377/pkg/cmd/server/server.go#L511-L543) (`Secrets` before `Ingress`es, Custom Resources
+ restored last), should ensure that there is no unnecessary certificate reissuance
+ due to the order of restore operation, see [Order of restore](#order-of-restore).
+
+- When restoring the deployment of `cert-manager` itself, it may be necessary to
+ restore `cert-manager`'s RBAC resources before the rest of the deployment.
+ This is because `cert-manager`'s controller needs to be able to create
+ `Certificate`'s for the `cert-manager`'s webhook before the webhook can become
+ ready. In order to do this, the controller needs the right permissions. Since
+ Velero by default restores pods before RBAC resources, the restore might get
+ stuck waiting for the webhook pod to become ready.
+
+- Velero does not restore owner references, so it may be necessary to exclude
+ `Certificate`s created for `Ingress`es from the backup even when not
+ re-creating the `Ingress` itself. See [Restoring Ingress Certificates](#restoring-ingress-certificates).
+
+
+#### Example backup and restore using Velero
+
+The following command will create a backup of all Kubernetes resources in the
+default and cert-manager namespaces, excluding `Order`s, `Challenge`s and
+`CertificateRequest`s (see above):
+```bash
+velero backup create \
+ full-backup \
+ --include-namespaces cert-manager,default \
+ --include-cluster-resources=true \
+ --exclude-resources challenges.acme.cert-manager.io,orders.acme.cert-manager.io,certificaterequests.cert-manager.io
+```
+
+To workaround Velero not restoring owner references, you can restore the backup
+in two steps: first restore the `Secret`s and `Ingress`es and the `cert-manager`
+deployment, second restore the `Certificate` resources. This will allow `cert-manager`'s
+controller to create the `Certificate` for the ingresses and set the owner reference.
+The second restore will then restore the manually created `Certificate`s and detect that
+the generated `Certificate`s for the `Ingress`es already exist and will not attempt to
+recreate them.
+
+1. Restore everything except `Certificate` resources:
+```bash
+velero restore create \
+ --from-backup full-backup \
+ --exclude-resources certificates.cert-manager.io
+```
+
+2. Wait for cert-manager to create the `Certificate`s for the `Ingress`es (if cert-manager is having RBAC/ webhook issues, you might have to manually restart the deployments). After the auto-generated `Certificate`s are created, restore the manually created `Certificate`s:
+```bash
+velero restore create \
+ --from-backup full-backup
+```
+
+## Backing up CertificateRequests
+
+ We no longer recommend including `CertificateRequest` resources in a backup
+ for most scenarios.
+ `CertificateRequest`s are designed to represent a one-time
+ request for an X.509 certificate. Once the request has been fulfilled,
+ `CertificateRequest` can usually be safely deleted[^1]. In most cases (such as when
+ a `CertificateRequest` has been created for a `Certificate`) a new
+ `CertificateRequest` will be created when needed (i.e at a time of a renewal
+ of a `Certificate`).
+ In `v1.3.0` , as part of our work towards [policy
+ implementation](https://github.com/cert-manager/cert-manager/pull/3727) we
+ introduced identity fields for `CertificateRequest` resources where, at a time
+ of creation, `cert-mananager`'s webhook updates `CertificateRequest`'s spec
+ with immutable identity fields, representing the identity of the creator of
+ the `CertificateRequest`.
+ This introduces some extra complexity for backing up
+ and restoring `CertificateRequest`s as the identity of the restorer might
+ differ from that of the original creator and in most cases a restored
+ `CertificateRequest` would likely end up with incorrect state.
+
+ [^1]: there is an edge case where certain changes to `Certificate` spec may not
+ trigger re-issuance if there is no `CertificateRequest` for that
+ `Certificate`. See [documentation on when do certificates get
+ re-issued](../faq/README.md#when-do-certs-get-re-issued).
\ No newline at end of file
diff --git a/content/docs/usage/prometheus-metrics.md b/content/docs/devops-tips/prometheus-metrics.md
similarity index 100%
rename from content/docs/usage/prometheus-metrics.md
rename to content/docs/devops-tips/prometheus-metrics.md
diff --git a/content/docs/tutorials/syncing-secrets-across-namespaces.md b/content/docs/devops-tips/syncing-secrets-across-namespaces.md
similarity index 100%
rename from content/docs/tutorials/syncing-secrets-across-namespaces.md
rename to content/docs/devops-tips/syncing-secrets-across-namespaces.md
diff --git a/content/docs/faq/README.md b/content/docs/faq/README.md
index c2b27c0ad1..6e3dd7b240 100644
--- a/content/docs/faq/README.md
+++ b/content/docs/faq/README.md
@@ -91,19 +91,37 @@ cert-manager publishes all events to the Kubernetes events mechanism, you can ge
Due to the nature of the Kubernetes event mechanism these will be purged after a while. If you're using a dedicated logging system it might be able or is already also storing Kubernetes events.
-### What happens if issuance fails? Will it be retried?
-
{/* This empty link preserves old links to #what-happens-if-a-renewal-doesn't happen?-will-it-be-tried-again-after-some-time?", which matched the old title of this section */}
+
+### What happens if issuance fails? Will it be retried?
-
-
-cert-manager will retry a failed issuance except for a few rare edge cases where manual intervention is needed.
-
-If an issuance fails because of a temporary error, it will be retried again with a short exponential backoff (currently 5 seconds to 5 minutes). A temporary error is one that does not result in a failed `CertificateRequest`.
-
-If the issuance fails with an error that resulted in a failed `CertificateRequest`, it will be retried with a longer binary exponential backoff (1 hour to 32 hours) to avoid overwhelming external services.
-
-You can always trigger immediate renewal using the [`cmctl renew` command](../reference/cmctl.md#renew)
+cert-manager will retry a failed issuance except for a few rare edge cases where
+manual intervention is needed.
+
+We aim to retry after a short delay in case of ephemeral failures such as
+network connection errors and with a longer exponentially increasing delay after
+'terminal' failures.
+
+You can observe that latest issuance has terminally failed if the `Certificate`
+has `Issuing` condition set to false and has `status.lastFailureTime` set. In
+this case the issuance will be retried after an exponentially increasing delay
+(1 to 32 hours) by creating a new `CertficateRequest`. You can trigger an
+immediate renewal using the [`cmctl renew`
+command](../reference/cmctl.md#renew). Terminal failures occur if the issuer
+sets the `CertificateRequest` to failed (for example if CA rejected the request
+due to a rate limit being reached) or invalid or if the `CertificateRequest`
+gets denied by an approver.
+
+Ephemeral failures result in the same `CertificateRequest` being re-synced after
+a short delay (up to 5 minutes). Typically they can only be observed in
+cert-manager controller logs.
+
+If it appears the issuance has got stuck and `cmctl renew` does not work, you
+can delete the latest `CertificateRequest`. This is mostly a harmless action
+(the worst that could happen is duplicate issuance if there was a potentially
+successful one in progress), but we do aim for this to not be part of user flow-
+do reach out if you think you have found a case where the flow could be
+improved.
### Is ECC (elliptic-curve cryptography) supported?
@@ -132,6 +150,44 @@ spec:
Default `duration` is [90 days](https://github.com/cert-manager/cert-manager/blob/v1.2.0/pkg/apis/certmanager/v1/const.go#L26). If `renewBefore` has not been set, `Certificate` will be renewed 2/3 through its _actual_ duration.
+
+### Why are passwords on JKS or PKCS#12 files not helpful?
+
+This question comes in many forms, including:
+
+- "Why is it OK to hard code these passwords?"
+- "Do I need to keep these passwords secure?"
+- "Are these passwords used in a secure way?"
+
+Specifically, this FAQ talks about passwords for PKCS#12 and JKS "keystores".
+
+#### Simple Answer
+
+"Passwords" on PKCS#12 or JKS files are almost always security theater, and they're only needed to support applications which are unable to parse password-less versions of these files. Even if you use a secure password for these files (which is rare), weak encryption algorithms and the management of the underlying material usually invalidate the secure password.
+
+We recommend that you treat these passwords as legacy implementation details, and use short hard-coded strings for these passwords when you're
+forced to use one. Don't spend time trying to generate or handle "secure" passwords for these files - simply choose a constant such as `changeit` or `notapassword123` and use that for every PKCS#12 or JKS bundle you generate.
+
+#### Longer Answer
+
+Lots of people see the word "password" when handling JKS or PKCS#12 bundles and they draw the obvious
+conclusion that it's a valuable security resource which needs to be handled carefully.
+
+This is generally not the case - not only are these passwords not really passwords, but they're also vanishingly unlikely to be meaningful for security of any kind.
+
+Mostly, these passwords exist only because some applications require some password to be set. That requirement is the sole reason for cert-manager and its sub-projects supporting setting a password on these types of bundles.
+
+There are several main reasons why we don't consider these passwords to be security critical:
+
+1. Most applications which use these passwords will mount the file containing the password in plain text right next to the bundle which uses it, with the same permissions and access control. This would make even the most secure password completely pointless as a security measure.
+2. Most PKCS#12 and JKS bundles which are encrypted use extremely old encryption algorithms which are fundamentally insecure
+3. The word "password" leads people to think of human-memorable passwords, which are not appropriate for this kind of encryption. This means that the passwords used are often themselves insecure in this context.
+4. When we generate PKCS#12 or JKS files, they almost always live in the same Secret as an unencrypted private key anyway!
+
+Without a very detailed threat model and putting serious time into your system's architecture in an extremely paranoid way, spending time on these "passwords" is going to be a red herring time sink with little to no return. Your efforts would almost always be better spent on securing systems through other methods.
+
+See "simple answer" above for usage guidelines for these "passwords".
+
## Miscellaneous
### Kubernetes has a builtin `CertificateSigningRequest` API. Why not use that?
diff --git a/content/docs/installation/README.md b/content/docs/installation/README.md
index df829ac3d1..2237153d06 100644
--- a/content/docs/installation/README.md
+++ b/content/docs/installation/README.md
@@ -12,7 +12,7 @@ Learn about the various ways you can install cert-manager and how to choose betw
The default static configuration can be installed as follows:
```bash
-kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml
```
📖 Read more about [installing cert-manager using kubectl apply and static manifests](./kubectl.md).
@@ -32,10 +32,9 @@ which you can do from the OpenShift web console.
## Continuous deployment
-> You know how to configure your cert-manager setup and want to automate this.
+> If you know how to configure your cert-manager setup and want to automate this,
+> you can use the cert-manager Helm chart directly with tools like Flux, ArgoCD and Anthos.
+> Or you can output YAML using `helm template` to generate customized cert-manager installation manifests,
+> which can be piped into your preferred deployment tool.
-📖 **helm**: You can use [the cert-manager Helm chart](./helm.md) directly with systems like Flux, ArgoCD and Anthos.
-
-📖 **helm template**: You can use `helm template` to generate customized cert-manager installation manifests.
-See [Output YAML using helm template](./helm.md#output-yaml) for more details.
-This templated cert-manager manifest can be piped into your preferred deployment tool.
+📖 **Continuous Deployment**: Learn [how to automate the installation of cert-manager using tools like Flux and Argo CD](./continuous-deployment-and-gitops.md).
diff --git a/content/docs/installation/best-practice.md b/content/docs/installation/best-practice.md
index f2ca51b603..6ab631b73b 100644
--- a/content/docs/installation/best-practice.md
+++ b/content/docs/installation/best-practice.md
@@ -1,22 +1,476 @@
---
title: Best Practice
-description: Learn how to deploy cert-manager to comply with popular security standards such as those produced by the CIS, NSA, and BSI.
+description: |
+ Learn about best practices for deploying cert-manager in production,
+ and how to configure cert-manager to comply with popular security standards
+ such as those produced by the CIS, NSA, and BSI.
---
-Learn how to deploy cert-manager to comply with popular security standards such as
+In this section you will learn how to configure cert-manager to comply with popular security standards such as
the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/),
the [NSA Kubernetes Hardening Guide](https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF), or
the [BSI Kubernetes Security Recommendations](https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Grundschutz/International/bsi_it_gs_comp_2022.pdf?__blob=publicationFile&v=2#page=475).
+And you will learn about best practices for deploying cert-manager in production;
+such as those enforced by tools like [Datree and its built in rules](https://hub.datree.io/built-in-rules),
+and those documented by the likes of [Learnk8s in their "Kubernetes production best practices" checklist](https://learnk8s.io/production-best-practices/).
+
## Overview
-The default cert-manager resources in the Helm chart or YAML manifests (Deployment, Pod, ServiceAccount etc) are designed for backwards compatibility rather than for best practice or maximum security.
+The default cert-manager resources in the Helm chart or YAML manifests (Deployment, Pod, ServiceAccount etc)
+are designed for backwards compatibility rather than for best practice or maximum security.
You may find that the default resources do not comply with the security policy on your Kubernetes cluster
and in that case you can modify the installation configuration using Helm chart values to override the defaults.
+## Network Requirements and Network Policy
+
+The network requirements of each cert-manager Pod are summarized below.
+Some network requirements depend on specific Issuer / ClusterIssuer configurations
+and / or specific configuration options.
+
+When you have understood the network requirements of **your** cert-manager installation,
+you should consider implementing a "least privilege" network policy,
+using a [Kubernetes Network (CNI) Plugin](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) such as [Calico](https://www.tigera.io/project-calico/).
+
+The network policy should prevent untrusted clients from connecting to the cert-manager Pods
+and it should prevent cert-manager from connecting to untrusted servers.
+
+An example of this recommendation is found in the Calico Documentation:
+> We recommend creating an implicit default deny policy for your Kubernetes pods, regardless of whether you use Calico or Kubernetes network policy. This ensures that unwanted traffic is denied by default.
+>
+> 📖 [Calico Best practice: implicit default deny policy](https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-default-deny#best-practice-implicit-default-deny-policy).
+
+You can use the Kubernetes builtin `NetworkPolicy` resource,
+which is portable because it is recognized by any of the [Kubernetes Network (CNI) Plugins](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/).
+Or you may prefer to use the custom resources provided by your CNI software.
+
+> 📖 Learn about the [Kubernetes builtin NetworkPolicy API](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
+> and see [some example policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/#default-policies).
+
+### Network Requirements
+
+Here is an overview of the network requirements:
+
+1. **UDP / TCP: cert-manager (all) -> Kubernetes DNS**:
+ All cert-manager components perform UDP DNS queries for both cluster and external domain names.
+ Some DNS queries may use TCP.
+
+1. **TCP: Kubernetes (API server) -> cert-manager (webhook)**:
+ The Kubernetes API server establishes HTTPS connections to the [cert-manager webhook component](../concepts/webhook.md).
+ Read the cert-manager [webhook troubleshooting guide](../troubleshooting/webhook.md)
+ to understand the webhook networking requirements.
+
+1. **TCP: cert-manager (webhook, controller, cainjector, startupapicheck) -> Kubernetes API server**:
+ The cert-manager webhook, controller, cainjector and startupapicheck
+ establish HTTPS connections to the Kubernetes API server,
+ to interact with cert-manager custom resources and Kubernetes resources.
+ The cert-manager webhook is a special case;
+ it connects to the Kubernetes API server to use the `SubjectAccessReview` API,
+ to verify clients attempting to modify `Approved` or `Denied` conditions of `CertificateRequest` resources.
+
+1. **TCP: cert-manager (controller) -> HashiCorp Vault (authentication and resource API endpoints)**:
+ The cert-manager controller may establish HTTPS connections to one or more Vault API endpoints,
+ if you are using the [Vault Issuer](../configuration/vault.md).
+ The target host and port of the Vault endpoints
+ are configured in Issuer or ClusterIssuer resources.
+
+1. **TCP: cert-manager (controller) -> Venafi TLS Protect (authentication and resource API endpoints)**:
+ The cert-manager controller may establish HTTPS connections to one or more Venafi API endpoints,
+ if you are using the [Venafi Issuer](../configuration/venafi.md).
+ The target host and port of the Venafi API endpoints
+ are configured in Issuer or ClusterIssuer resources.
+
+1. **TCP: cert-manager (controller) -> DNS API endpoints (for ACME DNS01)**:
+ The cert-manager controller may establish HTTPS connections to DNS API endpoints such as Amazon Route53,
+ and to any associated authentication endpoints,
+ if you are using the [ACME Issuer with DNS01 solvers](../configuration/acme/dns01/README.md#supported-dns01-providers).
+
+1. **UDP / TCP: cert-manager (controller) -> External DNS**:
+ If you use the ACME Issuer, the cert-manager controller may send
+ DNS queries to recursive DNS servers,
+ as part of the ACME challenge self-check process.
+ It does this to ensure that the DNS01 or HTTP01 challenge is resolvable,
+ before asking the ACME server to perform its checks.
+
+ In the case of DNS01 it may also perform a series of DNS queries to authoritative DNS servers,
+ to compute the DNS zone in which to add the DNS01 challenge record.
+ In the case of DNS01, cert-manager also [supports DNS over HTTPS](../releases/release-notes/release-notes-1.13.md#dns-over-https-doh-support).
+
+ You can choose the host and port of the DNS servers, using the following [controller flags](../cli/controller.md):
+ `--acme-http01-solver-nameservers`,
+ `--dns01-recursive-nameservers`, and
+ `--dns01-recursive-nameservers-only`.
+
+1. **TCP: ACME (Let's Encrypt) -> cert-manager (acmesolver)**:
+ If you use an ACME Issuer configured for HTTP01,
+ cert-manager will deploy an `acmesolver` Pod, a Service and an Ingress (or Gateway API) resource
+ in the namespace of the Issuer
+ or in the cert-manager namespace if it is a ClusterIssuer.
+ The ACME implementation will establish an HTTP connection to this Pod via your chosen ingress load balancer,
+ so your network policy must allow this.
+
+ > ℹ️ The acmesolver Pod **does not** require access to the Kubernetes API server.
+
+1. **TCP: Metrics Server -> cert-manager (controller)**:
+ The cert-manager controller has a metrics server which listens for HTTP connections on TCP port 9402.
+ Create a network policy which allows access to this service from your chosen metrics collector.
+
+## Isolate cert-manager on dedicated node pools
+
+cert-manager is a cluster scoped operator and you should treat it as part of your platform's control plane.
+The cert-manager controller creates and modifies Kubernetes Secret resources
+and the controller and cainjector both cache TLS Secret resources in memory.
+These are two reasons why you should consider isolating the cert-manager components from
+other less privileged workloads.
+For example, if an untrusted or malicious workload runs on the same Node as the cert-manager controller,
+and somehow gains root access to the underlying node,
+it may be able to read the private keys in Secrets that the controller has cached in memory.
+
+You can mitigate this risk by running cert-manager on nodes that are reserved for trusted platform operators.
+
+The Helm chart for cert-manager has parameters to configure the Pod `tolerations` and `nodeSelector` for each component.
+The exact values of these parameters will depend on your particular cluster.
+
+> 📖 Read [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/)
+> in the [Kubernetes documentation](https://kubernetes.io/docs/).
+>
+> 📖 Read about [Taints and Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)
+> in the [Kubernetes documentation](https://kubernetes.io/docs/).
+
+### Example
+
+This example demonstrates how to use:
+`taints` to *repel* non-platform Pods from Nodes which you have reserved for your platform's control-plane,
+`tolerations` to *allow* cert-manager Pods to run on those Nodes, and
+`nodeSelector` to *place* the cert-manager Pods on those Nodes.
+
+Label the Nodes:
+
+```bash
+kubectl label node ... node-restriction.kubernetes.io/reserved-for=platform
+```
+
+Taint the Nodes:
+
+```bash
+kubectl taint node ... node-restriction.kubernetes.io/reserved-for=platform:NoExecute
+```
+
+Then install cert-manager using the following Helm chart values:
+
+```yaml
+nodeSelector:
+ kubernetes.io/os: linux
+ node-restriction.kubernetes.io/reserved-for: platform
+tolerations:
+- key: node-restriction.kubernetes.io/reserved-for
+ operator: Equal
+ value: platform
+
+webhook:
+ nodeSelector:
+ kubernetes.io/os: linux
+ node-restriction.kubernetes.io/reserved-for: platform
+ tolerations:
+ - key: node-restriction.kubernetes.io/reserved-for
+ operator: Equal
+ value: platform
+
+cainjector:
+ nodeSelector:
+ kubernetes.io/os: linux
+ node-restriction.kubernetes.io/reserved-for: platform
+ tolerations:
+ - key: node-restriction.kubernetes.io/reserved-for
+ operator: Equal
+ value: platform
+
+startupapicheck:
+ nodeSelector:
+ kubernetes.io/os: linux
+ node-restriction.kubernetes.io/reserved-for: platform
+ tolerations:
+ - key: node-restriction.kubernetes.io/reserved-for
+ operator: Equal
+ value: platform
+```
+
+> ℹ️ This example uses `nodeSelector` to *place* the Pods but you could also use `affinity.nodeAffinity`.
+> `nodeSelector` is chosen here because it has a simpler syntax.
+>
+> ℹ️ The default `nodeSelector` value `kubernetes.io/os: linux` [avoids placing cert-manager Pods on Windows nodes in a mixed OS cluster](https://github.com/cert-manager/cert-manager/pull/3605),
+> so that must be explicitly included here too.
+>
+> 📖 Read the [Guide to isolating tenant workloads to specific nodes](https://aws.github.io/aws-eks-best-practices/security/docs/multitenancy/#isolating-tenant-workloads-to-specific-nodes)
+> in the [EKS Best Practice Guides](https://aws.github.io/aws-eks-best-practices/),
+> for an in-depth explanation of these techniques.
+>
+> 📖 Learn how to [Isolate your workloads in dedicated node pools](https://cloud.google.com/kubernetes-engine/docs/how-to/isolate-workloads-dedicated-nodes) on [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/docs/).
+>
+> 📖 Learn about [Placing pods on specific nodes using node selectors, with RedHat OpenShift](https://docs.openshift.com/container-platform/4.13/nodes/scheduling/nodes-scheduler-node-selectors.html).
+>
+> 📖 Read more about the [`node-restriction.kubernetes.io/` prefix and the `NodeRestriction` admission plugin](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction).
+>
+> ℹ️ On a multi-tenant cluster,
+> consider enabling the [`PodTolerationRestriction` plugin](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#podtolerationrestriction)
+> to limit which tolerations tenants may add to their Pods.
+> You may also use that plugin to add default tolerations to the `cert-manager` namespace,
+> which obviates the need to explicitly set the tolerations in the Helm chart.
+>
+> ℹ️ Alternatively, you could use [Kyverno](https://kyverno.io/docs/) to limit which tolerations Pods are allowed to use.
+> Read [Restrict control plane scheduling](https://kyverno.io/policies/other/res/restrict-controlplane-scheduling/restrict-controlplane-scheduling/) as a starting point.
+
+## High Availability
+
+cert-manager has three long-running components: controller, cainjector, and webhook.
+Each of these components has a Deployment and by default each Deployment has 1 replica
+but this does not provide high availability.
+The Helm chart for cert-manager has parameters to configure the `replicaCount` for each Deployment.
+In production we recommend the following `replicaCount` parameters:
+
+```yaml
+replicaCount: 2
+webhook:
+ replicaCount: 3
+cainjector:
+ replicaCount: 2
+```
+
+### controller and cainjector
+
+The controller and cainjector components use [leader election](https://pkg.go.dev/k8s.io/client-go/tools/leaderelection)
+to ensure that only one replica is active.
+This prevents conflicts which would arise if multiple replicas were reconciling the same API resources.
+So in these components you can use multiple replicas to achieve high availability but not for horizontal scaling.
+
+Use two replicas to ensures that there is a standby Pod scheduled to a Node which is ready to take leadership,
+should the current leader encounter a disruption.
+For example, when the leader Pod is drained from its node.
+Or, if the leader Pod encounters an unexpected deadlock.
+
+There is little justification for using more than 2 replicas of these components.
+
+### webhook
+
+By default the cert-manager webhook Deployment has 1 replica, but in production you should use 3 or more.
+If the cert-manager webhook is unavailable, all API operations on cert-manager custom resources will fail,
+and this will disrupt any software that creates, updates or deletes cert-manager custom resources (including cert-manager itself),
+and it may cause other disruptions to your cluster.
+So it is *especially* important to keep at multiple replicas of the cert-manager webhook running at all times.
+
+> ℹ️ By contrast, if there is only a single replica of the cert-manager controller, there is less risk of disruption.
+> For example, if the Node hosting the single cert-manager controller manager Pod is drained,
+> there will be a delay while a new Pod is started on another Node,
+> and any cert-manager resources that are created or changed during that time will not be reconciled until the new Pod starts up.
+> But the controller manager works asynchronously anyway, so any applications which depend on the cert-manager custom resources
+> will be designed to tolerate this situation.
+> That being said, the best practice is to run 2 or more replicas of each controller if the cluster has sufficient resources.
+>
+> 📖 Read [Ensure control plane stability when using webhooks](https://cloud.google.com/kubernetes-engine/docs/how-to/optimize-webhooks)
+> in the Google Kubernetes Engine (GKE) documentation,
+> for examples of how webhook disruptions might disrupt your cluster.
+>
+> 📖 Read [The dark side of Kubernetes admission webhooks](https://techblog.cisco.com/blog/dark-side-of-kubernetes-admission-webhooks)
+> on the Cisco Tech Blog, to learn more about potential issues caused by webhooks and how you can avoid them.
+
+### Topology Spread Constraints
+
+Consider using [Topology Spread Constraints](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/),
+to ensure that a disruption of a node or data center does not degrade the operation of cert-manager.
+
+For high availability you do not want the replica Pods to be scheduled on the same Node,
+because if that node fails, both the active and standby Pods will exit,
+and there will be no further reconciliation of the resources by that controller,
+until there is another Node with sufficient free resources to run a new Pod,
+and until that Pod has become Ready.
+
+It is also desirable for the Pods to be running in separate data centers (availability zones),
+if the cluster has nodes distributed between zones.
+Then, in the event of a failure at the data center hosting the active Pod ,
+the standby Pod will immediately be available to take leadership.
+
+Fortunately you may not need to do anything to achieve these goals
+because [Kubernetes >= 1.24 has Built-in default constraints](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/#internal-default-constraints)
+which should mean that the high availability scheduling described above will happen implicitly.
+
+> ℹ️ In case your cluster does not use Built-in default constraints.
+> You can add [Topology Spread Constraints](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/)
+> to each of the cert-manager components using Helm chart values.
+
+### PodDisruptionBudget
+
+For high availability you should also deploy a `PodDisruptionBudget` resource with `minAvailable=1`.
+
+This ensures that a *voluntary* disruption, such as the draining of a Node, cannot proceed
+until at least one other replica has been successfully scheduled and started on another Node.
+The Helm chart has parameters to enable and configure a PodDisruptionBudget
+for each of the long-running cert-manager components.
+We recommend the following parameters:
+
+```yaml
+podDisruptionBudget:
+ enabled: true
+ minAvailable: 1
+webhook:
+ podDisruptionBudget:
+ enabled: true
+ minAvailable: 1
+cainjector:
+ podDisruptionBudget:
+ enabled: true
+ minAvailable: 1
+```
+
+> 📖 Read about [Specifying a Disruption Budget for your Application](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) in the Kubernetes documentation.
+>
+> ⚠️ These PodDisruptionBudget settings are only suitable for high availability deployments.
+> You must increase the `replicaCount` of each Deployment to more than the `minAvailable` value,
+> otherwise the PodDisruptionBudget will prevent you from draining cert-manager Pods.
+
+## Scalability
+
+cert-manager has three long-running components: controller, cainjector, and webhook.
+The Helm chart does not include resource requests and limits for any of these,
+so you should supply resource requests and limits which are appropriate for your cluster.
+
+### controller and cainjector
+
+The controller and cainjector components use leader election to ensure that only one replica is active.
+This prevents conflicts which would arise if multiple replicas were reconciling the same API resources.
+You cannot use horizontal scaling for these components.
+Use vertical scaling instead.
+
+#### Memory
+
+Use vertical scaling to assign sufficient memory resources to these components.
+The memory requirements will be higher on clusters with very many API resources or with large API resources.
+This is because each of the components reconciles one or more Kubernetes API resources,
+and each component will cache the metadata and sometimes the entire resource in memory,
+so as to reduce the load on the Kubernetes API server.
+
+If your cluster contains a high volume of `CertificateRequest` resources such as when using many ephemeral or short lived certificates rotated frequently,
+you will need to increase the memory limit of the controller Pod.
+
+You can also reduce the memory consumption of `cainjector`
+by configuring it to only watch resources in the `cert-manager` namespace,
+and by configuring it to **not** watch `Certificate` resources.
+Here's how to configure the [cainjector command line flags](../cli/cainjector.md) using Helm chart values:
+
+```yaml
+cainjector:
+ extraArgs:
+ - --namespace=cert-manager
+ - --enable-certificates-data-source=false
+```
+
+> ⚠️️ This optimization is only appropriate if `cainjector` is being used exclusively for the the cert-manager webhook.
+> It is not appropriate if `cainjector` is also being used to manage the TLS certificates for webhooks of other software.
+> For example, some Kubebuilder derived projects may depend on `cainjector`
+> to [inject TLS certificates for their webhooks](https://book.kubebuilder.io/cronjob-tutorial/running-webhook.html#cert-manager).
+
+#### CPU
+
+Use vertical scaling to assign sufficient CPU resources to the these components.
+The CPU requirements will be higher on clusters where there are very frequent updates to the resources which are reconciled by these components.
+Whenever a resource changes, it will be queued to be re-reconciled by the component.
+Higher CPU resources allow the component to process the queue faster.
+
+### webhook
+
+The cert-manager webhook does not use leader election, so you *can* scale it horizontally by increasing the number of replicas.
+When the Kubernetes API server connects to the cert-manager webhook it does so via a Service which load balances the connections
+between all the Ready replicas.
+For this reason, there is a clear benefit to increasing the number of webhook replicas to 3 or more,
+on clusters where there is a high frequency of cert-manager custom resource interactions.
+Furthermore, the webhook has modest memory requirements because it does not use a cache.
+For this reason, the resource cost of scaling out the webhook is relatively low.
+
+## Use Liveness Probes
+
+An example of this recommendation is found in the Datree Documentation:
+[Ensure each container has a configured liveness probe](https://hub.datree.io/built-in-rules/ensure-liveness-probe):
+> Liveness probes allow Kubernetes to determine when a pod should be replaced.
+> They are fundamental in configuring a resilient cluster architecture.
+
+The cert-manager webhook and controller Pods do have liveness probes,
+but only the webhook liveness probe is enabled by default.
+The cainjector Pod does not have a liveness probe, yet.
+More information below.
+
+### webhook
+
+The [cert-manager webhook](../concepts/webhook.md) has a [liveness probe which is enabled by default](https://github.com/cert-manager/cert-manager/blob/eafe0d0aae4b7a9411825424f6b43fb623e1ba65/deploy/charts/cert-manager/templates/webhook-deployment.yaml#L108C1-L121)
+and the [timings and thresholds can be configured using Helm values](https://github.com/cert-manager/cert-manager/blob/eafe0d0aae4b7a9411825424f6b43fb623e1ba65/deploy/charts/cert-manager/README.template.md?plain=1#L181-L185).
+
+### controller
+
+> ℹ️ The cert-manager controller liveness probe was introduced in cert-manager release `1.12`.
+
+The cert-manager controller has a liveness probe, but it is **disabled by default**.
+You can enable it using the Helm chart value `livenessProbe.enabled=true`,
+but first read the background information below.
+
+> 📢 The controller liveness probe is a new feature in cert-manager release 1.12
+> and it is disabled by default, as a precaution, in case it causes problems in the field.
+> [Please get in touch](../contributing/README.md)
+> and tell us if you have enabled the controller liveness probe in production
+> and whether you would like it to be turned on by default.
+> Please also include any circumstances where the controller has become stuck
+> and where the liveness probe has been necessary to automatically restart the process.
+
+The liveness probe for the cert-manager controller is an HTTP probe which connects
+to the `/livez` endpoint of a healthz server which listens on port 9443 and runs in its own thread.
+The `/livez` endpoint currently reports the combined status of the following sub-systems
+and each sub-system has its own `/livez` endpoint. These are:
+
+* `/livez/leaderElection`: Returns an error if the leader election record has not been renewed
+ or if the leader election thread has exited without also crashing the parent process.
+
+> ℹ️ In future more sub-systems could be checked by the `/livez` endpoint,
+> similar to how Kubernetes [ensure logging is not blocked](https://github.com/kubernetes/kubernetes/pull/64946)
+> and have [health checks for each controller](https://github.com/kubernetes/kubernetes/pull/104667).
+>
+> 📖 Read about [how to access individual health checks and verbose status information](https://kubernetes.io/docs/reference/using-api/health-checks/) (cert-manager uses the same healthz endpoint multiplexer as Kubernetes).
+
+### cainjector
+
+The cainjector Pod does not have a liveness probe or a `/livez` healthz endpoint,
+but there is justification for it in the GitHub issue:
+[cainjector in a zombie state after attempting to shut down](https://github.com/cert-manager/cert-manager/issues/5889).
+Please add your remarks to that issue if you have also experienced this specific problem,
+and add your remarks to [Helm: Allow configuration of readiness, liveness and startup probes for all created Pods](https://github.com/cert-manager/cert-manager/issues/5626) if you have a general request for a liveness probe in cainjector.
+
+### Background Information
+
+The cert-manager `controller` process and the `cainjector` process,
+both use the Kubernetes [leader election library](https://pkg.go.dev/k8s.io/client-go/tools/leaderelection),
+to ensure that only one replica of each process can be active at any one time.
+The Kubernetes control-plane components also use this library.
+
+The leader election code runs in a loop in a separate thread (go routine).
+If it initially wins the leader election race and if it later fails to renew its leader election lease, it exits.
+If the leader election thread exits, all the other threads are gracefully shutdown and then the process exits.
+Similarly, if any of the other main threads exit unexpectedly,
+that will trigger the orderly shutdown of the remaining threads and the process will exit.
+
+This adheres to the principle that [Containers should crash when there's a fatal error](https://blog.colinbreck.com/kubernetes-liveness-and-readiness-probes-revisited-how-to-avoid-shooting-yourself-in-the-other-foot/#letitcrash).
+Kubernetes will restart the crashed container, and if it crashes repeatedly,
+there will be increasing time delays between successive restarts.
+
+For this reason, the liveness probe should only be needed if there is a bug in this orderly shutdown process,
+or if there is a bug in one of the other threads which causes the process to deadlock and not shutdown.
+
+You may want to enable the liveness probe anyway, for defense against unforeseen bugs and deadlocks,
+but you will need to monitor the processes closely and,
+tweak the [various liveness probe time settings and thresholds](https://github.com/cert-manager/cert-manager/blob/eafe0d0aae4b7a9411825424f6b43fb623e1ba65/deploy/charts/cert-manager/values.yaml#L254-L268), if necessary.
+
+> 📖 Read [Configure Liveness, Readiness and Startup Probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#before-you-begin) in the Kubernetes documentation, paying particular attention to the notes and cautions in that document.
+>
+> 📖 Read [Shooting Yourself in the Foot with Liveness Probes](https://blog.colinbreck.com/kubernetes-liveness-and-readiness-probes-how-to-avoid-shooting-yourself-in-the-foot/#shootingyourselfinthefootwithlivenessprobes) for more cautionary information about liveness probes.
+
## Restrict Auto-Mount of Service Account Tokens
-This recommendation is described in the [Kyverno Policy Catalogue](https://kyverno.io/policies/other/restrict_automount_sa_token/restrict_automount_sa_token/) as follows:
+This recommendation is described in the [Kyverno Policy Catalogue](https://kyverno.io/policies/other/res/restrict-automount-sa-token/restrict-automount-sa-token/) as follows:
> Kubernetes automatically mounts ServiceAccount credentials in each Pod. The
> ServiceAccount may be assigned roles allowing Pods to access API resources.
> Blocking this ability is an extension of the least privilege best practice and
@@ -25,7 +479,7 @@ This recommendation is described in the [Kyverno Policy Catalogue](https://kyver
The cert-manager components *do* need to speak to the API server but we still recommend setting `automountServiceAccountToken: false` for the following reasons:
1. Setting `automountServiceAccountToken: false` will allow cert-manager to be installed on clusters where Kyverno (or some other policy system) is configured to deny Pods that have this field set to `true`. The Kubernetes default value is `true`.
-2. With `automountServiceAccountToken: true`, *all* the containers in the Pod will mount the ServiceAccount token, including side-car and init containers that might have been injected into the cert-manager Pod resources by Kubernetes admission controllers.
+2. With `automountServiceAccountToken: true`, *all* the containers in the Pod will mount the ServiceAccount token, including side-car and init containers that might have been injected into the cert-manager Pod resources by Kubernetes admission controllers.
The principle of least privilege suggests that it is better to explicitly mount the ServiceAccount token into the cert-manager containers.
So it is recommended to set `automountServiceAccountToken: false` and manually add a projected `Volume` to each of the cert-manager Deployment resources, containing the ServiceAccount token, CA certificate and namespace files that would normally be [added automatically by the Kubernetes ServiceAccount controller](https://github.com/kubernetes/kubernetes/blob/3992eda8e61725c470fb6141a7fe4e7f9ee31ea5/plugin/pkg/admission/serviceaccount/admission.go#L421-L460),
@@ -45,4 +499,3 @@ Download the following Helm chart values file and supply it to `helm install`, `
This list of recommendations is a work-in-progress.
If you have other best practice recommendations please [contribute to this page](../contributing/contributing-flow.md).
-
diff --git a/content/docs/installation/code-signing.md b/content/docs/installation/code-signing.md
index cd05c04f2f..c6cade8771 100644
--- a/content/docs/installation/code-signing.md
+++ b/content/docs/installation/code-signing.md
@@ -22,7 +22,7 @@ The simplest way to verify signatures is to download the public key and then pas
```console
curl -sSOL https://cert-manager.io/public-keys/cert-manager-pubkey-2021-09-20.pem
-IMAGE_TAG=v1.11.0 # change as needed
+IMAGE_TAG=v1.13.2 # change as needed
cosign verify --signature-digest-algorithm sha512 --key cert-manager-pubkey-2021-09-20.pem quay.io/jetstack/cert-manager-acmesolver:$IMAGE_TAG
cosign verify --signature-digest-algorithm sha512 --key cert-manager-pubkey-2021-09-20.pem quay.io/jetstack/cert-manager-cainjector:$IMAGE_TAG
cosign verify --signature-digest-algorithm sha512 --key cert-manager-pubkey-2021-09-20.pem quay.io/jetstack/cert-manager-ctl:$IMAGE_TAG
diff --git a/content/docs/installation/compatibility.md b/content/docs/installation/compatibility.md
index efb53c9aad..516bc941a0 100644
--- a/content/docs/installation/compatibility.md
+++ b/content/docs/installation/compatibility.md
@@ -84,6 +84,8 @@ helm install \
--version ${CERT_MANAGER_VERSION} --set global.leaderElection.namespace=cert-manager
```
+The implication for a `kubectl apply` type installation is then either "you must manually update the manifests prior to installation by replacing `kube-system` with cert-manager" or "Don't install cert-manager using kubectl apply. Helm is the recommended solution".
+
## AWS EKS
When using a custom CNI (such as Weave or Calico) on EKS, the webhook cannot be
@@ -109,4 +111,4 @@ the webhook listens. See the warning at the top of this page for more details.
Because Fargate forces you to use its networking, you cannot manually set the networking
type and options such as `webhook.hostNetwork` on the helm chart will cause your
-cert-manager deployment to fail in surprising ways.
\ No newline at end of file
+cert-manager deployment to fail in surprising ways.
diff --git a/content/docs/installation/configuring-components.md b/content/docs/installation/configuring-components.md
new file mode 100644
index 0000000000..d10ba2d555
--- /dev/null
+++ b/content/docs/installation/configuring-components.md
@@ -0,0 +1,95 @@
+---
+title: cert-manager component configuration
+description: 'Configure cert-manager components using CLI flags or a configuration file'
+---
+
+To configure the cert-manager components, you can use CLI flags or a configuration file.
+The CLI flags take precedence over the configuration file.
+
+## CLI flags
+
+An overview of the available CLI flags for each component can be found on the following pages:
+- cert-manager controller: [controller CLI flags](../cli/controller.md)
+- cert-manager webhook: [webhook CLI flags](../cli/webhook.md)
+- cert-manager cainjector: [cainjector CLI flags](../cli/cainjector.md)
+- cert-manager acmesolver: [acmesolver CLI flags](../cli/acmesolver.md)
+- cert-manager cmctl: [cmctl CLI flags](../cli/cmctl.md)
+
+When using the Helm chart, the CLI flags can be specified in the `controller.extraArgs`, `webhook.extraArgs`, `cainjector.extraArgs` and `acmesolver.extraArgs` values.
+
+## Configuration file
+
+The configuration file is a YAML file that contains the configuration for the cert-manager components.
+The configuration file can be specified using the `--config` CLI flag. When using the Helm chart, the
+configuration file can be specified in the `config` and `webhook.config` values.
+
+### Controller configuration file
+
+The webhook configuration API documentation can be found on the [ControllerConfiguration](../reference/api-docs.md#controller.config.cert-manager.io/v1alpha1.ControllerConfiguration) page.
+
+This is an example configuration file for the controller component:
+
+```yaml
+apiVersion: controller.config.cert-manager.io/v1alpha1
+kind: ControllerConfiguration
+
+logging:
+ verbosity: 2
+ format: text
+
+leaderElectionConfig:
+ namespace: my-namespace
+
+kubernetesAPIQPS: 10
+kubernetesAPIBurst: 50
+
+numberOfConcurrentWorkers: 200
+
+featureGates:
+ AdditionalCertificateOutputFormats: true
+ ExperimentalCertificateSigningRequestControllers: true
+ ExperimentalGatewayAPISupport: true
+ ServerSideApply: true
+ LiteralCertificateSubject: true
+ UseCertificateRequestBasicConstraints: true
+```
+
+> **Note:** This is included as an example only and not intended to be used as default settings.
+
+### Webhook configuration file
+
+The webhook configuration API documentation can be found on the [WebhookConfiguration](../reference/api-docs.md#webhook.config.cert-manager.io/v1alpha1.WebhookConfiguration) page.
+
+Here is an example configuration file for the webhook component:
+
+```yaml
+apiVersion: webhook.config.cert-manager.io/v1alpha1
+kind: WebhookConfiguration
+
+logging:
+ verbosity: 2
+ format: text
+
+securePort: 6443
+healthzPort: 6080
+
+featureGates:
+ AdditionalCertificateOutputFormats: true
+ LiteralCertificateSubject: true
+```
+
+> **Note:** This is included as an example only and not intended to be used as default settings.
+
+## Feature gates
+
+Feature gates can be used to enable or disable experimental features in cert-manager.
+
+There are 2 levels of feature gates (more details in [Kubernetes definition of feature stages](https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-stages)):
+- **Alpha:** feature is not yet stable and might be removed or changed in the future. Alpha features are disabled by default and need to be explicitly enabled by the user (to test the feature).
+- **Beta:** feature is almost stable but might still change in the future. Beta features are enabled by default and can be disabled by the user (if any issues are encountered).
+
+Each cert-manager component has its own set of feature gates. They can be enabled/ disabled using the `--feature-gates` flag or the `featureGates` value in the config file. The available feature gates for each component can be found on the following pages:
+
+- cert-manager controller: [controller feature gates](https://github.com/cert-manager/cert-manager/blob/master/internal/controller/feature/features.go)
+- cert-manager webhook: [webhook feature gates](https://github.com/cert-manager/cert-manager/blob/master/internal/webhook/feature/features.go)
+- cert-manager cainjector: [cainjector feature gates](https://github.com/cert-manager/cert-manager/blob/master/internal/cainjector/feature/features.go)
diff --git a/content/docs/installation/continuous-deployment-and-gitops.md b/content/docs/installation/continuous-deployment-and-gitops.md
new file mode 100644
index 0000000000..aaa3a07886
--- /dev/null
+++ b/content/docs/installation/continuous-deployment-and-gitops.md
@@ -0,0 +1,114 @@
+---
+title: Continuous Deployment
+description: Learn how to automate the installation of cert-manager using tools like Flux and Argo CD
+---
+
+Learn how to automate the installation of cert-manager using tools like Flux and Argo CD.
+
+## Introduction
+
+You can use [the cert-manager Helm chart](./helm.md) directly with tools like Flux, ArgoCD and Anthos,
+and you can [output YAML using helm template](./helm.md#output-yaml) to generate customized cert-manager installation manifests,
+which can be piped into your preferred deployment tool.
+
+This page contains notes about how to install cert-manager with *some* of these tools.
+
+> 📢 Please help us improve this page
+> by contributing notes or short tutorials about using cert-manager with common GitOps and continuous deployment tools.
+
+## Using the Flux Helm Controller
+
+The cert-manager Helm chart can be installed by the [Flux Helm Controller](https://fluxcd.io/flux/components/helm/).
+
+First create a [`HelmRepository` resource](https://fluxcd.io/flux/components/source/helmrepositories/),
+configured with URL of the cert-manager Helm repository.
+Then create a [`HelmRelease` resource](https://fluxcd.io/flux/components/helm/helmreleases/),
+configured with your desired cert-manager chart values and release.
+
+Here is an example which installs the latest patch version of the cert-manager 1.12 release,
+and then upgrades to the latest patch version of the 1.13 release.
+
+> ⚠️ This is a simple example which may not be suitable for production use.
+> You should also refer to the [official Flux example repo](https://github.com/fluxcd/flux2-kustomize-helm-example),
+> where cert-manager is now fully integrated.
+> It shows how to deploy ClusterIssuer resources in the right order,
+> after cert-manager CRDs and controller have been installed.
+
+### Prerequisites
+
+You'll need the [`flux` CLI](https://fluxcd.io/flux/cmd/)
+and a Kubernetes cluster with [Flux installed](https://fluxcd.io/flux/installation/).
+
+Here's how to quickly install Flux on a [Kind](https://kind.sigs.k8s.io/) cluster:
+
+```bash
+kind create cluster
+flux check --pre
+flux install
+flux check
+```
+
+### Create a `HelmRepository` resource
+
+```bash
+flux create source helm cert-manager --url https://charts.jetstack.io
+```
+
+### Create a `HelmRelease` resource
+
+Put your Helm chart values in a `values.yaml` file.
+Use the `installCRDs` value, so that Flux can install and upgrade the CRD resources.
+
+```yaml
+# values.yaml
+installCRDs: true
+```
+
+```bash
+flux create helmrelease cert-manager \
+ --chart cert-manager \
+ --source HelmRepository/cert-manager.flux-system \
+ --release-name cert-manager \
+ --target-namespace cert-manager \
+ --create-target-namespace \
+ --values values.yaml \
+ --chart-version 1.12.x
+```
+
+### Updates and Upgrades
+
+And when you want to upgrade to the cert-manager 1.13 release,
+you can simply update the partial semantic version in the chart version:
+
+```bash
+flux create helmrelease cert-manager \
+ --chart cert-manager \
+ --source HelmRepository/cert-manager.flux-system \
+ --release-name cert-manager \
+ --target-namespace cert-manager \
+ --create-target-namespace \
+ --values values.yaml \
+ --chart-version 1.13.x
+```
+
+### Troubleshooting
+
+Check Flux events and logs for warnings and errors:
+
+```bash
+flux events
+flux logs
+```
+
+Use `cmctl` to check for problems with the cert-manager webhook or CRDs:
+
+```bash
+cmctl check api
+cmctl version -o yaml
+```
+
+Check the cert-manager logs for warnings and errors:
+
+```bash
+kubectl logs -n cert-manager -l app.kubernetes.io/instance=cert-manager --prefix --all-containers
+```
diff --git a/content/docs/installation/helm.md b/content/docs/installation/helm.md
index f662f11f40..870cc78a0d 100644
--- a/content/docs/installation/helm.md
+++ b/content/docs/installation/helm.md
@@ -13,12 +13,11 @@ non-namespaced resources in your cluster and care must be taken to ensure that i
### Prerequisites
- [Install Helm version 3 or later](https://helm.sh/docs/intro/install/).
-- Install a [supported version of Kubernetes or OpenShift](./supported-releases.md).
+- Install a [supported version of Kubernetes or OpenShift](../releases/README.md).
- Read [Compatibility with Kubernetes Platform Providers](./compatibility.md) if you are using Kubernetes on a cloud platform.
### Steps
-
#### 1. Add the Helm repository
This repository is the only supported source of cert-manager charts. There are some other mirrors and copies across the internet, but those are entirely unofficial and could present a security risk.
@@ -38,23 +37,29 @@ helm repo update
#### 3. Install `CustomResourceDefinitions`
cert-manager requires a number of CRD resources, which can be installed manually using `kubectl`,
-or using the `installCRDs` option when installing the Helm chart.
+or using the `installCRDs` option when installing the Helm chart. Both options
+are described below and will achieve the same result but with varying
+consequences. You should consult the [CRD Considerations](#crd-considerations)
+section below for details on each method.
##### Option 1: installing CRDs with `kubectl`
+> Recommended for production installations
```bash
-kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.crds.yaml
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.crds.yaml
```
##### Option 2: install CRDs as part of the Helm release
+> Recommended for ease of use & compatibility
+
To automatically install and manage the CRDs as part of your Helm release, you
must add the `--set installCRDs=true` flag to your Helm installation command.
Uncomment the relevant line in the next steps to enable this.
-Note that if you're using a `helm` version based on Kubernetes `v1.18` or below (Helm `v3.2`), `installCRDs` will not work with cert-manager `v0.16`. See the [v0.16 upgrade notes](./upgrading/upgrading-0.15-0.16.md#helm) for more details.
+Note that if you're using a `helm` version based on Kubernetes `v1.18` or below (Helm `v3.2`), `installCRDs` will not work with cert-manager `v0.16`. See the [v0.16 upgrade notes](../releases/upgrading/upgrading-0.15-0.16.md#helm) for more details.
#### 4. Install cert-manager
@@ -65,7 +70,7 @@ helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
- --version v1.11.0 \
+ --version v1.13.2 \
# --set installCRDs=true
```
@@ -78,12 +83,13 @@ helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
- --version v1.11.0 \
+ --version v1.13.2 \
+ # --set installCRDs=true
--set prometheus.enabled=false \ # Example: disabling prometheus using a Helm parameter
--set webhook.timeoutSeconds=4 # Example: changing the webhook timeout using a Helm parameter
```
-Once you have deployed cert-manager, you can [verify](./verify.md) the installation.
+Once you have deployed cert-manager, you can [verify](./kubectl.md#verify) the installation.
### Installing cert-manager as subchart
@@ -108,17 +114,20 @@ version: 0.1.0
appVersion: "0.1.0"
dependencies:
- name: cert-manager
- version: v1.11.0
+ version: v1.13.2
repository: https://charts.jetstack.io
alias: cert-manager
condition: cert-manager.enabled
```
-You can then override the namespace in 2 ways
+
+You can then override the namespace in 2 ways:
+
1. In `Values.yaml` file
```yaml
cert-manager: #defined by either the name or alias of your dependency in Chart.yaml
namespace: security
```
+
2. In the helm command using `--set`
```bash
helm install example example_chart \
@@ -139,7 +148,7 @@ helm template \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
- --version v1.11.0 \
+ --version v1.13.2 \
# --set prometheus.enabled=false \ # Example: disabling prometheus using a Helm parameter
# --set installCRDs=true \ # Uncomment to also template CRDs
> cert-manager.custom.yaml
@@ -170,7 +179,6 @@ Uninstalling cert-manager from a `helm` installation is a case of running the
installation process, *in reverse*, using the delete command on both `kubectl`
and `helm`.
-
```bash
helm --namespace cert-manager delete cert-manager
```
@@ -192,6 +200,10 @@ using the link to the version `vX.Y.Z` you installed:
kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/vX.Y.Z/cert-manager.crds.yaml
```
+*Note:* If you used `helm` to install the CRDs with the `installCRDs=true`
+value for the chart, then the CRDs will have been automatically removed and
+you do not need to run this final `kubectl` command.
+
### Namespace Stuck in Terminating State
If the namespace has been marked for deletion without deleting the cert-manager
@@ -204,3 +216,78 @@ experiencing issues then run:
```bash
kubectl delete apiservice v1beta1.webhook.cert-manager.io
```
+
+## CRD considerations
+
+### kubectl installation
+
+When installing CRDs with `kubectl`, you will need to upgrade these in tandem
+with your cert-manager installation upgrades. This approach may be useful when
+you do not have the ability to install CRDs all the time in your environment.
+If you do not upgrade these as you upgrade cert-manager itself, you may miss
+out on new features for cert-manager.
+
+Benefits:
+
+- CRDs will not change once applied
+
+Drawbacks:
+
+- CRDs are not automatically updated and need to be reapplied before
+ upgrading cert-manager
+- You may have different installation processes for CRDs compared to
+ the other resources.
+
+### helm installation
+
+cert-manager **does not use** the [official helm method](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/ )
+of installing CRD resources. This is because it makes upgrading CRDs
+impossible with `helm` CLI alone. The helm team explain the limitations
+of their approach [here](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/#some-caveats-and-explanations).
+
+cert-manager actually bundles the CRDs along with the other templates
+in the Helm chart. This means that Helm manages these resources so they are
+upgraded with your cert-manager release when you use
+`installCRDs: true` in your values file or CLI command. This does also mean
+that if you uninstall the release, the CRDs will also be uninstalled. If that
+happens then you will loose all instances of those CRDs, e.g. all `Certificate`
+resources in the cluster. You should consider if this is likely to happen to
+you and have a mitigation, such as
+[backups](https://cert-manager.io/docs/tutorials/backup/#backing-up-cert-manager-resource-configuration)
+or a means to reapply resources from an Infrastructure as Code (IaC) pattern.
+
+**Note** this also means a typo like `installCRD: true` would be an invalid
+value and helm would silently ignore this and remove the CRDs when you next
+run your `helm upgrade`.
+
+Benefits:
+
+- CRDS are automatically updated when you upgrade cert-manager via `helm`
+- Same action manages both CRDs and other installation resources
+
+Drawbacks:
+
+- If you uninstall cert-manager, the CRDs are also uninstalled.
+- Helm values need to be correct to avoid accidental removal of CRDs.
+
+### CRD Installation Advice
+
+> You should follow the path that makes sense for your environment.
+
+Generally we recommend:
+
+- For **Safety**, install CRDs outside of Helm, e.g. `kubectl`
+- For **Ease of use**, install CRDS with `helm`
+
+You may want to consider your approach along with other tools that may offer
+helm compatible installs, for a standardized approach to managing CRD
+resources. If you have an approach that cert-manager does not currently
+support, then please
+[raise an issue](https://github.com/cert-manager/cert-manager/issues) to
+discuss.
+
+## Using the Flux Helm Controller
+
+The cert-manager Helm chart can be installed and upgraded by the Flux Helm Controller.
+
+> 📖 Read more at [Continuous Deployment: Using the Flux Helm Controller](./continuous-deployment-and-gitops.md).
diff --git a/content/docs/installation/kubectl.md b/content/docs/installation/kubectl.md
index 742f50768d..c6a787a86b 100644
--- a/content/docs/installation/kubectl.md
+++ b/content/docs/installation/kubectl.md
@@ -7,42 +7,145 @@ Learn how to install cert-manager using kubectl and static manifests.
## Prerequisites
-- [Install `kubectl` version `>= v1.19.0`](https://kubernetes.io/docs/tasks/tools/). (otherwise, you'll have issues updating the CRDs - see [v0.16 upgrade notes](./upgrading/upgrading-0.15-0.16.md#issue-with-older-versions-of-kubectl))
-- Install a [supported version of Kubernetes or OpenShift](./supported-releases.md).
+- [Install `kubectl` version `>= v1.19.0`](https://kubernetes.io/docs/tasks/tools/). (otherwise, you'll have issues updating the CRDs - see [v0.16 upgrade notes](../releases/upgrading/upgrading-0.15-0.16.md#issue-with-older-versions-of-kubectl))
+- Install a [supported version of Kubernetes or OpenShift](../releases/README.md).
- Read [Compatibility with Kubernetes Platform Providers](./compatibility.md) if you are using Kubernetes on a cloud platform.
## Steps
-All resources (the [`CustomResourceDefinitions`](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions) and the cert-manager, cainjector and webhook components)
+### 1. Install from the cert-manager release manifest
+
+All resources (the CustomResourceDefinitions and the cert-manager, cainjector and webhook components)
are included in a single YAML manifest file:
Install all cert-manager components:
```bash
-kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml
```
By default, cert-manager will be installed into the `cert-manager`
namespace. It is possible to run cert-manager in a different namespace, although
you'll need to make modifications to the deployment manifests.
-Once you have deployed cert-manager, you can [verify the installation](./verify.md).
+Once you've installed cert-manager, you can verify it is deployed correctly by
+checking the `cert-manager` namespace for running pods:
+
+```bash
+$ kubectl get pods --namespace cert-manager
+
+NAME READY STATUS RESTARTS AGE
+cert-manager-5c6866597-zw7kh 1/1 Running 0 2m
+cert-manager-cainjector-577f6d9fd7-tr77l 1/1 Running 0 2m
+cert-manager-webhook-787858fcdb-nlzsq 1/1 Running 0 2m
+```
+
+You should see the `cert-manager`, `cert-manager-cainjector`, and
+`cert-manager-webhook` pods in a `Running` state. The webhook might take a
+little longer to successfully provision than the others.
+
+If you experience problems, first check the [FAQ](../faq/README.md).
+
+### 2. (optional) Wait for cert-manager webhook to be ready
+
+The webhook component can take some time to start, and make the Kubernetes API server trust the webhook's certificate.
+
+First, make sure that [cmctl is installed](../reference/cmctl.md#installation).
+
+cmctl performs a dry-run certificate creation check against the Kubernetes cluster.
+If successful, the message `The cert-manager API is ready` is displayed.
+
+```bash
+$ cmctl check api
+The cert-manager API is ready
+```
+
+The command can also be used to wait for the check to be successful.
+Here is an output example of running the command at the same time that cert-manager is being installed:
-## Permissions Errors on Google Kubernetes Engine
+```bash
+$ cmctl check api --wait=2m
+Not ready: the cert-manager CRDs are not yet installed on the Kubernetes API server
+Not ready: the cert-manager CRDs are not yet installed on the Kubernetes API server
+Not ready: the cert-manager webhook deployment is not ready yet
+Not ready: the cert-manager webhook deployment is not ready yet
+Not ready: the cert-manager webhook deployment is not ready yet
+Not ready: the cert-manager webhook deployment is not ready yet
+The cert-manager API is ready
+```
+
+
+### 2. (optional) End-to-end verify the installation
+
+Best way to fully verify the installation is to issue a test certificate. For this, we will create a self-signed issuer and a certificate resource in a test namespace.
-When running on GKE (Google Kubernetes Engine), you might encounter a 'permission denied' error when creating some
-of the required resources. This is a nuance of the way GKE handles RBAC and IAM permissions,
-and as such you might need to elevate your own privileges to that of a "cluster-admin" **before**
-running `kubectl apply`.
-If you have already run `kubectl apply`, you should run it again after elevating your permissions:
+```bash
+$ cat < test-resources.yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: cert-manager-test
+---
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: test-selfsigned
+ namespace: cert-manager-test
+spec:
+ selfSigned: {}
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: selfsigned-cert
+ namespace: cert-manager-test
+spec:
+ dnsNames:
+ - example.com
+ secretName: selfsigned-cert-tls
+ issuerRef:
+ name: test-selfsigned
+EOF
+```
+Create the test resources.
```bash
-kubectl create clusterrolebinding cluster-admin-binding \
- --clusterrole=cluster-admin \
- --user=$(gcloud config get-value core/account)
+$ kubectl apply -f test-resources.yaml
```
+Check the status of the newly created certificate. You may need to wait a few
+seconds before cert-manager processes the certificate request.
+```bash
+$ kubectl describe certificate -n cert-manager-test
+
+...
+Spec:
+ Common Name: example.com
+ Issuer Ref:
+ Name: test-selfsigned
+ Secret Name: selfsigned-cert-tls
+Status:
+ Conditions:
+ Last Transition Time: 2019-01-29T17:34:30Z
+ Message: Certificate is up to date and has not expired
+ Reason: Ready
+ Status: True
+ Type: Ready
+ Not After: 2019-04-29T17:34:29Z
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal CertIssued 4s cert-manager Certificate issued successfully
+```
+
+Clean up the test resources.
+```bash
+$ kubectl delete -f test-resources.yaml
+```
+
+If all the above steps have completed without error, you're good to go!
+
## Uninstalling
> **Warning**: To uninstall cert-manager you should always use the same process for
> installing but in reverse. Deviating from the following process whether
@@ -115,6 +218,7 @@ First, delete existing cert-manager webhook configurations, if any:
```bash
kubectl delete mutatingwebhookconfigurations cert-manager-webhook
+kubectl delete validatingwebhookconfigurations cert-manager-webhook
```
Then change the `.metadata.finalizers` field to an empty list by editing the challenge resource:
diff --git a/content/docs/installation/operator-lifecycle-manager.md b/content/docs/installation/operator-lifecycle-manager.md
index f9982899ad..dddca56fcc 100644
--- a/content/docs/installation/operator-lifecycle-manager.md
+++ b/content/docs/installation/operator-lifecycle-manager.md
@@ -7,7 +7,7 @@ description: 'cert-manager installation: Using OLM'
### Prerequisites
-- Install a [supported version of Kubernetes or OpenShift](./supported-releases.md).
+- Install a [supported version of Kubernetes or OpenShift](../releases/README.md).
- Read [Compatibility with Kubernetes Platform Providers](./compatibility.md) if you are using Kubernetes on a cloud platform.
### Option 1: Installing from OperatorHub Web Console on OpenShift
@@ -41,7 +41,8 @@ from the [Krew Kubectl plugins index][] and then use that to install the cert-ma
```sh
operator-sdk olm install
kubectl krew install operator
-kubectl operator install cert-manager -n operators --channel stable --approval Automatic
+kubectl create ns cert-manager
+kubectl operator install cert-manager -n cert-manager --channel stable --approval Automatic --create-operator-group
```
You can monitor the progress of the installation as follows:
@@ -217,7 +218,7 @@ The following JSON patch will append `-v=6` to command line arguments of the cer
(the first container of the first Deployment).
```bash
-kubectl patch csv cert-manager.v1.11.0 \
+kubectl patch csv cert-manager.v1.13.2 \
--type json \
-p '[{"op": "add", "path": "/spec/install/spec/deployments/0/spec/template/spec/containers/0/args/-", "value": "-v=6" }]'
```
diff --git a/content/docs/installation/reinstall.md b/content/docs/installation/reinstall.md
new file mode 100644
index 0000000000..9c544b3723
--- /dev/null
+++ b/content/docs/installation/reinstall.md
@@ -0,0 +1,33 @@
+---
+title: Reinstalling cert-manager
+description: 'cert-manager installation: Reinstalling cert-manager overview'
+---
+
+In some cases there may be a need to do a full uninstall and re-install of
+cert-manager. An example could be when a very old cert-manager version needs to
+be brought up to date and it isn't feasible to upgrade one minor version at a
+time, which is our default recommended upgrade strategy.
+
+If cert-manager `CustomResourceDefinition`s are also uninstalled, this will mean
+loss of associated cert-manager custom resources such as `Certificate`s. The
+main concern associated with this is application downtime and unnecessary
+certificate reissuance, that could happen if `Secret`s with the X.509
+certificates get deleted. You can use [`--enable-certificate-owner-ref`
+flag](https://cert-manager.io/docs/cli/controller/)
+on the cert-manager controller to configure whether the `Secret`s should be deleted.
+If this flag is set to true, each `Secret` will have an owner reference to the
+`Certificate` for which it was created and when the `Certificate` is deleted,
+the `Secret` will be garbage collected. The default value for this flag is
+false. If the `Certificate`s get deleted and re-applied, but the `Secret`s remain
+in the cluster, the newly applied `Certificate`s should be able to pick up the
+same `Secret`s and should not unnecessarily reissue the X.509 certs.
+
+When uninstalling and re-installing in order to upgrade, you should still read
+through the release notes for each skipped version.
+
+Some things to look out for when considering uninstalling and re-installing
+cert-manager _including the CRDs_:
+
+- Is `--enable-certificate-owner-ref` flag currently set to true or could it have been set to true at some point previously? Due to an earlier bug, the owner reference that gets added to `Secret`s is _not_ removed when the value of `--enable-certificate-owner-ref` is changed from true to false, see [`cert-manager#4788`](https://github.com/cert-manager/cert-manager/issues/4788)
+- Are there currently any certificate issuances in progress? If so, with the custom resources deleted, the progress will be lost. This could potentially cause duplicated issuances.
+- Is there a need to convert cert-manager custom resource manifests to v1 API? You can use [`cmctl convert` command](../reference/cmctl.md#convert) to do that.
diff --git a/content/docs/installation/uninstall.md b/content/docs/installation/uninstall.md
index abef2ffbd9..3ffc30772c 100644
--- a/content/docs/installation/uninstall.md
+++ b/content/docs/installation/uninstall.md
@@ -1,5 +1,5 @@
---
-title: Uninstall
+title: Uninstalling cert-manager
description: 'cert-manager installation: Uninstalling cert-manager'
---
@@ -9,4 +9,6 @@ two platforms is similar. Select the method that was used for installing
cert-manager to go to the relevant uninstall documentation.
- [kubectl](./kubectl.md#uninstalling)
-- [helm](./helm.md#uninstalling)
\ No newline at end of file
+- [helm](./helm.md#uninstalling)
+
+If you need to preserve cert-manager custom resources (`Certificate`s, `Issuer`s etc), that are not version controlled or backed up by other means, take a look at our [backup and restore guide](../devops-tips/backup.md).
diff --git a/content/docs/installation/upgrading/README.md b/content/docs/installation/upgrade.md
similarity index 61%
rename from content/docs/installation/upgrading/README.md
rename to content/docs/installation/upgrade.md
index 16d60fb1c9..0bfc4da1e3 100644
--- a/content/docs/installation/upgrading/README.md
+++ b/content/docs/installation/upgrade.md
@@ -1,16 +1,17 @@
---
-title: Upgrading
+title: Upgrading cert-manager
description: 'cert-manager installation: Upgrading cert-manager overview'
---
-This section contains information on upgrading cert-manager.
-It also contains documents detailing breaking changes between cert-manager
-versions, and information on things to look out for when upgrading.
+In the [releases section](../releases/README.md) of the documentation, you can find the release notes
+and upgrade instructions for each release of cert-manager. It also contains
+information on the breaking changes between each release and things to look out
+for when upgrading.
> Note: Before performing upgrades of cert-manager, it is advised to take a
> backup of all your cert-manager resources just in case an issue occurs whilst
> upgrading. You can read how to backup and restore cert-manager in the [backup
-> and restore](../../tutorials/backup.md) guide.
+> and restore](../devops-tips/backup.md) guide.
We recommend that you upgrade cert-manager one minor version at a time, always
choosing the latest patch version for the minor version. You should always read
@@ -87,7 +88,7 @@ number you want to install:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download//cert-manager.yaml
```
-Once you have deployed the new version of cert-manager, you can [verify](../verify.md) the installation.
+Once you have deployed the new version of cert-manager, you can [verify](kubectl.md#verify) the installation.
## Reinstalling cert-manager
@@ -96,26 +97,4 @@ cert-manager. An example could be when a very old cert-manager version needs to
be brought up to date and it isn't feasible to upgrade one minor version at a
time, which is our default recommended upgrade strategy.
-If cert-manager `CustomResourceDefinition`s are also uninstalled, this will mean
-loss of associated cert-manager custom resources such as `Certificate`s. The
-main concern associated with this is application downtime and unnecessary
-certificate reissuance, that could happen if `Secret`s with the X.509
-certificates get deleted. You can use [`--enable-certificate-owner-ref`
-flag](https://cert-manager.io/docs/cli/controller/)
-on the cert-manager controller to configure whether the `Secret`s should be deleted.
-If this flag is set to true, each `Secret` will have an owner reference to the
-`Certificate` for which it was created and when the `Certificate` is deleted,
-the `Secret` will be garbage collected. The default value for this flag is
-false. If the `Certificate`s get deleted and re-applied, but the `Secret`s remain
-in the cluster, the newly applied `Certificate`s should be able to pick up the
-same `Secret`s and should not unnecessarily reissue the X.509 certs.
-
-When uninstalling and re-installing in order to upgrade, you should still read
-through the release notes for each skipped version.
-
-Some things to look out for when considering uninstalling and re-installing
-cert-manager _including the CRDs_:
-
-- Is `--enable-certificate-owner-ref` flag currently set to true or could it have been set to true at some point previously? Due to an earlier bug, the owner reference that gets added to `Secret`s is _not_ removed when the value of `--enable-certificate-owner-ref` is changed from true to false, see [`cert-manager#4788`](https://github.com/cert-manager/cert-manager/issues/4788)
-- Are there currently any certificate issuances in progress? If so, with the custom resources deleted, the progress will be lost. This could potentially cause duplicated issuances.
-- Is there a need to convert cert-manager custom resource manifests to v1 API? You can use [`cmctl convert` command](../../reference/cmctl.md#convert) to do that.
+See [Reinstalling cert-manager](reinstall.md) for a full guide on how to do this without any issues.
diff --git a/content/docs/manifest.json b/content/docs/manifest.json
index 0250d16ace..6a18b7cb22 100644
--- a/content/docs/manifest.json
+++ b/content/docs/manifest.json
@@ -2,6 +2,7 @@
"routes": [
{
"title": "cert-manager",
+
"routes": [
{
"title": "Introduction",
@@ -12,272 +13,398 @@
"path": "/docs/getting-started/README.md"
},
{
- "title": "Installation",
+ "title": "Releases",
"routes": [
- {
- "title": "Introduction",
- "path": "/docs/installation/README.md"
- },
{
"title": "Supported Releases",
- "path": "/docs/installation/supported-releases.md"
+ "path": "/docs/releases/README.md"
},
{
- "title": "Cloud Compatibility",
- "path": "/docs/installation/compatibility.md"
+ "title": "1.13",
+ "path": "/docs/releases/release-notes/release-notes-1.13.md"
},
{
- "title": "kubectl apply",
- "path": "/docs/installation/kubectl.md"
+ "title": "Upgrade 1.12 to 1.13",
+ "path": "/docs/releases/upgrading/upgrading-1.12-1.13.md"
},
{
- "title": "Helm",
- "path": "/docs/installation/helm.md"
- },
- {
- "title": "OperatorHub (OLM)",
- "path": "/docs/installation/operator-lifecycle-manager.md"
+ "title": "1.12",
+ "path": "/docs/releases/release-notes/release-notes-1.12.md"
},
{
- "title": "Other tools",
- "path": "/docs/installation/other-tools.md"
+ "title": "Upgrade 1.11 to 1.12",
+ "path": "/docs/releases/upgrading/upgrading-1.11-1.12.md"
},
{
- "title": "Verifying",
- "path": "/docs/installation/verify.md"
- },
- {
- "title": "Feature flags",
- "path": "/docs/installation/featureflags.md"
- },
- {
- "title": "Upgrading",
+ "title": "Older releases",
"routes": [
- {
- "title": "Introduction",
- "path": "/docs/installation/upgrading/README.md"
- },
{
"title": "Notes on Ingress Class Compatibility",
- "path": "/docs/installation/upgrading/ingress-class-compatibility.md"
+ "path": "/docs/releases/upgrading/ingress-class-compatibility.md"
},
{
"title": "Migrating Deprecated API Resources",
- "path": "/docs/installation/upgrading/remove-deprecated-apis.md"
+ "path": "/docs/releases/upgrading/remove-deprecated-apis.md"
+ },
+ {
+ "title": "1.11",
+ "path": "/docs/releases/release-notes/release-notes-1.11.md"
+ },
+ {
+ "title": "Upgrade 1.10 to 1.11",
+ "path": "/docs/releases/upgrading/upgrading-1.10-1.11.md"
+ },
+ {
+ "title": "1.10",
+ "path": "/docs/releases/release-notes/release-notes-1.10.md"
+ },
+ {
+ "title": "Upgrade 1.9 to 1.10",
+ "path": "/docs/releases/upgrading/upgrading-1.9-1.10.md"
+ },
+ {
+ "title": "1.9",
+ "path": "/docs/releases/release-notes/release-notes-1.9.md"
+ },
+ {
+ "title": "Upgrade 1.8 to 1.9",
+ "path": "/docs/releases/upgrading/upgrading-1.8-1.9.md"
+ },
+ {
+ "title": "1.8",
+ "path": "/docs/releases/release-notes/release-notes-1.8.md"
+ },
+ {
+ "title": "Upgrade 1.7 to 1.8",
+ "path": "/docs/releases/upgrading/upgrading-1.7-1.8.md"
+ },
+ {
+ "title": "1.7",
+ "path": "/docs/releases/release-notes/release-notes-1.7.md"
+ },
+ {
+ "title": "Upgrade 1.6 to 1.7",
+ "path": "/docs/releases/upgrading/upgrading-1.6-1.7.md"
+ },
+ {
+ "title": "1.6",
+ "path": "/docs/releases/release-notes/release-notes-1.6.md"
+ },
+ {
+ "title": "Upgrade 1.5 to 1.6",
+ "path": "/docs/releases/upgrading/upgrading-1.5-1.6.md"
+ },
+ {
+ "title": "1.5",
+ "path": "/docs/releases/release-notes/release-notes-1.5.md"
+ },
+ {
+ "title": "Upgrade 1.4 to 1.5",
+ "path": "/docs/releases/upgrading/upgrading-1.4-1.5.md"
+ },
+ {
+ "title": "1.4",
+ "path": "/docs/releases/release-notes/release-notes-1.4.md"
+ },
+ {
+ "title": "Upgrade 1.3 to 1.4",
+ "path": "/docs/releases/upgrading/upgrading-1.3-1.4.md"
+ },
+ {
+ "title": "1.3",
+ "path": "/docs/releases/release-notes/release-notes-1.3.md"
+ },
+ {
+ "title": "Upgrade 1.2 to 1.3",
+ "path": "/docs/releases/upgrading/upgrading-1.2-1.3.md"
+ },
+ {
+ "title": "1.2",
+ "path": "/docs/releases/release-notes/release-notes-1.2.md"
+ },
+ {
+ "title": "Upgrade 1.1 to 1.2",
+ "path": "/docs/releases/upgrading/upgrading-1.1-1.2.md"
+ },
+ {
+ "title": "1.1",
+ "path": "/docs/releases/release-notes/release-notes-1.1.md"
+ },
+ {
+ "title": "Upgrade 1.0 to 1.1",
+ "path": "/docs/releases/upgrading/upgrading-1.0-1.1.md"
},
{
- "title": "v1.10 to v1.11",
- "path": "/docs/installation/upgrading/upgrading-1.10-1.11.md"
+ "title": "1.0",
+ "path": "/docs/releases/release-notes/release-notes-1.0.md"
},
{
- "title": "v1.9 to v1.10",
- "path": "/docs/installation/upgrading/upgrading-1.9-1.10.md"
+ "title": "Upgrade 0.16 to 1.0",
+ "path": "/docs/releases/upgrading/upgrading-0.16-1.0.md"
},
{
- "title": "v1.8 to v1.9",
- "path": "/docs/installation/upgrading/upgrading-1.8-1.9.md"
+ "title": "0.16",
+ "path": "/docs/releases/release-notes/release-notes-0.16.md"
},
{
- "title": "v1.7 to v1.8",
- "path": "/docs/installation/upgrading/upgrading-1.7-1.8.md"
+ "title": "Upgrade 0.15 to 0.16",
+ "path": "/docs/releases/upgrading/upgrading-0.15-0.16.md"
},
{
- "title": "v1.6 to v1.7",
- "path": "/docs/installation/upgrading/upgrading-1.6-1.7.md"
+ "title": "0.15",
+ "path": "/docs/releases/release-notes/release-notes-0.15.md"
},
{
- "title": "v1.5 to v1.6",
- "path": "/docs/installation/upgrading/upgrading-1.5-1.6.md"
+ "title": "Upgrade 0.14 to 0.15",
+ "path": "/docs/releases/upgrading/upgrading-0.14-0.15.md"
},
{
- "title": "v1.4 to v1.5",
- "path": "/docs/installation/upgrading/upgrading-1.4-1.5.md"
+ "title": "0.14",
+ "path": "/docs/releases/release-notes/release-notes-0.14.md"
},
{
- "title": "v1.3 to v1.4",
- "path": "/docs/installation/upgrading/upgrading-1.3-1.4.md"
+ "title": "Upgrade 0.13 to 0.14",
+ "path": "/docs/releases/upgrading/upgrading-0.13-0.14.md"
},
{
- "title": "v1.2 to v1.3",
- "path": "/docs/installation/upgrading/upgrading-1.2-1.3.md"
+ "title": "0.13",
+ "path": "/docs/releases/release-notes/release-notes-0.13.md"
},
{
- "title": "v1.1 to v1.2",
- "path": "/docs/installation/upgrading/upgrading-1.1-1.2.md"
+ "title": "Upgrade 0.12 to 0.13",
+ "path": "/docs/releases/upgrading/upgrading-0.12-0.13.md"
},
{
- "title": "v1.0 to v1.1",
- "path": "/docs/installation/upgrading/upgrading-1.0-1.1.md"
+ "title": "0.12",
+ "path": "/docs/releases/release-notes/release-notes-0.12.md"
},
{
- "title": "v0.16 to v1.0",
- "path": "/docs/installation/upgrading/upgrading-0.16-1.0.md"
+ "title": "Upgrade 0.11 to 0.12",
+ "path": "/docs/releases/upgrading/upgrading-0.11-0.12.md"
},
{
- "title": "v0.15 to v0.16",
- "path": "/docs/installation/upgrading/upgrading-0.15-0.16.md"
+ "title": "0.11",
+ "path": "/docs/releases/release-notes/release-notes-0.11.md"
},
{
- "title": "v0.14 to v0.15",
- "path": "/docs/installation/upgrading/upgrading-0.14-0.15.md"
+ "title": "Upgrade 0.10 to 0.11",
+ "path": "/docs/releases/upgrading/upgrading-0.10-0.11.md"
},
{
- "title": "v0.13 to v0.14",
- "path": "/docs/installation/upgrading/upgrading-0.13-0.14.md"
+ "title": "0.10",
+ "path": "/docs/releases/release-notes/release-notes-0.10.md"
},
{
- "title": "v0.12 to v0.13",
- "path": "/docs/installation/upgrading/upgrading-0.12-0.13.md"
+ "title": "Upgrade 0.9 to 0.10",
+ "path": "/docs/releases/upgrading/upgrading-0.9-0.10.md"
},
{
- "title": "v0.11 to v0.12",
- "path": "/docs/installation/upgrading/upgrading-0.11-0.12.md"
+ "title": "0.9",
+ "path": "/docs/releases/release-notes/release-notes-0.9.md"
},
{
- "title": "v0.10 to v0.11",
- "path": "/docs/installation/upgrading/upgrading-0.10-0.11.md"
+ "title": "Upgrade 0.8 to 0.9",
+ "path": "/docs/releases/upgrading/upgrading-0.8-0.9.md"
},
{
- "title": "v0.9 to v0.10",
- "path": "/docs/installation/upgrading/upgrading-0.9-0.10.md"
+ "title": "0.8",
+ "path": "/docs/releases/release-notes/release-notes-0.8.md"
},
{
- "title": "v0.8 to v0.9",
- "path": "/docs/installation/upgrading/upgrading-0.8-0.9.md"
+ "title": "Upgrade 0.7 to 0.8",
+ "path": "/docs/releases/upgrading/upgrading-0.7-0.8.md"
},
{
- "title": "v0.7 to v0.8",
- "path": "/docs/installation/upgrading/upgrading-0.7-0.8.md"
+ "title": "0.7",
+ "path": "/docs/releases/release-notes/release-notes-0.7.md"
},
{
- "title": "v0.6 to v0.7",
- "path": "/docs/installation/upgrading/upgrading-0.6-0.7.md"
+ "title": "Upgrade 0.6 to 0.7",
+ "path": "/docs/releases/upgrading/upgrading-0.6-0.7.md"
},
{
- "title": "v0.5 to v0.6",
- "path": "/docs/installation/upgrading/upgrading-0.5-0.6.md"
+ "title": "0.6",
+ "path": "/docs/releases/release-notes/release-notes-0.6.md"
},
{
- "title": "v0.4 to v0.5",
- "path": "/docs/installation/upgrading/upgrading-0.4-0.5.md"
+ "title": "Upgrade 0.5 to 0.6",
+ "path": "/docs/releases/upgrading/upgrading-0.5-0.6.md"
},
{
- "title": "v0.3 to v0.4",
- "path": "/docs/installation/upgrading/upgrading-0.3-0.4.md"
+ "title": "0.5",
+ "path": "/docs/releases/release-notes/release-notes-0.5.md"
},
{
- "title": "v0.2 to v0.3",
- "path": "/docs/installation/upgrading/upgrading-0.2-0.3.md"
+ "title": "Upgrade 0.4 to 0.5",
+ "path": "/docs/releases/upgrading/upgrading-0.4-0.5.md"
+ },
+ {
+ "title": "0.4",
+ "path": "/docs/releases/release-notes/release-notes-0.4.md"
+ },
+ {
+ "title": "Upgrade 0.3 to 0.4",
+ "path": "/docs/releases/upgrading/upgrading-0.3-0.4.md"
+ },
+ {
+ "title": "0.3",
+ "path": "/docs/releases/release-notes/release-notes-0.3.md"
+ },
+ {
+ "title": "Upgrade 0.2 to 0.3",
+ "path": "/docs/releases/upgrading/upgrading-0.2-0.3.md"
+ },
+ {
+ "title": "0.2",
+ "path": "/docs/releases/release-notes/release-notes-0.2.md"
+ },
+ {
+ "title": "0.1",
+ "path": "/docs/releases/release-notes/release-notes-0.1.md"
}
]
+ }
+ ]
+ },
+ {
+ "title": "0. Installation",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/docs/installation/README.md"
},
{
- "title": "Uninstall",
- "path": "/docs/installation/uninstall.md"
+ "title": "a. kubectl apply",
+ "path": "/docs/installation/kubectl.md"
},
{
- "title": "API compatibility",
- "path": "/docs/installation/api-compatibility.md"
+ "title": "b. Helm",
+ "path": "/docs/installation/helm.md"
},
{
- "title": "Signature Verification",
- "path": "/docs/installation/code-signing.md"
+ "title": "c. OperatorHub (OLM)",
+ "path": "/docs/installation/operator-lifecycle-manager.md"
},
{
- "title": "Best Practice",
- "path": "/docs/installation/best-practice.md"
- }
- ]
- },
- {
- "title": "Configuration",
- "routes": [
+ "title": "d. Continuous Deployment",
+ "path": "/docs/installation/continuous-deployment-and-gitops.md"
+ },
{
- "title": "Introduction",
- "path": "/docs/configuration/README.md"
+ "title": "Configuring Components",
+ "path": "/docs/installation/configuring-components.md"
},
{
- "title": "SelfSigned",
- "path": "/docs/configuration/selfsigned.md"
+ "title": "Upgrade",
+ "path": "/docs/installation/upgrade.md"
},
{
- "title": "CA",
- "path": "/docs/configuration/ca.md"
+ "title": "Reinstall",
+ "path": "/docs/installation/reinstall.md"
},
{
- "title": "Vault",
- "path": "/docs/configuration/vault.md"
+ "title": "Uninstall",
+ "path": "/docs/installation/uninstall.md"
},
{
- "title": "Venafi",
- "path": "/docs/configuration/venafi.md"
+ "title": "Signature Verification",
+ "path": "/docs/installation/code-signing.md"
+ }
+ ]
+ },
+ {
+ "title": "1. Configuring Issuers",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/docs/configuration/README.md"
},
{
- "title": "External",
- "path": "/docs/configuration/external.md"
+ "title": "Issuers",
+ "path": "/docs/configuration/issuers.md"
},
{
- "title": "ACME",
+ "title": "In-tree Issuer Config",
"routes": [
{
- "title": "Introduction",
- "path": "/docs/configuration/acme/README.md"
+ "title": "SelfSigned",
+ "path": "/docs/configuration/selfsigned.md"
},
{
- "title": "HTTP01",
- "routes": [
- {
- "title": "Introduction",
- "path": "/docs/configuration/acme/http01/README.md"
- },
- {
- "title": "External Load Balancer",
- "path": "/docs/configuration/acme/http01/externalloadbalancer.md"
- }
- ]
+ "title": "CA",
+ "path": "/docs/configuration/ca.md"
+ },
+ {
+ "title": "Vault",
+ "path": "/docs/configuration/vault.md"
+ },
+ {
+ "title": "Venafi",
+ "path": "/docs/configuration/venafi.md"
},
{
- "title": "DNS01",
+ "title": "ACME",
"routes": [
{
"title": "Introduction",
- "path": "/docs/configuration/acme/dns01/README.md"
+ "path": "/docs/configuration/acme/README.md"
},
{
- "title": "ACMEDNS",
- "path": "/docs/configuration/acme/dns01/acme-dns.md"
+ "title": "HTTP01",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/docs/configuration/acme/http01/README.md"
+ },
+ {
+ "title": "External Load Balancer",
+ "path": "/docs/configuration/acme/http01/externalloadbalancer.md"
+ }
+ ]
},
{
- "title": "Akamai",
- "path": "/docs/configuration/acme/dns01/akamai.md"
- },
- {
- "title": "AzureDNS",
- "path": "/docs/configuration/acme/dns01/azuredns.md"
- },
- {
- "title": "Cloudflare",
- "path": "/docs/configuration/acme/dns01/cloudflare.md"
- },
- {
- "title": "DigitalOcean",
- "path": "/docs/configuration/acme/dns01/digitalocean.md"
- },
- {
- "title": "Google CloudDNS",
- "path": "/docs/configuration/acme/dns01/google.md"
- },
- {
- "title": "RFC-2136",
- "path": "/docs/configuration/acme/dns01/rfc2136.md"
- },
- {
- "title": "Route53",
- "path": "/docs/configuration/acme/dns01/route53.md"
- },
- {
- "title": "Webhook",
- "path": "/docs/configuration/acme/dns01/webhook.md"
+ "title": "DNS01",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/docs/configuration/acme/dns01/README.md"
+ },
+ {
+ "title": "ACMEDNS",
+ "path": "/docs/configuration/acme/dns01/acme-dns.md"
+ },
+ {
+ "title": "Akamai",
+ "path": "/docs/configuration/acme/dns01/akamai.md"
+ },
+ {
+ "title": "AzureDNS",
+ "path": "/docs/configuration/acme/dns01/azuredns.md"
+ },
+ {
+ "title": "Cloudflare",
+ "path": "/docs/configuration/acme/dns01/cloudflare.md"
+ },
+ {
+ "title": "DigitalOcean",
+ "path": "/docs/configuration/acme/dns01/digitalocean.md"
+ },
+ {
+ "title": "Google CloudDNS",
+ "path": "/docs/configuration/acme/dns01/google.md"
+ },
+ {
+ "title": "RFC-2136",
+ "path": "/docs/configuration/acme/dns01/rfc2136.md"
+ },
+ {
+ "title": "Route53",
+ "path": "/docs/configuration/acme/dns01/route53.md"
+ },
+ {
+ "title": "Webhook",
+ "path": "/docs/configuration/acme/dns01/webhook.md"
+ }
+ ]
}
]
}
@@ -286,81 +413,118 @@
]
},
{
- "title": "Usage",
+ "title": "2. Requesting Certificates",
"routes": [
{
"title": "Introduction",
"path": "/docs/usage/README.md"
},
{
- "title": "Certificate Resources",
+ "title": "Certificate",
"path": "/docs/usage/certificate.md"
},
{
- "title": "Prometheus Metrics",
- "path": "/docs/usage/prometheus-metrics.md"
+ "title": "CertificateRequest",
+ "path": "/docs/usage/certificaterequest.md"
},
{
- "title": "Securing Ingress Resources",
+ "title": "Ingress",
"path": "/docs/usage/ingress.md"
},
{
- "title": "Securing Gateway Resources",
+ "title": "Gateway",
"path": "/docs/usage/gateway.md"
},
{
- "title": "Securing Istio Service Mesh",
- "path": "/docs/usage/istio.md"
- },
- {
- "title": "CSI Driver",
- "path": "/docs/usage/csi.md"
+ "title": "CertificateSigningRequests",
+ "path": "/docs/usage/kube-csr.md"
},
{
- "title": "Kubernetes CertificateSigningRequests",
- "path": "/docs/usage/kube-csr.md"
+ "title": "Service Mesh",
+ "routes": [
+ {
+ "title": "istio-csr",
+ "path": "/docs/usage/istio-csr.md"
+ }
+ ]
},
{
- "title": "Policy for cert-manager certificates",
- "path": "/docs/usage/approver-policy.md"
+ "title": "CSI Driver",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/docs/usage/csi.md"
+ },
+ {
+ "title": "csi-driver",
+ "path": "/docs/usage/csi-driver.md"
+ },
+ {
+ "title": "csi-driver-spiffe",
+ "path": "/docs/usage/csi-driver-spiffe.md"
+ }
+ ]
}
]
},
{
- "title": "Projects",
+ "title": "3. Distributing Trust",
"routes": [
{
- "title": "Contents",
- "path": "/docs/projects/README.md"
- },
- {
- "title": "istio-csr",
- "path": "/docs/projects/istio-csr.md"
+ "title": "Introduction",
+ "path": "/docs/trust/README.md"
},
{
- "title": "csi-driver",
- "path": "/docs/projects/csi-driver.md"
- },
+ "title": "trust-manager",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/docs/trust/trust-manager/README.md"
+ },
+ {
+ "title": "API Reference",
+ "path": "/docs/trust/trust-manager/api-reference.md"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "title": "4. Defining Policy",
+ "routes": [
{
- "title": "csi-driver-spiffe",
- "path": "/docs/projects/csi-driver-spiffe.md"
+ "title": "Introduction",
+ "path": "/docs/policy/README.md"
},
{
- "title": "approver-policy",
- "path": "/docs/projects/approver-policy.md"
+ "title": "Defaulting",
+ "path": "/docs/policy/defaulting.md"
},
{
- "title": "trust-manager",
+ "title": "Approval",
"routes": [
{
"title": "Introduction",
- "path": "/docs/projects/trust-manager/README.md"
+ "path": "/docs/policy/approval/README.md"
},
{
- "title": "API Reference",
- "path": "/docs/projects/trust-manager/api-reference.md"
+ "title": "approver-policy",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/docs/policy/approval/approver-policy/README.md"
+ },
+ {
+ "title": "API Reference",
+ "path": "/docs/policy/approval/approver-policy/api-reference.md"
+ }
+ ]
}
]
+ },
+ {
+ "title": "Issuing",
+ "path": "/docs/policy/issuing.md"
}
]
},
@@ -387,10 +551,6 @@
"title": "Migrating from Kube-LEGO",
"path": "/docs/tutorials/acme/migrating-from-kube-lego.md"
},
- {
- "title": "Backup and Restore Resources",
- "path": "/docs/tutorials/backup.md"
- },
{
"title": "DNS Validation",
"path": "/docs/tutorials/acme/dns-validation.md"
@@ -411,23 +571,52 @@
"title": "Securing the istio Service Mesh using cert-manager",
"path": "/docs/tutorials/istio-csr/istio-csr.md"
},
+ {
+ "title": "Securing Ingresses with ZeroSSL",
+ "path": "/docs/tutorials/zerossl/zerossl.md"
+ },
+ {
+ "title": "Managing public trust in kubernetes with trust-manager",
+ "path": "/docs/tutorials/getting-started-with-trust-manager/README.md"
+ }
+ ]
+ },
+ {
+ "title": "DevOps Tips",
+ "routes": [
+ {
+ "title": "Installing on a Cloud Provider",
+ "path": "/docs/installation/compatibility.md"
+ },
+ {
+ "title": "Prometheus Metrics",
+ "path": "/docs/devops-tips/prometheus-metrics.md"
+ },
+ {
+ "title": "Backup and Restore Resources",
+ "path": "/docs/devops-tips/backup.md"
+ },
{
"title": "Syncing Secrets Across Namespaces",
- "path": "/docs/tutorials/syncing-secrets-across-namespaces.md"
+ "path": "/docs/devops-tips/syncing-secrets-across-namespaces.md"
},
{
- "title": "Securing Ingresses with ZeroSSL",
- "path": "/docs/tutorials/zerossl/zerossl.md"
+ "title": "Best Practice Installation Options",
+ "path": "/docs/installation/best-practice.md"
}
]
},
{
- "title": "Troubleshooting",
+ "title": "Troubleshooting & FAQ",
"routes": [
{
"title": "Introduction",
"path": "/docs/troubleshooting/README.md"
},
+ {
+ "title": "Frequently Asked Questions",
+ "path": "/docs/faq/README.md"
+ },
{
"title": "Troubleshooting ACME / Let's Encrypt Certificates",
"path": "/docs/troubleshooting/acme.md"
@@ -438,10 +627,6 @@
}
]
},
- {
- "title": "FAQ",
- "path": "/docs/faq/README.md"
- },
{
"title": "Contributing",
"routes": [
@@ -449,6 +634,10 @@
"title": "Introduction",
"path": "/docs/contributing/README.md"
},
+ {
+ "title": "Projects",
+ "path": "/docs/contributing/projects.md"
+ },
{
"title": "Feature Policy",
"path": "/docs/contributing/policy.md"
@@ -490,7 +679,7 @@
"path": "/docs/contributing/kind.md"
},
{
- "title": "Implementing Feature Gates",
+ "title": "Feature gates",
"path": "/docs/contributing/featuregates.md"
},
{
@@ -532,166 +721,12 @@
"path": "/docs/contributing/signing-keys.md"
},
{
- "title": "Importing cert-manager in Go",
- "path": "/docs/contributing/importing.md"
- }
- ]
- },
- {
- "title": "Release Notes",
- "routes": [
- {
- "title": "Introduction",
- "path": "/docs/release-notes/README.md"
- },
- {
- "title": "v1.12",
- "path": "/docs/release-notes/release-notes-1.12.md"
- },
- {
- "title": "v1.11",
- "path": "/docs/release-notes/release-notes-1.11.md"
- },
- {
- "title": "v1.10",
- "path": "/docs/release-notes/release-notes-1.10.md"
- },
- {
- "title": "v1.9",
- "path": "/docs/release-notes/release-notes-1.9.md"
- },
- {
- "title": "v1.8",
- "path": "/docs/release-notes/release-notes-1.8.md"
- },
- {
- "title": "v1.7",
- "path": "/docs/release-notes/release-notes-1.7.md"
- },
- {
- "title": "v1.6",
- "path": "/docs/release-notes/release-notes-1.6.md"
- },
- {
- "title": "v1.5",
- "path": "/docs/release-notes/release-notes-1.5.md"
- },
- {
- "title": "v1.4",
- "path": "/docs/release-notes/release-notes-1.4.md"
- },
- {
- "title": "v1.3",
- "path": "/docs/release-notes/release-notes-1.3.md"
- },
- {
- "title": "v1.2",
- "path": "/docs/release-notes/release-notes-1.2.md"
- },
- {
- "title": "v1.1",
- "path": "/docs/release-notes/release-notes-1.1.md"
- },
- {
- "title": "v1.0",
- "path": "/docs/release-notes/release-notes-1.0.md"
- },
- {
- "title": "v0.16",
- "path": "/docs/release-notes/release-notes-0.16.md"
- },
- {
- "title": "v0.15",
- "path": "/docs/release-notes/release-notes-0.15.md"
- },
- {
- "title": "v0.14",
- "path": "/docs/release-notes/release-notes-0.14.md"
- },
- {
- "title": "v0.13",
- "path": "/docs/release-notes/release-notes-0.13.md"
- },
- {
- "title": "v0.12",
- "path": "/docs/release-notes/release-notes-0.12.md"
- },
- {
- "title": "v0.11",
- "path": "/docs/release-notes/release-notes-0.11.md"
- },
- {
- "title": "v0.10",
- "path": "/docs/release-notes/release-notes-0.10.md"
- },
- {
- "title": "v0.9",
- "path": "/docs/release-notes/release-notes-0.9.md"
- },
- {
- "title": "v0.8",
- "path": "/docs/release-notes/release-notes-0.8.md"
- },
- {
- "title": "v0.7",
- "path": "/docs/release-notes/release-notes-0.7.md"
- },
- {
- "title": "v0.6",
- "path": "/docs/release-notes/release-notes-0.6.md"
- },
- {
- "title": "v0.5",
- "path": "/docs/release-notes/release-notes-0.5.md"
- },
- {
- "title": "v0.4",
- "path": "/docs/release-notes/release-notes-0.4.md"
- },
- {
- "title": "v0.3",
- "path": "/docs/release-notes/release-notes-0.3.md"
- },
- {
- "title": "v0.2",
- "path": "/docs/release-notes/release-notes-0.2.md"
- },
- {
- "title": "v0.1",
- "path": "/docs/release-notes/release-notes-0.1.md"
- }
- ]
- },
- {
- "title": "Concepts",
- "routes": [
- {
- "title": "Introduction",
- "path": "/docs/concepts/README.md"
- },
- {
- "title": "Issuer",
- "path": "/docs/concepts/issuer.md"
- },
- {
- "title": "Certificate",
- "path": "/docs/concepts/certificate.md"
- },
- {
- "title": "CertificateRequest",
- "path": "/docs/concepts/certificaterequest.md"
- },
- {
- "title": "ACME Orders and Challenges",
- "path": "/docs/concepts/acme-orders-challenges.md"
- },
- {
- "title": "Webhook",
- "path": "/docs/concepts/webhook.md"
+ "title": "API compatibility",
+ "path": "/docs/contributing/api-compatibility.md"
},
{
- "title": "CA Injector",
- "path": "/docs/concepts/ca-injector.md"
+ "title": "Importing cert-manager in Go",
+ "path": "/docs/contributing/importing.md"
}
]
},
@@ -743,6 +778,32 @@
{
"title": "API Reference",
"path": "/docs/reference/api-docs.md"
+ },
+
+ {
+ "title": "Concepts",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/docs/concepts/README.md"
+ },
+ {
+ "title": "Issuer",
+ "path": "/docs/concepts/issuer.md"
+ },
+ {
+ "title": "ACME Orders and Challenges",
+ "path": "/docs/concepts/acme-orders-challenges.md"
+ },
+ {
+ "title": "Webhook",
+ "path": "/docs/concepts/webhook.md"
+ },
+ {
+ "title": "CA Injector",
+ "path": "/docs/concepts/ca-injector.md"
+ }
+ ]
}
]
}
diff --git a/content/docs/policy/README.md b/content/docs/policy/README.md
new file mode 100644
index 0000000000..c9529fdfbb
--- /dev/null
+++ b/content/docs/policy/README.md
@@ -0,0 +1,20 @@
+---
+title: Policy
+description: 'Rules for guiding certificate self-service.'
+---
+
+![issuance flow: policy](/images/issuance-flow-policy.png)
+
+To scale certificate management, it is critical to distribute the responsibility of
+managing certificates to the teams that need them. To do this effectively, often a
+self-service model is used, teams are considered "customers" of a platform team that
+provides the Kubernetes infrastructure (including certificate management). This multi-tenant
+model removes the bottleneck of a single team managing certificates for everyone.
+
+However, to be successful, the platform team should guide its customers to follow best
+practices, and ensure that certificates are issued in a secure and consistent way. These
+best practices and rules are what we call "policy". Currently, cert-manager distinguishes
+between three types of policy:
+- [Defaulting Policy](defaulting.md): Defining defaults for Certificate properties.
+- [Approval Policy](approval): Restricting who can request which certificates.
+- [Issuing Policy](issuing.md): Configuring how requests are mapped to Certificates.
diff --git a/content/docs/policy/approval/README.md b/content/docs/policy/approval/README.md
new file mode 100644
index 0000000000..9374fbb374
--- /dev/null
+++ b/content/docs/policy/approval/README.md
@@ -0,0 +1,36 @@
+---
+title: Approval Policy
+description: 'Restricting who can request which certificates.'
+---
+
+![issuance flow: policy](/images/issuance-flow-policy.png)
+
+In the issuance flow, there are typically two places where non-conforming certificate
+requests can be rejected: before sending the X.509 Certificate Signing Request (CSR) to the
+issuer, and after receiving the X.509 Certificate by the issuer. In the first case,
+it is cert-manager that rejects the request. In the second case, it is the issuer
+that rejects the request.
+
+## Rejecting requests before sending the X.509 Certificate Signing Request (CSR) to the issuer
+
+cert-manager requires that a [CertificateRequest](../../usage/certificaterequest.md)
+is approved before it is sent to the issuer. Also, CertificateSigningRequests must
+be approved before they are sent to the issuer. This approval is done by adding an
+[approval condition](../../usage/certificaterequest.md#approval) to the resource.
+
+In a default installation, cert-manager automatically approves all CertificateRequests
+and CertificateSigningRequests that use any of its built-in issuers. This is done to
+simplify the first-time experience of using cert-manager. However, this is not
+recommended for production environments. Instead, you should configure a more strict
+auto-approver that limits who can request which certificates. [approver-policy](approver-policy)
+is an example of such an auto-approver.
+
+## Rejecting requests after receiving the X.509 Certificate Signing Request (CSR) by the issuer
+
+After receiving the X.509 Certificate Signing Request (CSR), the logic to reject requests
+is up to the issuer. cert-manager supports a large number of issuers, each issuer
+has full autonomy over what requests are rejected and what error messages are returned.
+Additionally, an issuer could also choose accept all requests and instead
+override the non-conforming properties in the CSR. More generally,
+the issuer is free to use any logic to map the properties in the X.509 Certificate Signing Request (CSR)
+to the properties in the X.509 Certificate (see [Issuing Policy](../issuing.md).
diff --git a/content/docs/projects/approver-policy.md b/content/docs/policy/approval/approver-policy/README.md
similarity index 70%
rename from content/docs/projects/approver-policy.md
rename to content/docs/policy/approval/approver-policy/README.md
index 4b991df08f..f026e0f01b 100644
--- a/content/docs/projects/approver-policy.md
+++ b/content/docs/policy/approval/approver-policy/README.md
@@ -1,45 +1,77 @@
---
title: approver-policy
-description: ''
+description: 'Policy plugin for cert-manager'
---
approver-policy is a cert-manager
-[approver](../concepts/certificaterequest.md#approval)
-that will approve or deny CertificateRequests based on CRD defined policies.
+[approver](../../../usage/certificaterequest.md#approval)
+that will approve or deny CertificateRequests based on policies defined in
+the `CertificateRequestPolicy` custom resource.
----
+## Prerequisites
-## Installation
+[cert-manager must be installed](../../../installation/README.md), and
+the [the default approver in cert-manager must be disabled](../../../usage/certificaterequest.md#approver-controller).
-[cert-manager](../installation/README.md) is required to be installed with approver-policy.
+> ⚠️ If the default approver is not disabled in cert-manager, approver-policy will
+> race with cert-manager and policy will be ineffective.
-> ⚠️
->
-> It is important that the
-> [default approver is disabled in cert-manager](../concepts/certificaterequest.md#approver-controller).
-> If the default approver is not disabled in cert-manager, approver-policy will
-> race with cert-manager and thus policy becomes useless.
+If you install cert-manager using `helm install` or `helm upgrade`,
+you can disable the default approver by [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing) using the `--set` or `--values` command line flags:
+
+```
+# Example --set value
+--set extraArgs={--controllers='*\,-certificaterequests-approver'} # ⚠ Disable cert-manager's built-in approver
+```
+
+```yaml
+# Example --values file content
+extraArgs:
+ - "--controllers=*,-certificaterequests-approver" # ⚠ Disable cert-manager's built-in approver
+```
+
+Here's a full example which will install cert-manager or reconfigure it if it is already installed:
+
+```terminal
+helm upgrade cert-manager jetstack/cert-manager \
+ --install \
+ --create-namespace \
+ --namespace cert-manager \
+ --version REPLACE-WITH-YOUR-CERT-MANAGER-VERSION \
+ --set installCRDs=true \
+ --set extraArgs={--controllers='*\,-certificaterequests-approver'} # ⚠ Disable cert-manager's built-in approver
+```
+
+> ℹ️ The `--set installCRDs=true` setting is a convenient way to install the
+> cert-manager CRDS, but it is optional and has some drawbacks.
+> Read [Helm: Installing Custom Resource Definitions](https://deploy-preview-1216--cert-manager-website.netlify.app/docs/installation/helm/#3-install-customresourcedefinitions) to learn more.
>
-> ```terminal
-> $ helm upgrade -i -n cert-manager cert-manager jetstack/cert-manager --set extraArgs={--controllers='*\,-certificaterequests-approver'} --set installCRDs=true --create-namespace
-> ```
+> ℹ️ Be sure to customize the cert-manager controller `extraArgs`,
+> which are at the top level of the values file.
+> *Do not* change the `webhook.extraArgs`, `startupAPICheck.extraArgs` or `cainjector.extraArgs` settings.
>
-> ⚠️
+> ⚠️ If you are reconfiguring an already installed cert-manager,
+> check whether the original installation already customized the `extraArgs` value
+> by running `helm get values cert-manager --namespace cert-manager`.
+> If there are already `extraArgs` values, merge those with the extra `--controllers` value.
+> Otherwise your original `extraArgs` values will be overwritten.
+
+## Installation
To install approver-policy:
```terminal
-$ helm repo add jetstack https://charts.jetstack.io --force-update
-$ helm upgrade -i -n cert-manager cert-manager-approver-policy jetstack/cert-manager-approver-policy --wait
+helm repo add jetstack https://charts.jetstack.io --force-update
+helm upgrade -i -n cert-manager cert-manager-approver-policy jetstack/cert-manager-approver-policy --wait
```
If you are using approver-policy with [external
-issuers](../configuration/external.md), you _must_
+issuers](../../../configuration/issuers.md), you _must_
include their signer names so that approver-policy has permissions to approve
and deny CertificateRequests that
-[reference them](../concepts/certificaterequest.md#rbac-syntax).
+[reference them](../../../usage/certificaterequest.md#rbac-syntax).
For example, if using approver-policy for the internal issuer types, along with
-[google-ca-issuer](https://github.com/jetstack/google-cas-issuer), and
+[google-cas-issuer](https://github.com/jetstack/google-cas-issuer), and
[aws-privateca-issuer](https://github.com/cert-manager/aws-privateca-issuer),
set the following values when installing:
@@ -52,8 +84,6 @@ awspcaclusterissuers.awspca.cert-manager.io/*,awspcaissuers.awspca.cert-manager.
}"
```
----
-
## Configuration
> Example policy resources can be found
@@ -72,6 +102,13 @@ selector.
least one policy is appropriate for the request but none of those permit the
request, the request is denied.**
+A denied CertificateRequest is considered to be permanently failed. If it was
+created for a Certificate resource, the issuance will be retried with
+[exponential backoff](../../../faq/README.md#what-happens-if-issuance-fails-will-it-be-retried)
+like all other permanent issuance failures. A CertificateRequest that is neither
+approved nor denied (because no matching policy was found) will not be further
+processed by cert-manager until it gets either approved or denied.
+
CertificateRequestPolicies are cluster scoped resources that can be thought of
as "policy profiles". They describe any request that is approved by that
policy. Policies are bound to Kubernetes users and ServiceAccounts using RBAC.
@@ -124,8 +161,6 @@ subjects:
apiGroup: rbac.authorization.k8s.io
```
----
-
## Behavior
CertificateRequestPolicy are split into 4 parts; `allowed`, `contraints`,
@@ -296,7 +331,7 @@ spec:
...
selector:
issuerRef:
- - name: "my-ca"
+ name: "my-ca"
kind: "*Issuer"
group: "cert-manager.io"
```
@@ -365,7 +400,7 @@ time. Plugins are designed to be used as extensions to the existing policy
checks where the user requires special functionality that the existing checks
can't provide.
-Plugins are defined as a block on the CertificateRequestPolicy Spec.
+Plugins are defined as a block on the CertificateRequestPolicy `spec`.
```yaml
apiVersion: policy.cert-manager.io/v1alpha1
@@ -380,4 +415,17 @@ spec:
val-1: key-1
```
-There are currently no none open source plugins.
+## Known Plugins from the Community
+
+- [CEL approver-policy plugin](https://github.com/erikgb/cel-approver-policy-plugin) (experimental)
+
+If you want to implement an external approver policy plugin take a look at the
+example implementation at
+https://github.com/cert-manager/example-approver-policy-plugin.
+
+Have you implemented a plugin for approver-policy? Feel free to add a link to your plugin from this page by
+opening a pull request in the [cert-manager website project](https://github.com/cert-manager/website).
+
+## API Reference
+
+> 📖 Read the [approver-policy API reference](api-reference.md).
diff --git a/content/docs/policy/approval/approver-policy/api-reference.md b/content/docs/policy/approval/approver-policy/api-reference.md
new file mode 100644
index 0000000000..e4d45bb829
--- /dev/null
+++ b/content/docs/policy/approval/approver-policy/api-reference.md
@@ -0,0 +1,978 @@
+---
+title: approver-policy API Reference
+description: "approver-policy API documentation"
+---
+
+Packages:
+
+- [`policy.cert-manager.io/v1alpha1`](#policycert-manageriov1alpha1)
+
+# `policy.cert-manager.io/v1alpha1`
+
+Resource Types:
+
+
+- [CertificateRequestPolicy](#certificaterequestpolicy)
+
+
+
+
+## `CertificateRequestPolicy`
+
+
+
+
+
+CertificateRequestPolicy is an object for describing a "policy profile" that makes decisions on whether applicable CertificateRequests should be approved or denied.
+
+
+ Selector is used for selecting over which CertificateRequests this CertificateRequestPolicy is appropriate for and so will used for its approval evaluation.
+
+ Allowed is the set of attributes that are "allowed" by this policy. A CertificateRequest will only be considered permissible for this policy if the CertificateRequest has the same or less as what is allowed. Empty or `nil` allowed fields mean CertificateRequests are not allowed to have that field present to be permissible.
+
+ Constraints is the set of attributes that _must_ be satisfied by the CertificateRequest for the request to be permissible by the policy. Empty or `nil` constraint fields mean CertificateRequests satisfy that field with any value of their corresponding attribute.
+
+ Plugins define a set of plugins and their configuration that should be executed when this policy is evaluated against a CertificateRequest. A plugin must already be built within approver-policy for it to be available.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.selector`
+
+
+Selector is used for selecting over which CertificateRequests this CertificateRequestPolicy is appropriate for and so will used for its approval evaluation.
+
+
+ IssuerRef is used to match this CertificateRequestPolicy against processed CertificateRequests. This policy will only be evaluated against a CertificateRequest whose `spec.issuerRef` field matches `spec.selector.issuerRef`. CertificateRequests will not be processed on unmatched `issuerRef` if defined, regardless of whether the requestor is bound by RBAC. Accepts wildcards "*". Omitted values are equivalent to "*".
+ The following value will match _all_ `issuerRefs`: ``` issuerRef: {} ```
+
+ Namespace is used to select on Namespaces, meaning the CertificateRequestPolicy will only match on CertificateRequests that have been created in matching selected Namespaces. If this field is omitted, all Namespaces are selected.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.selector.issuerRef`
+
+
+IssuerRef is used to match this CertificateRequestPolicy against processed CertificateRequests. This policy will only be evaluated against a CertificateRequest whose `spec.issuerRef` field matches `spec.selector.issuerRef`. CertificateRequests will not be processed on unmatched `issuerRef` if defined, regardless of whether the requestor is bound by RBAC. Accepts wildcards "*". Omitted values are equivalent to "*".
+ The following value will match _all_ `issuerRefs`: ``` issuerRef: {} ```
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
group
+
string
+
+ Group is the wildcard selector to match the `spec.issuerRef.group` field on requests. Accepts wildcards "*". An omitted field or value of `nil` matches all.
+
+
false
+
+
kind
+
string
+
+ Kind is the wildcard selector to match the `spec.issuerRef.kind` field on requests. Accepts wildcards "*". An omitted field or value of `nil` matches all.
+
+
false
+
+
name
+
string
+
+ Name is the wildcard selector to match the `spec.issuerRef.name` field on requests. Accepts wildcards "*". An omitted field or value of `nil` matches all.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.selector.namespace`
+
+
+Namespace is used to select on Namespaces, meaning the CertificateRequestPolicy will only match on CertificateRequests that have been created in matching selected Namespaces. If this field is omitted, all Namespaces are selected.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
matchLabels
+
map[string]string
+
+ MatchLabels is the set of Namespace labels that select on CertificateRequests which have been created in a Namespace matching the selector.
+
+
false
+
+
matchNames
+
[]string
+
+ MatchNames are the set of Namespace names that select on CertificateRequests that have been created in a matching Namespace. Accepts wildcards "*".
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed`
+
+
+Allowed is the set of attributes that are "allowed" by this policy. A CertificateRequest will only be considered permissible for this policy if the CertificateRequest has the same or less as what is allowed. Empty or `nil` allowed fields mean CertificateRequests are not allowed to have that field present to be permissible.
+
+
+ IPAddresses defines the X.509 IP SANs that may be requested for.
+
+
false
+
+
isCA
+
boolean
+
+ IsCA defines whether it is permissible for a CertificateRequest to have the `spec.IsCA` field set to `true`. An omitted field, value of `nil` or `false`, forbids the `spec.IsCA` field from bring `true`. A value of `true` permits CertificateRequests setting the `spec.IsCA` field to `true`.
+
+ URIs defines the X.509 URI SANs that may be requested for.
+
+
false
+
+
usages
+
[]enum
+
+ Usages defines the list of permissible key usages that may appear on the CertificateRequest `spec.keyUsages` field. An omitted field or value of `nil` forbids any Usages being requested. An empty slice `[]` is equivalent to `nil`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.commonName`
+
+
+CommonName defines the X.509 Common Name that is permissible.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Value is also defined.
+
+
false
+
+
value
+
string
+
+ Value defines the value that is permissible to be present on the request. Accepts wildcards "*". An omitted field or value of `nil` forbids the value from being requested. An empty string is equivalent to `nil`, however an empty string pared with Required as `true` is an impossible condition that always denies. Value may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.dnsNames`
+
+
+DNSNames defines the X.509 DNS SANs that may be requested for. Accepts wildcards "*".
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.emailAddresses`
+
+
+EmailAddresses defines the X.509 Email SANs that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.ipAddresses`
+
+
+IPAddresses defines the X.509 IP SANs that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.subject`
+
+
+Subject defines the X.509 subject that is permissible. An omitted field or value of `nil` forbids any Subject being requested.
+
+
+ StreetAddresses defines the X.509 Subject Street Addresses that may be requested for.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.subject.countries`
+
+
+Countries define the X.509 Subject Countries that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.subject.localities`
+
+
+Localities defines the X.509 Subject Localities that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.subject.organizationalUnits`
+
+
+OrganizationalUnits defines the X.509 Subject Organizational Units that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.subject.organizations`
+
+
+Organizations define the X.509 Subject Organizations that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.subject.postalCodes`
+
+
+PostalCodes defines the X.509 Subject Postal Codes that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.subject.provinces`
+
+
+Provinces defines the X.509 Subject Provinces that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.subject.serialNumber`
+
+
+SerialNumber defines the X.509 Subject Serial Number that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Value is also defined.
+
+
false
+
+
value
+
string
+
+ Value defines the value that is permissible to be present on the request. Accepts wildcards "*". An omitted field or value of `nil` forbids the value from being requested. An empty string is equivalent to `nil`, however an empty string pared with Required as `true` is an impossible condition that always denies. Value may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.subject.streetAddresses`
+
+
+StreetAddresses defines the X.509 Subject Street Addresses that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.allowed.uris`
+
+
+URIs defines the X.509 URI SANs that may be requested for.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
required
+
boolean
+
+ Required marks this field as being a required value on the request. May only be set to true if Values is also defined. Default is nil which marks the field as not required.
+
+
false
+
+
values
+
[]string
+
+ Defines the values that are permissible to be present on request. Accepts wildcards "*". An omitted field or value of `nil` forbids any value on the related field in the request from being requested. An empty slice `[]` is equivalent to `nil`, however an empty slice pared with Required `true` is an impossible condition that always denies. Values may not be `nil` if Required is `true`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.constraints`
+
+
+Constraints is the set of attributes that _must_ be satisfied by the CertificateRequest for the request to be permissible by the policy. Empty or `nil` constraint fields mean CertificateRequests satisfy that field with any value of their corresponding attribute.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
maxDuration
+
string
+
+ MaxDuration defines the maximum duration a certificate may be requested for. Values are inclusive (i.e. a max value of `1h` will accept a duration of `1h`). MaxDuration and MinDuration may be the same value. An omitted field or value of `nil` permits any maximum duration. If MaxDuration is defined, a duration _must_ be requested on the CertificateRequest.
+
+
false
+
+
minDuration
+
string
+
+ MinDuration defines the minimum duration a certificate may be requested for. Values are inclusive (i.e. a min value of `1h` will accept a duration of `1h`). MinDuration and MaxDuration may be the same value. An omitted field or value of `nil` permits any minimum duration. If MinDuration is defined, a duration _must_ be requested on the CertificateRequest.
+
+ PrivateKey defines the shape of permissible private keys that may be used for the request with this policy. An omitted field or value of `nil` permits the use of any private key by the requestor.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.constraints.privateKey`
+
+
+PrivateKey defines the shape of permissible private keys that may be used for the request with this policy. An omitted field or value of `nil` permits the use of any private key by the requestor.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
algorithm
+
enum
+
+ Algorithm defines the allowed crypto algorithm that is used by the requestor for their private key in their request. An omitted field or value of `nil` permits any Algorithm.
+
+ Enum: RSA, ECDSA, Ed25519
+
+
false
+
+
maxSize
+
integer
+
+ MaxSize defines the maximum key size a requestor may use for their private key. Values are inclusive (i.e. a min value of `2048` will accept a size of `2048`). MaxSize and MinSize may be the same value. An omitted field or value of `nil` permits any maximum size.
+
+
false
+
+
minSize
+
integer
+
+ MinSize defines the minimum key size a requestor may use for their private key. Values are inclusive (i.e. a min value of `2048` will accept a size of `2048`). MinSize and MaxSize may be the same value. An omitted field or value of `nil` permits any minimum size.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.spec.plugins[key]`
+
+
+CertificateRequestPolicyPluginData is configuration needed by the plugin approver to evaluate a CertificateRequest on this policy.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
values
+
map[string]string
+
+ Values define a set of well-known, to the plugin, key value pairs that are required for the plugin to successfully evaluate a request based on this policy.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.status`
+
+
+CertificateRequestPolicyStatus defines the observed state of the CertificateRequestPolicy.
+
+
+ List of status conditions to indicate the status of the CertificateRequestPolicy. Known condition types are `Ready`.
+
+
false
+
+
+
+
+### `CertificateRequestPolicy.status.conditions[index]`
+
+
+CertificateRequestPolicyCondition contains condition information for a CertificateRequestPolicyStatus.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
status
+
string
+
+ Status of the condition, one of ('True', 'False', 'Unknown').
+
+
true
+
+
type
+
string
+
+ Type of the condition, known values are (`Ready`).
+
+
true
+
+
lastTransitionTime
+
string
+
+ LastTransitionTime is the timestamp corresponding to the last status change of this condition.
+
+ Format: date-time
+
+
false
+
+
message
+
string
+
+ Message is a human readable description of the details of the last transition, complementing reason.
+
+
false
+
+
observedGeneration
+
integer
+
+ If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the CertificateRequestPolicy.
+
+ Format: int64
+
+
false
+
+
reason
+
string
+
+ Reason is a brief machine readable explanation for the condition's last transition.
+
+
false
+
+
diff --git a/content/docs/policy/defaulting.md b/content/docs/policy/defaulting.md
new file mode 100644
index 0000000000..ee885aa9d4
--- /dev/null
+++ b/content/docs/policy/defaulting.md
@@ -0,0 +1,41 @@
+---
+title: Defaulting Policy
+description: 'Defining defaults for Certificate properties.'
+---
+
+![issuance flow: policy](/images/issuance-flow-policy.png)
+
+In the issuance flow, there are two places where defaults can be applied: before the X.509
+CertificateSigningRequest is created, and before the X.509 Certificate is created. In
+the first case, it is cert-manager that applies the defaults. In the second case, it is the
+issuer that applies the defaults.
+
+An important difference between these two cases is that in the first case, there are more
+properties that can be defaulted. For example, since the private key still has to be generated,
+all the properties of the private key can be defaulted. In the second case, the private key
+has already been generated. Also, the issuer reference itself can be defaulted in the first
+case, but not in the second case. For example, in a specific namespace, the issuer can be
+defaulted to a specific issuer.
+
+Defaulting is done to simplify the experience of the person requesting the certificate. It
+does not prevent the person from overriding the defaults. Therefore, an approval policy can
+be used (see [Approval Policy](approval) for more details).
+
+## Defaults applied by cert-manager: before creating the X.509 Certificate Signing Request (CSR)
+
+To apply defaults before the X.509 Certificate Signing Request (CSR) is created, defaults must be
+applied to the inputs used to create the CSR. After the CSR is created, it cannot be modified without
+invalidating the its signature. This means that defaults cannot be applied to any of the properties of
+the CSR included in the CertificateRequest or CertificateSigningRequest resource.
+
+Instead, defaults must be applied to the Certificate resource that is used to create the CertificateSigningRequest.
+When using a CSI driver, defaults must be applied to CSI annotations or CSI driver configuration.
+To dynamically apply defaults to these resources, you can use tools like [`kyverno`](https://kyverno.io/).
+CI/CD tools like Helm, kustomize, ... can also be used to template and apply defaults to these resources.
+
+## Defaults applied by the issuer: before creating the X.509 Certificate
+
+Before creating the X.509 Certificate, the issuer can use default values for properties in
+the resulting certificate. More generally, the issuer is free to use any logic to map the
+properties in the X.509 Certificate Signing Request (CSR) to the properties in the X.509 Certificate
+(see [Issuing Policy](issuing.md) for more details).
diff --git a/content/docs/policy/issuing.md b/content/docs/policy/issuing.md
new file mode 100644
index 0000000000..b573a5b1a7
--- /dev/null
+++ b/content/docs/policy/issuing.md
@@ -0,0 +1,21 @@
+---
+title: Issuing Policy
+description: 'Configuring how requests are mapped to Certificates.'
+---
+
+![issuance flow: policy](/images/issuance-flow-policy.png)
+
+cert-manager integrates with a large number of different certificate issuers, each
+issuer has full autonomy over what issued certificates look like and what properties
+they have. cert-manager does not require or enforce any specific relationship between
+the properties in a CertificateRequest/ CertificateSigningRequest and the properties
+in the issued certificate (except for the public key which must match).
+
+For the core [SelfSigned](../configuration/selfsigned.md) and [CA](../configuration/ca.md) issuers,
+cert-manager implements its own issuing policy. This policy is very simple and is not configurable.
+All the requested properties will be copied into the issued certificate.
+
+Another example is the [Let's Encrypt CA issuer](https://letsencrypt.org/) which also implements its own issuing policy. This policy is more complex than a 1:1
+copy of the requested properties. For example, the Let's Encrypt issuer will always
+[issue certificates with a 90 day validity period](https://letsencrypt.org/2015/11/09/why-90-days).
+Also, it only supports a [limited set of (extended) key usages](https://community.letsencrypt.org/t/custom-extendedkeyusage-stripped-from-csr-while-generating-cert/17759/2).
\ No newline at end of file
diff --git a/content/docs/reference/api-docs.md b/content/docs/reference/api-docs.md
index 4943e086a6..b3d73a0e55 100644
--- a/content/docs/reference/api-docs.md
+++ b/content/docs/reference/api-docs.md
@@ -13,6 +13,9 @@ description: >-
The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources.
+
The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of class, name or ingressClassName may be specified.
@@ -1893,6 +1896,17 @@ description: >-
LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer
+
+
+ lastPrivateKeyHash
+
+ string
+
+
+ (Optional)
+
LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer
+
+
AzureDNSEnvironment (string alias)
@@ -2508,7 +2522,7 @@ description: >-
Certificate
-
A Certificate resource should be created to ensure an up to date and signed x509 certificate is stored in the Kubernetes Secret resource named in spec.secretName.
+
A Certificate resource should be created to ensure an up to date and signed X.509 certificate is stored in the Kubernetes Secret resource named in spec.secretName.
The stored certificate will be renewed before it expires (as configured by spec.renewBefore).
The common name attribute is specified separately in the commonName field. Cannot be set if the literalSubject field is set.
@@ -2586,7 +2607,8 @@ description: >-
(Optional)
-
LiteralSubject is an LDAP formatted string that represents the X.509 Subject field. Use this instead of the Subject field if you need to ensure the correct ordering of the RDN sequence, such as when issuing certs for LDAP authentication. See https://github.com/cert-manager/cert-manager/issues/3203, https://github.com/cert-manager/cert-manager/issues/4424. This field is alpha level and is only supported by cert-manager installations where LiteralCertificateSubject feature gate is enabled on both cert-manager controller and webhook.
Cannot be set if the subject or commonName field is set. This is an Alpha Feature and is only enabled with the --feature-gates=LiteralCertificateSubject=true option set on both the controller and webhook components.
@@ -2597,7 +2619,8 @@ description: >-
(Optional)
-
CommonName is a common name to be used on the Certificate. The CommonName should have a length of 64 characters or fewer to avoid generating invalid CSRs. This value is ignored by TLS clients when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4
Should have a length of 64 characters or fewer to avoid generating invalid CSRs. Cannot be set if the literalSubject field is set.
@@ -2610,7 +2633,8 @@ description: >-
(Optional)
-
The requested ‘duration’ (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types. If unset this defaults to 90 days. Certificate will be renewed either 2⁄3 through its duration or renewBefore period before its expiry, whichever is later. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration
+
Requested ‘duration’ (i.e. lifetime) of the Certificate. Note that the issuer may choose to ignore the requested duration, just like any other requested attribute.
+
If unset, this defaults to 90 days. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration.
@@ -2623,10 +2647,9 @@ description: >-
(Optional)
-
- How long before the currently issued certificate’s expiry cert-manager should renew the certificate. The default is 2⁄3 of the issued certificate’s duration. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration
- https://golang.org/pkg/time/#ParseDuration
-
+
How long before the currently issued certificate’s expiry cert-manager should renew the certificate. For example, if a certificate is valid for 60 minutes, and renewBefore=10m, cert-manager will begin to attempt to renew the certificate 50 minutes after it was issued (i.e. when there are 10 minutes remaining until the certificate is no longer valid).
+
NOTE: The actual lifetime of the issued certificate is used to determine the renewal time. If an issuer returns a certificate with a different lifetime than the one requested, cert-manager will use the lifetime of the issued certificate.
+
If unset, this defaults to 1⁄3 of the issued certificate’s lifetime. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration.
@@ -2637,7 +2660,7 @@ description: >-
(Optional)
-
DNSNames is a list of DNS subjectAltNames to be set on the Certificate.
+
Requested DNS subject alternative names.
@@ -2648,7 +2671,7 @@ description: >-
(Optional)
-
IPAddresses is a list of IP address subjectAltNames to be set on the Certificate.
+
Requested IP address subject alternative names.
@@ -2659,7 +2682,7 @@ description: >-
(Optional)
-
URIs is a list of URI subjectAltNames to be set on the Certificate.
+
Requested URI subject alternative names.
@@ -2670,7 +2693,7 @@ description: >-
(Optional)
-
EmailAddresses is a list of email subjectAltNames to be set on the Certificate.
+
Requested email subject alternative names.
@@ -2680,7 +2703,7 @@ description: >-
string
-
SecretName is the name of the secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer.
+
Name of the Secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer. The Secret resource lives in the same namespace as the Certificate resource.
@@ -2693,7 +2716,7 @@ description: >-
(Optional)
-
SecretTemplate defines annotations and labels to be copied to the Certificate’s Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate’s Secret.
+
Defines annotations and labels to be copied to the Certificate’s Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate’s Secret.
@@ -2706,10 +2729,7 @@ description: >-
(Optional)
-
- Keystores configures additional keystore output formats stored in the
- secretName Secret resource.
-
+
Additional keystore output formats to be stored in the Certificate’s Secret.
@@ -2721,7 +2741,8 @@ description: >-
-
IssuerRef is a reference to the issuer for this certificate. If the kind field is not set, or set to Issuer, an Issuer resource with the given name in the same namespace as the Certificate will be used. If the kind field is set to ClusterIssuer, a ClusterIssuer with the provided name will be used. The name field in this stanza is required at all times.
+
Reference to the issuer responsible for issuing the certificate. If the issuer is namespace-scoped, it must be in the same namespace as the Certificate. If the issuer is cluster-scoped, it can be used from any namespace.
+
The name field of the reference must always be specified.
@@ -2732,7 +2753,8 @@ description: >-
(Optional)
-
IsCA will mark this Certificate as valid for certificate signing. This will automatically add the cert sign usage to the list of usages.
+
Requested basic constraints isCA value. The isCA value is used to set the isCA field on the created CertificateRequest resources. Note that the issuer may choose to ignore the requested isCA value, just like any other requested attribute.
+
If true, this will automatically add the cert sign usage to the list of requested usages.
@@ -2745,7 +2767,8 @@ description: >-
(Optional)
-
Usages is the set of x509 usages that are requested for the certificate. Defaults to digital signature and key encipherment if not specified.
+
Requested key usages and extended key usages. These usages are used to set the usages field on the created CertificateRequest resources. If encodeUsagesInRequest is unset or set to true, the usages will additionally be encoded in the request field which contains the CSR blob.
+
If unset, defaults to digital signature and key encipherment.
@@ -2758,7 +2781,7 @@ description: >-
(Optional)
-
Options to control private keys used for the Certificate.
+
Private key options. These include the key algorithm and size, the used encoding and the rotation policy.
@@ -2769,7 +2792,8 @@ description: >-
(Optional)
-
EncodeUsagesInRequest controls whether key usages should be present in the CertificateRequest
+
Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR.
+
This option defaults to true, and should only be disabled if the target issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions.
@@ -2780,7 +2804,11 @@ description: >-
(Optional)
-
revisionHistoryLimit is the maximum number of CertificateRequest revisions that are maintained in the Certificate’s history. Each revision represents a single CertificateRequest created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number. If set, revisionHistoryLimit must be a value of 1 or greater. If unset (nil), revisions will not be garbage collected. Default value is nil.
+
+ The maximum number of CertificateRequest revisions that are maintained in the Certificate’s history. Each revision represents a single CertificateRequest
+ created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number.
+
+
If set, revisionHistoryLimit must be a value of 1 or greater. If unset (nil), revisions will not be garbage collected. Default value is nil.
@@ -2793,9 +2821,10 @@ description: >-
(Optional)
+
Defines extra output formats of the private key and signed certificate chain to be written to this Certificate’s target Secret.
- AdditionalOutputFormats defines extra output formats of the private key and signed certificate chain to be written to this Certificate’s target Secret. This is an Alpha Feature and is only enabled with the
- --feature-gates=AdditionalCertificateOutputFormats=true option on both the controller and webhook components.
+ This is an Alpha Feature and is only enabled with the
+ --feature-gates=AdditionalCertificateOutputFormats=true option set on both the controller and webhook components.
@@ -2812,7 +2841,7 @@ description: >-
(Optional)
-
Status of the Certificate. This is set and managed automatically.
A CertificateRequest is used to request a signed certificate from one of the configured issuers.
-
- All fields within the CertificateRequest’s spec are immutable after creation. A CertificateRequest will either succeed or fail, as denoted by its status.state
- field.
-
+
All fields within the CertificateRequest’s spec are immutable after creation. A CertificateRequest will either succeed or fail, as denoted by its Ready status condition and its status.failureTime field.
A CertificateRequest is a one-shot resource, meaning it represents a single point in time request for a certificate and cannot be re-used.
The requested ‘duration’ (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types.
+
Requested ‘duration’ (i.e. lifetime) of the Certificate. Note that the issuer may choose to ignore the requested duration, just like any other requested attribute.
@@ -2902,7 +2934,8 @@ description: >-
-
IssuerRef is a reference to the issuer for this CertificateRequest. If the kind field is not set, or set to Issuer, an Issuer resource with the given name in the same namespace as the CertificateRequest will be used. If the kind field is set to ClusterIssuer, a ClusterIssuer with the provided name will be used. The name field in this stanza is required at all times. The group field refers to the API group of the issuer which defaults to cert-manager.io if empty.
+
Reference to the issuer responsible for issuing the certificate. If the issuer is namespace-scoped, it must be in the same namespace as the Certificate. If the issuer is cluster-scoped, it can be used from any namespace.
+
The name field of the reference must always be specified.
@@ -2912,7 +2945,8 @@ description: >-
[]byte
-
The PEM-encoded x509 certificate signing request to be submitted to the CA for signing.
+
The PEM-encoded X.509 certificate signing request to be submitted to the issuer for signing.
+
If the CSR has a BasicConstraints extension, its isCA attribute must match the isCA value of this CertificateRequest. If the CSR has a KeyUsage extension, its key usages must match the key usages in the usages field of this CertificateRequest. If the CSR has a ExtKeyUsage extension, its extended key usages must match the extended key usages in the usages field of this CertificateRequest.
@@ -2923,7 +2957,9 @@ description: >-
(Optional)
-
IsCA will request to mark the certificate as valid for certificate signing when submitting to the issuer. This will automatically add the cert sign usage to the list of usages.
+
Requested basic constraints isCA value. Note that the issuer may choose to ignore the requested isCA value, just like any other requested attribute.
+
NOTE: If the CSR in the Request field has a BasicConstraints extension, it must have the same isCA value as specified here.
+
If true, this will automatically add the cert sign usage to the list of requested usages.
@@ -2936,7 +2972,9 @@ description: >-
(Optional)
-
Usages is the set of x509 usages that are requested for the certificate. If usages are set they SHOULD be encoded inside the CSR spec Defaults to digital signature and key encipherment if not specified.
+
Requested key usages and extended key usages.
+
NOTE: If the CSR in the Request field has uses the KeyUsage or ExtKeyUsage extension, these extensions must have the same values as specified here without any additional values.
+
If unset, defaults to digital signature and key encipherment.
@@ -2996,7 +3034,7 @@ description: >-
(Optional)
-
Status of the CertificateRequest. This is set and managed automatically.
A condition added to Certificate resources when an issuance is required. This condition will be automatically added and set to true if: * No keypair data exists in the target Secret * The data stored in the Secret cannot be decoded * The private key and certificate do not have matching public keys * If a CertificateRequest for the current revision exists and the certificate data stored in the Secret does not match the
- status.certificate on the CertificateRequest. * If no CertificateRequest resource exists for the current revision, the options on the Certificate resource are compared against the x509 data in the Secret, similar to what’s done in earlier versions. If there is a mismatch, an issuance is triggered. This condition may also be added by external API consumers to trigger a re-issuance manually for any other reason.
+ status.certificate on the CertificateRequest. * If no CertificateRequest resource exists for the current revision, the options on the Certificate resource are compared against the X.509 data in the Secret, similar to what’s done in earlier versions. If there is a mismatch, an issuance is triggered. This condition may also be added by external API consumers to trigger a re-issuance manually for any other reason.
It will be removed by the ‘issuing’ controller upon completing issuance.
CertificatePrivateKey contains configuration options for private keys used by the Certificate controller. This allows control of how private keys are rotated.
+
CertificatePrivateKey contains configuration options for private keys used by the Certificate controller. These include the key algorithm and size, the used encoding and the rotation policy.
@@ -3476,7 +3514,8 @@ description: >-
(Optional)
-
RotationPolicy controls how private keys should be regenerated when a re-issuance is being processed. If set to Never, a private key will only be generated if one does not already exist in the target spec.secretName. If one does exists but it does not have the correct algorithm or size, a warning will be raised to await user intervention. If set to Always, a private key matching the specified requirements will be generated whenever a re-issuance occurs. Default is ‘Never’ for backward compatibility.
+
RotationPolicy controls how private keys should be regenerated when a re-issuance is being processed.
+
If set to Never, a private key will only be generated if one does not already exist in the target spec.secretName. If one does exists but it does not have the correct algorithm or size, a warning will be raised to await user intervention. If set to Always, a private key matching the specified requirements will be generated whenever a re-issuance occurs. Default is Never for backward compatibility.
@@ -3489,7 +3528,8 @@ description: >-
(Optional)
-
The private key cryptography standards (PKCS) encoding for this certificate’s private key to be encoded in. If provided, allowed values are PKCS1 and PKCS8 standing for PKCS#1 and PKCS#8, respectively. Defaults to PKCS1 if not specified.
+
The private key cryptography standards (PKCS) encoding for this certificate’s private key to be encoded in.
+
If provided, allowed values are PKCS1 and PKCS8 standing for PKCS#1 and PKCS#8, respectively. Defaults to PKCS1 if not specified.
@@ -3502,7 +3542,8 @@ description: >-
(Optional)
-
Algorithm is the private key algorithm of the corresponding private key for this certificate. If provided, allowed values are either RSA,Ed25519 or ECDSA If algorithm is specified and size is not provided, key size of 256 will be used for ECDSA key algorithm and key size of 2048 will be used for RSA key algorithm. key size is ignored when using the Ed25519 key algorithm.
+
Algorithm is the private key algorithm of the corresponding private key for this certificate.
+
If provided, allowed values are either RSA, ECDSA or Ed25519. If algorithm is specified and size is not provided, key size of 2048 will be used for RSA key algorithm and key size of 256 will be used for ECDSA key algorithm. key size is ignored when using the Ed25519 key algorithm.
@@ -3513,7 +3554,8 @@ description: >-
(Optional)
-
Size is the key bit size of the corresponding private key for this certificate. If algorithm is set to RSA, valid values are 2048, 4096 or 8192, and will default to 2048 if not specified. If algorithm is set to ECDSA, valid values are 256, 384 or 521, and will default to 256 if not specified. If algorithm is set to Ed25519, Size is ignored. No other values are allowed.
+
Size is the key bit size of the corresponding private key for this certificate.
+
If algorithm is set to RSA, valid values are 2048, 4096 or 8192, and will default to 2048 if not specified. If algorithm is set to ECDSA, valid values are 256, 384 or 521, and will default to 256 if not specified. If algorithm is set to Ed25519, Size is ignored. No other values are allowed.
CertificateRequestSpec defines the desired state of CertificateRequest
+
NOTE: It is important to note that the issuer can choose to ignore or change any of the requested attributes. How the issuer maps a certificate request to a signed certificate is the full responsibility of the issuer itself. For example, as an edge case, an issuer that inverts the isCA value is free to do so.
@@ -3668,7 +3711,7 @@ description: >-
(Optional)
-
The requested ‘duration’ (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types.
+
Requested ‘duration’ (i.e. lifetime) of the Certificate. Note that the issuer may choose to ignore the requested duration, just like any other requested attribute.
@@ -3680,7 +3723,8 @@ description: >-
-
IssuerRef is a reference to the issuer for this CertificateRequest. If the kind field is not set, or set to Issuer, an Issuer resource with the given name in the same namespace as the CertificateRequest will be used. If the kind field is set to ClusterIssuer, a ClusterIssuer with the provided name will be used. The name field in this stanza is required at all times. The group field refers to the API group of the issuer which defaults to cert-manager.io if empty.
+
Reference to the issuer responsible for issuing the certificate. If the issuer is namespace-scoped, it must be in the same namespace as the Certificate. If the issuer is cluster-scoped, it can be used from any namespace.
+
The name field of the reference must always be specified.
@@ -3690,7 +3734,8 @@ description: >-
[]byte
-
The PEM-encoded x509 certificate signing request to be submitted to the CA for signing.
+
The PEM-encoded X.509 certificate signing request to be submitted to the issuer for signing.
+
If the CSR has a BasicConstraints extension, its isCA attribute must match the isCA value of this CertificateRequest. If the CSR has a KeyUsage extension, its key usages must match the key usages in the usages field of this CertificateRequest. If the CSR has a ExtKeyUsage extension, its extended key usages must match the extended key usages in the usages field of this CertificateRequest.
@@ -3701,7 +3746,9 @@ description: >-
(Optional)
-
IsCA will request to mark the certificate as valid for certificate signing when submitting to the issuer. This will automatically add the cert sign usage to the list of usages.
+
Requested basic constraints isCA value. Note that the issuer may choose to ignore the requested isCA value, just like any other requested attribute.
+
NOTE: If the CSR in the Request field has a BasicConstraints extension, it must have the same isCA value as specified here.
+
If true, this will automatically add the cert sign usage to the list of requested usages.
@@ -3714,7 +3761,9 @@ description: >-
(Optional)
-
Usages is the set of x509 usages that are requested for the certificate. If usages are set they SHOULD be encoded inside the CSR spec Defaults to digital signature and key encipherment if not specified.
+
Requested key usages and extended key usages.
+
NOTE: If the CSR in the Request field has uses the KeyUsage or ExtKeyUsage extension, these extensions must have the same values as specified here without any additional values.
+
If unset, defaults to digital signature and key encipherment.
@@ -3786,7 +3835,7 @@ description: >-
(Optional)
-
List of status conditions to indicate the status of a CertificateRequest. Known condition types are Ready and InvalidRequest.
+
List of status conditions to indicate the status of a CertificateRequest. Known condition types are Ready, InvalidRequest, Approved and Denied.
@@ -3798,7 +3847,7 @@ description: >-
(Optional)
- The PEM encoded x509 certificate resulting from the certificate signing request. If not set, the CertificateRequest has either not been completed or has failed. More information on failure can be found by checking the
+ The PEM encoded X.509 certificate resulting from the certificate signing request. If not set, the CertificateRequest has either not been completed or has failed. More information on failure can be found by checking the
conditions field.
@@ -3811,7 +3860,7 @@ description: >-
(Optional)
-
The PEM encoded x509 certificate of the signer, also known as the CA (Certificate Authority). This is set on a best-effort basis by different issuers. If not set, the CA is assumed to be unknown/not available.
+
The PEM encoded X.509 certificate of the signer, also known as the CA (Certificate Authority). This is set on a best-effort basis by different issuers. If not set, the CA is assumed to be unknown/not available.
CertificateSpec defines the desired state of Certificate. A valid Certificate requires at least one of a CommonName, DNSName, or URISAN to be valid.
+
CertificateSpec defines the desired state of Certificate.
+
NOTE: The specification contains a lot of “requested” certificate attributes, it is important to note that the issuer can choose to ignore or change any of these requested attributes. How the issuer maps a certificate request to a signed certificate is the full responsibility of the issuer itself. For example, as an edge case, an issuer that inverts the isCA value is free to do so.
+
A valid Certificate requires at least one of a CommonName, LiteralSubject, DNSName, or URI to be valid.
The common name attribute is specified separately in the commonName field. Cannot be set if the literalSubject field is set.
@@ -3900,7 +3952,8 @@ description: >-
(Optional)
-
LiteralSubject is an LDAP formatted string that represents the X.509 Subject field. Use this instead of the Subject field if you need to ensure the correct ordering of the RDN sequence, such as when issuing certs for LDAP authentication. See https://github.com/cert-manager/cert-manager/issues/3203, https://github.com/cert-manager/cert-manager/issues/4424. This field is alpha level and is only supported by cert-manager installations where LiteralCertificateSubject feature gate is enabled on both cert-manager controller and webhook.
Cannot be set if the subject or commonName field is set. This is an Alpha Feature and is only enabled with the --feature-gates=LiteralCertificateSubject=true option set on both the controller and webhook components.
@@ -3911,7 +3964,8 @@ description: >-
(Optional)
-
CommonName is a common name to be used on the Certificate. The CommonName should have a length of 64 characters or fewer to avoid generating invalid CSRs. This value is ignored by TLS clients when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4
Should have a length of 64 characters or fewer to avoid generating invalid CSRs. Cannot be set if the literalSubject field is set.
@@ -3924,7 +3978,8 @@ description: >-
(Optional)
-
The requested ‘duration’ (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types. If unset this defaults to 90 days. Certificate will be renewed either 2⁄3 through its duration or renewBefore period before its expiry, whichever is later. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration
+
Requested ‘duration’ (i.e. lifetime) of the Certificate. Note that the issuer may choose to ignore the requested duration, just like any other requested attribute.
+
If unset, this defaults to 90 days. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration.
@@ -3937,10 +3992,9 @@ description: >-
(Optional)
-
- How long before the currently issued certificate’s expiry cert-manager should renew the certificate. The default is 2⁄3 of the issued certificate’s duration. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration
- https://golang.org/pkg/time/#ParseDuration
-
+
How long before the currently issued certificate’s expiry cert-manager should renew the certificate. For example, if a certificate is valid for 60 minutes, and renewBefore=10m, cert-manager will begin to attempt to renew the certificate 50 minutes after it was issued (i.e. when there are 10 minutes remaining until the certificate is no longer valid).
+
NOTE: The actual lifetime of the issued certificate is used to determine the renewal time. If an issuer returns a certificate with a different lifetime than the one requested, cert-manager will use the lifetime of the issued certificate.
+
If unset, this defaults to 1⁄3 of the issued certificate’s lifetime. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration.
@@ -3951,7 +4005,7 @@ description: >-
(Optional)
-
DNSNames is a list of DNS subjectAltNames to be set on the Certificate.
+
Requested DNS subject alternative names.
@@ -3962,7 +4016,7 @@ description: >-
(Optional)
-
IPAddresses is a list of IP address subjectAltNames to be set on the Certificate.
+
Requested IP address subject alternative names.
@@ -3973,7 +4027,7 @@ description: >-
(Optional)
-
URIs is a list of URI subjectAltNames to be set on the Certificate.
+
Requested URI subject alternative names.
@@ -3984,7 +4038,7 @@ description: >-
(Optional)
-
EmailAddresses is a list of email subjectAltNames to be set on the Certificate.
+
Requested email subject alternative names.
@@ -3994,7 +4048,7 @@ description: >-
string
-
SecretName is the name of the secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer.
+
Name of the Secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer. The Secret resource lives in the same namespace as the Certificate resource.
@@ -4007,7 +4061,7 @@ description: >-
(Optional)
-
SecretTemplate defines annotations and labels to be copied to the Certificate’s Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate’s Secret.
+
Defines annotations and labels to be copied to the Certificate’s Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate’s Secret.
@@ -4020,10 +4074,7 @@ description: >-
(Optional)
-
- Keystores configures additional keystore output formats stored in the
- secretName Secret resource.
-
+
Additional keystore output formats to be stored in the Certificate’s Secret.
@@ -4035,7 +4086,8 @@ description: >-
-
IssuerRef is a reference to the issuer for this certificate. If the kind field is not set, or set to Issuer, an Issuer resource with the given name in the same namespace as the Certificate will be used. If the kind field is set to ClusterIssuer, a ClusterIssuer with the provided name will be used. The name field in this stanza is required at all times.
+
Reference to the issuer responsible for issuing the certificate. If the issuer is namespace-scoped, it must be in the same namespace as the Certificate. If the issuer is cluster-scoped, it can be used from any namespace.
+
The name field of the reference must always be specified.
@@ -4046,7 +4098,8 @@ description: >-
(Optional)
-
IsCA will mark this Certificate as valid for certificate signing. This will automatically add the cert sign usage to the list of usages.
+
Requested basic constraints isCA value. The isCA value is used to set the isCA field on the created CertificateRequest resources. Note that the issuer may choose to ignore the requested isCA value, just like any other requested attribute.
+
If true, this will automatically add the cert sign usage to the list of requested usages.
@@ -4059,7 +4112,8 @@ description: >-
(Optional)
-
Usages is the set of x509 usages that are requested for the certificate. Defaults to digital signature and key encipherment if not specified.
+
Requested key usages and extended key usages. These usages are used to set the usages field on the created CertificateRequest resources. If encodeUsagesInRequest is unset or set to true, the usages will additionally be encoded in the request field which contains the CSR blob.
+
If unset, defaults to digital signature and key encipherment.
@@ -4072,7 +4126,7 @@ description: >-
(Optional)
-
Options to control private keys used for the Certificate.
+
Private key options. These include the key algorithm and size, the used encoding and the rotation policy.
@@ -4083,7 +4137,8 @@ description: >-
(Optional)
-
EncodeUsagesInRequest controls whether key usages should be present in the CertificateRequest
+
Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR.
+
This option defaults to true, and should only be disabled if the target issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions.
@@ -4094,7 +4149,11 @@ description: >-
(Optional)
-
revisionHistoryLimit is the maximum number of CertificateRequest revisions that are maintained in the Certificate’s history. Each revision represents a single CertificateRequest created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number. If set, revisionHistoryLimit must be a value of 1 or greater. If unset (nil), revisions will not be garbage collected. Default value is nil.
+
+ The maximum number of CertificateRequest revisions that are maintained in the Certificate’s history. Each revision represents a single CertificateRequest
+ created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number.
+
+
If set, revisionHistoryLimit must be a value of 1 or greater. If unset (nil), revisions will not be garbage collected. Default value is nil.
@@ -4107,9 +4166,10 @@ description: >-
(Optional)
+
Defines extra output formats of the private key and signed certificate chain to be written to this Certificate’s target Secret.
- AdditionalOutputFormats defines extra output formats of the private key and signed certificate chain to be written to this Certificate’s target Secret. This is an Alpha Feature and is only enabled with the
- --feature-gates=AdditionalCertificateOutputFormats=true option on both the controller and webhook components.
+ This is an Alpha Feature and is only enabled with the
+ --feature-gates=AdditionalCertificateOutputFormats=true option set on both the controller and webhook components.
@@ -4151,7 +4211,7 @@ description: >-
(Optional)
-
LastFailureTime is the time as recorded by the Certificate controller of the most recent failure to complete a CertificateRequest for this Certificate resource. If set, cert-manager will not re-request another Certificate until 1 hour has elapsed from this time.
+
LastFailureTime is set only if the lastest issuance for this Certificate failed and contains the time of the failure. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). If the latest issuance has succeeded this field will be unset.
@@ -4164,7 +4224,7 @@ description: >-
(Optional)
-
The time after which the certificate stored in the secret named by this resource in spec.secretName is valid.
+
The time after which the certificate stored in the secret named by this resource in spec.secretName is valid.
@@ -4518,7 +4578,10 @@ description: >-
bool
-
Create enables JKS keystore creation for the Certificate. If true, a file named keystore.jks will be created in the target Secret resource, encrypted using the password stored in passwordSecretRef. The keystore file will be updated immediately. A file named truststore.jks will also be created in the target Secret resource, encrypted using the password stored in passwordSecretRef containing the issuing Certificate Authority
+
+ Create enables JKS keystore creation for the Certificate. If true, a file named keystore.jks will be created in the target Secret resource, encrypted using the password stored in passwordSecretRef. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named truststore.jks will also be created in the target Secret resource, encrypted using the password stored in passwordSecretRef
+ containing the issuing Certificate Authority
+
@@ -4716,7 +4779,7 @@ description: >-
bool
-
Create enables PKCS12 keystore creation for the Certificate. If true, a file named keystore.p12 will be created in the target Secret resource, encrypted using the password stored in passwordSecretRef. The keystore file will be updated immediately. A file named truststore.p12 will also be created in the target Secret resource, encrypted using the password stored in passwordSecretRef containing the issuing Certificate Authority
+
Create enables PKCS12 keystore creation for the Certificate. If true, a file named keystore.p12 will be created in the target Secret resource, encrypted using the password stored in passwordSecretRef. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named truststore.p12 will also be created in the target Secret resource, encrypted using the password stored in passwordSecretRef containing the issuing Certificate Authority
@@ -4749,7 +4812,7 @@ description: >-
"ECDSA"
-
Denotes the ECDSA private key type.
+
ECDSA private key algorithm.
@@ -4757,7 +4820,7 @@ description: >-
"Ed25519"
-
Denotes the Ed25519 private key type.
+
Ed25519 private key algorithm.
@@ -4765,7 +4828,7 @@ description: >-
"RSA"
-
Denotes the RSA private key type.
+
RSA private key algorithm.
@@ -4786,7 +4849,7 @@ description: >-
"PKCS1"
-
PKCS1 key encoding will produce PEM files that include the type of private key as part of the PEM header, e.g. BEGIN RSA PRIVATE KEY. If the keyAlgorithm is set to ‘ECDSA’, this will produce private keys that use the BEGIN EC PRIVATE KEY header.
+
PKCS1 private key encoding. PKCS1 produces a PEM block that contains the private key algorithm in the header and the private key in the body. A key that uses this can be recognised by its BEGIN RSA PRIVATE KEY or BEGIN EC PRIVATE KEY header. NOTE: This encoding is not supported for Ed25519 keys. Attempting to use this encoding with an Ed25519 key will be ignored and default to PKCS8.
@@ -4794,10 +4857,7 @@ description: >-
"PKCS8"
-
- PKCS8 key encoding will produce PEM files with the BEGIN PRIVATE KEY
- header. It encodes the keyAlgorithm of the private key as part of the DER encoded PEM block.
-
+
PKCS8 private key encoding. PKCS8 produces a PEM block with a static header and both the private key algorithm and the private key in the body. A key that uses this encoding can be recognised by its BEGIN PRIVATE KEY header.
@@ -5344,6 +5404,563 @@ description: >-
+
controller.config.cert-manager.io/v1alpha1
+
+
Package v1alpha1 is the v1alpha1 version of the controller config API.
Each nameserver can be either the IP address and port of a standard recursive DNS server, or the endpoint to an RFC 8484 DNS over HTTPS endpoint. For example, the following values are valid: - “8.8.8.8:53” (Standard DNS) - “https://1.1.1.1/dns-query” (DNS over HTTPS)
+
+
+
+
+ recursiveNameserversOnly
+
+ bool
+
+
+
When true, cert-manager will only ever query the configured DNS resolvers to perform the ACME DNS01 self check. This is useful in DNS constrained environments, where access to authoritative nameservers is restricted. Enabling this option could cause the DNS01 self check to take longer due to caching performed by the recursive nameservers.
+
+
+
+
+ checkRetryPeriod
+
+ time.Duration
+
+
+
The duration the controller should wait between a propagation check. Despite the name, this flag is used to configure the wait period for both DNS01 and HTTP01 challenge propagation checks. For DNS01 challenges the propagation check verifies that a TXT record with the challenge token has been created. For HTTP01 challenges the propagation check verifies that the challenge token is served at the challenge URL. This should be a valid duration string, for example 180s or 1h
The Docker image to use to solve ACME HTTP01 challenges. You most likely will not need to change this parameter unless you are testing a new feature or developing cert-manager.
+
+
+
+
+ solverResourceRequestCPU
+
+ string
+
+
+
Defines the resource request CPU size when spawning new ACME HTTP01 challenge solver pods.
+
+
+
+
+ solverResourceRequestMemory
+
+ string
+
+
+
Defines the resource request Memory size when spawning new ACME HTTP01 challenge solver pods.
+
+
+
+
+ solverResourceLimitsCPU
+
+ string
+
+
+
Defines the resource limits CPU size when spawning new ACME HTTP01 challenge solver pods.
+
+
+
+
+ solverResourceLimitsMemory
+
+ string
+
+
+
Defines the resource limits Memory size when spawning new ACME HTTP01 challenge solver pods.
+
+
+
+
+ solverRunAsNonRoot
+
+ bool
+
+
+
Defines the ability to run the http01 solver as root for troubleshooting issues
+
+
+
+
+ solverNameservers
+
+ []string
+
+
+
A list of comma separated dns server endpoints used for ACME HTTP01 check requests. This should be a list containing host and port, for example [“8.8.8.8:53”,“8.8.4.4:53”] Allows specifying a list of custom nameservers to perform HTTP01 checks on.
+
+
+
+
+
ControllerConfiguration
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ kubeConfig
+
+ string
+
+
+
kubeConfig is the kubeconfig file used to connect to the Kubernetes apiserver. If not specified, the webhook will attempt to load the in-cluster-config.
+
+
+
+
+ apiServerHost
+
+ string
+
+
+
apiServerHost is used to override the API server connection address. Deprecated: use kubeConfig instead.
LeaderElectionConfig configures the behaviour of the leader election
+
+
+
+
+ controllers
+
+ []string
+
+
+
A list of controllers to enable. [’’] enables all controllers, [‘foo’] enables only the foo controller [’’, ‘-foo’] disables the controller named foo.
+
+
+
+
+ issuerAmbientCredentials
+
+ bool
+
+
+
Whether an issuer may make use of ambient credentials. ‘Ambient Credentials’ are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the Issuer API object. When this flag is enabled, the following sources for credentials are also used: AWS - All sources the Go SDK defaults to, notably including any EC2 IAM roles available via instance metadata.
+
+
+
+
+ clusterIssuerAmbientCredentials
+
+ bool
+
+
+
Whether a cluster-issuer may make use of ambient credentials for issuers. ‘Ambient Credentials’ are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the ClusterIssuer API object. When this flag is enabled, the following sources for credentials are also used: AWS - All sources the Go SDK defaults to, notably including any EC2 IAM roles available via instance metadata.
+
+
+
+
+ enableCertificateOwnerRef
+
+ bool
+
+
+
Whether to set the certificate resource as an owner of secret where the tls certificate is stored. When this flag is enabled, the secret will be automatically removed when the certificate resource is deleted.
+
+
+
+
+ copiedAnnotationPrefixes
+
+ []string
+
+
+
Specify which annotations should/shouldn’t be copied from Certificate to CertificateRequest and Order, as well as from CertificateSigningRequest to Order, by passing a list of annotation key prefixes. A prefix starting with a dash(-) specifies an annotation that shouldn’t be copied. Example: ‘*,-kubectl.kuberenetes.io/’- all annotations will be copied apart from the ones where the key is prefixed with ‘kubectl.kubernetes.io/’.
+
+
+
+
+ numberOfConcurrentWorkers
+
+ int32
+
+
+
The number of concurrent workers for each controller.
+
+
+
+
+ maxConcurrentChallenges
+
+ int32
+
+
+
The maximum number of challenges that can be scheduled as ‘processing’ at once.
+
+
+
+
+ metricsListenAddress
+
+ string
+
+
+
The host and port that the metrics endpoint should listen on.
+
+
+
+
+ healthzListenAddress
+
+ string
+
+
+
The host and port address, separated by a ‘:’, that the healthz server should listen on.
+
+
+
+
+ enablePprof
+
+ bool
+
+
+
Enable profiling for controller.
+
+
+
+
+ pprofAddress
+
+ string
+
+
+
The host and port that Go profiler should listen on, i.e localhost:6060. Ensure that profiler is not exposed on a public address. Profiler will be served at /debug/pprof.
Default issuer/certificates details consumed by ingress-shim Name of the Issuer to use when the tls is requested but issuer name is not specified on the ingress resource.
+
+
+
+
+ defaultIssuerKind
+
+ string
+
+
+
Kind of the Issuer to use when the TLS is requested but issuer kind is not specified on the ingress resource.
+
+
+
+
+ defaultIssuerGroup
+
+ string
+
+
+
Group of the Issuer to use when the TLS is requested but issuer group is not specified on the ingress resource.
If true, cert-manager will perform leader election between instances to ensure no more than one instance of cert-manager operates at a time
+
+
+
+
+ namespace
+
+ string
+
+
+
Namespace used to perform leader election. Only used if leader election is enabled
+
+
+
+
+ leaseDuration
+
+ time.Duration
+
+
+
The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. This is only applicable if leader election is enabled.
+
+
+
+
+ renewDeadline
+
+ time.Duration
+
+
+
The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. This is only applicable if leader election is enabled.
+
+
+
+
+ retryPeriod
+
+ time.Duration
+
+
+
The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled.
+
+
+
+
+ healthzTimeout
+
+ time.Duration
+
+
+
Leader election healthz checks within this timeout period after the lease expires will still return healthy.
+
+
+
+
+
meta.cert-manager.io/v1
Package v1 contains meta types for cert-manager APIs
@@ -5663,20 +6280,20 @@ description: >-
securePort
- int
+ int32
-
securePort is the port number to listen on for secure TLS connections from the kube-apiserver. Defaults to 6443.
+
securePort is the port number to listen on for secure TLS connections from the kube-apiserver. If 0, a random available port will be chosen. Defaults to 6443.
healthzPort
- int
+ int32
-
healthzPort is the port number to listen on (using plaintext HTTP) for healthz connections. Defaults to 6080.
+
healthzPort is the port number to listen on (using plaintext HTTP) for healthz connections. If 0, a random available port will be chosen. Defaults to 6080.
@@ -5731,6 +6348,19 @@ description: >-
pprofAddress configures the address on which /debug/pprof endpoint will be served if enabled. Defaults to ‘localhost:6060’.
- Generated with gen-crd-api-reference-docs on git commit ca9aaa0.
+ Generated with gen-crd-api-reference-docs on git commit d34bd7a.
diff --git a/content/docs/reference/cmctl.md b/content/docs/reference/cmctl.md
index 095c9dfe6e..d180dec3e3 100644
--- a/content/docs/reference/cmctl.md
+++ b/content/docs/reference/cmctl.md
@@ -74,7 +74,7 @@ Use "cmctl [command] --help" for more information about a command.
### Approve and Deny CertificateRequests
CertificateRequests can be
-[approved or denied](../concepts/certificaterequest.md#approval) using their
+[approved or denied](../usage/certificaterequest.md#approval) using their
respective cmctl commands:
> **Note**: The internal cert-manager approver may automatically approve all
@@ -282,7 +282,7 @@ cmctl x install \
```
You can find [a full list of the install parameters on cert-manager's ArtifactHub page](https://artifacthub.io/packages/helm/cert-manager/cert-manager#configuration). These are the same parameters that are available when using the Helm chart.
-Once you have deployed cert-manager, you can [verify](../installation/verify.md) the installation.
+Once you have deployed cert-manager, you can [verify](../installation/kubectl.md#verify) the installation.
The CLI also allows the user to output the templated manifest to `stdout`, instead of installing the manifest on the cluster.
@@ -327,7 +327,7 @@ This command can be used to prepare a cert-manager installation that was created
before cert-manager `v1` for upgrading to a cert-manager version `v1.6` or later.
It ensures that any cert-manager custom resources that may have been stored in etcd at
a deprecated API version get migrated to `v1`. See [Migrating Deprecated API
-Resources](https://cert-manager.io/docs/installation/upgrading/remove-deprecated-apis) for more context.
+Resources](https://cert-manager.io/docs/releases/upgrading/remove-deprecated-apis) for more context.
```bash
$ cmctl upgrade migrate-api-version --qps 5 --burst 10
diff --git a/content/docs/release-notes/README.md b/content/docs/release-notes/README.md
deleted file mode 100644
index eccfdd07a1..0000000000
--- a/content/docs/release-notes/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-title: Release Notes
-description: 'cert-manager release notes: Overview'
----
-
-- [`v1.12`](./release-notes-1.12.md)
-- [`v1.11`](./release-notes-1.11.md)
-- [`v1.10`](./release-notes-1.10.md)
-- [`v1.9`](./release-notes-1.9.md)
-- [`v1.8`](./release-notes-1.8.md)
-- [`v1.7`](./release-notes-1.7.md)
-- [`v1.6`](./release-notes-1.6.md)
-- [`v1.5`](./release-notes-1.5.md)
-- [`v1.4`](./release-notes-1.4.md)
-- [`v1.3`](./release-notes-1.3.md)
-- [`v1.2`](./release-notes-1.2.md)
-- [`v1.1`](./release-notes-1.1.md)
-- [`v1.0`](./release-notes-1.0.md)
-- [`v0.16`](./release-notes-0.16.md)
-- [`v0.15`](./release-notes-0.15.md)
-- [`v0.14`](./release-notes-0.14.md)
-- [`v0.13`](./release-notes-0.13.md)
-- [`v0.12`](./release-notes-0.12.md)
-- [`v0.11`](./release-notes-0.11.md)
-- [`v0.10`](./release-notes-0.10.md)
-- [`v0.9`](./release-notes-0.9.md)
-- [`v0.8`](./release-notes-0.8.md)
-- [`v0.7`](./release-notes-0.7.md)
-- [`v0.6`](./release-notes-0.6.md)
-- [`v0.5`](./release-notes-0.5.md)
-- [`v0.4`](./release-notes-0.4.md)
-- [`v0.3`](./release-notes-0.3.md)
-- [`v0.2`](./release-notes-0.2.md)
-- [`v0.1`](./release-notes-0.1.md)
diff --git a/content/docs/installation/supported-releases.md b/content/docs/releases/README.md
similarity index 75%
rename from content/docs/installation/supported-releases.md
rename to content/docs/releases/README.md
index ad08854415..14c30af732 100644
--- a/content/docs/installation/supported-releases.md
+++ b/content/docs/releases/README.md
@@ -13,22 +13,24 @@ Each release is supported for a period of four months, and we aim to create a ne
release roughly every two months, accounting for holiday periods, major conferences
and other world events.
-cert-manager expects that ServerSideApply is enabled in the cluster for all version of Kubernetes from 1.24 and above.
+
+## Currently supported releases
-
Currently supported releases
+| Release | Release Date | End of Life | [Supported Kubernetes versions][s] | [Supported OpenShift versions][s] |
+|----------|:------------:|:----------------------:|:----------------------------------:|:---------------------------------:|
+| [1.13][] | Sep 12, 2023 | Release of 1.15 | 1.23 → 1.28 | 4.10 → 4.15 |
+| [1.12][] | May 19, 2023 | Release of 1.14* | 1.22 → 1.27 | 4.9 → 4.14 |
-| Release | Release Date | End of Life | [Supported Kubernetes versions][s] | [Supported OpenShift versions][s] |
-|----------|:------------:|:---------------:|:----------------------------------:|:---------------------------------:|
-| [1.11][] | Jan 11, 2023 | Release of 1.13 | 1.21 → 1.26 | 4.8 → 4.13 |
-| [1.10][] | Oct 17, 2022 | Release of 1.12 | 1.20 → 1.26 | 4.7 → 4.13 |
-
-\*ServerSideApply should be enabled in the cluster
+\*This is an LTS release sponsored by [Venafi](https://www.venafi.com/).
+It will be supported for a longer period of time than other releases.
+The EOL date for this release has not yet been determined & communicated, but can be decided by the Sponsor.
+The cert-manager maintainers guarantee that this release will be supported until the release of 1.14.
## Upcoming releases
-| Release | Release Date | End of Life | [Supported Kubernetes versions][s] | [Supported OpenShift versions][s] |
-|----------|:--------------:|:--------------:|:-----------------------------------:|:---------------------------------:|
-| [1.12][] | End of April, 2023 | End of August, 2023 | 1.22 → 1.27 | 4.9 → 4.13 |
+| Release | Release Date | End of Life | [Supported Kubernetes versions][s] | [Supported OpenShift versions][s] |
+|----------|:------------:|:----------------------:|:----------------------------------:|:---------------------------------:|
+| [1.14][] | Jan 15, 2024 | ~4 months post release | TBD | TBD |
Dates in the future are uncertain and might change.
@@ -36,6 +38,8 @@ Dates in the future are uncertain and might change.
| Release | Release Date | EOL | Compatible Kubernetes versions | Compatible OpenShift versions |
|----------|:------------:|:------------:|:------------------------------:|:-----------------------------:|
+| [1.11][] | Jan 11, 2023 | Sep 12, 2023 | 1.21 → 1.27 | 4.8 → 4.14 |
+| [1.10][] | Oct 17, 2022 | May 19, 2023 | 1.20 → 1.26 | 4.7 → 4.13 |
| [1.9][] | Jul 22, 2022 | Jan 11, 2023 | 1.20 → 1.24 | 4.7 → 4.11 |
| [1.8][] | Apr 05, 2022 | Oct 17, 2022 | 1.19 → 1.24 | 4.6 → 4.11 |
| [1.7][] | Jan 26, 2021 | Jul 22, 2022 | 1.18 → 1.23 | 4.5 → 4.9 |
@@ -54,30 +58,32 @@ Dates in the future are uncertain and might change.
| [0.11][] | Oct 10, 2019 | Jan 21, 2020 | 1.9 → 1.21 | 3.09 → 4.7 |
[s]: #kubernetes-supported-versions
-[1.12]: https://github.com/cert-manager/cert-manager/milestone/33
-[1.11]: https://cert-manager.io/docs/release-notes/release-notes-1.11
-[1.10]: https://cert-manager.io/docs/release-notes/release-notes-1.10
-[1.9]: https://cert-manager.io/docs/release-notes/release-notes-1.9
-[1.8]: https://cert-manager.io/docs/release-notes/release-notes-1.8
-[1.7]: https://cert-manager.io/docs/release-notes/release-notes-1.7
-[1.6]: https://cert-manager.io/docs/release-notes/release-notes-1.6
-[1.5]: https://cert-manager.io/docs/release-notes/release-notes-1.5
-[1.4]: https://cert-manager.io/docs/release-notes/release-notes-1.4
-[1.3]: https://cert-manager.io/docs/release-notes/release-notes-1.3
-[1.2]: https://cert-manager.io/docs/release-notes/release-notes-1.2
-[1.1]: https://cert-manager.io/docs/release-notes/release-notes-1.1
-[1.0]: https://cert-manager.io/docs/release-notes/release-notes-1.0
-[0.16]: https://cert-manager.io/docs/release-notes/release-notes-0.16
-[0.15]: https://cert-manager.io/docs/release-notes/release-notes-0.15
-[0.14]: https://cert-manager.io/docs/release-notes/release-notes-0.14
-[0.13]: https://cert-manager.io/docs/release-notes/release-notes-0.13
-[0.12]: https://cert-manager.io/docs/release-notes/release-notes-0.12
-[0.11]: https://cert-manager.io/docs/release-notes/release-notes-0.11
+[1.14]: https://github.com/cert-manager/cert-manager/milestone/35
+[1.13]: ./release-notes/release-notes-1.13.md
+[1.12]: ./release-notes/release-notes-1.12.md
+[1.11]: ./release-notes/release-notes-1.11.md
+[1.10]: ./release-notes/release-notes-1.10.md
+[1.9]: ./release-notes/release-notes-1.9.md
+[1.8]: ./release-notes/release-notes-1.8.md
+[1.7]: ./release-notes/release-notes-1.7.md
+[1.6]: ./release-notes/release-notes-1.6.md
+[1.5]: ./release-notes/release-notes-1.5.md
+[1.4]: ./release-notes/release-notes-1.4.md
+[1.3]: ./release-notes/release-notes-1.3.md
+[1.2]: ./release-notes/release-notes-1.2.md
+[1.1]: ./release-notes/release-notes-1.1.md
+[1.0]: ./release-notes/release-notes-1.0.md
+[0.16]: ./release-notes/release-notes-0.16.md
+[0.15]: ./release-notes/release-notes-0.15.md
+[0.14]: ./release-notes/release-notes-0.14.md
+[0.13]: ./release-notes/release-notes-0.13.md
+[0.12]: ./release-notes/release-notes-0.12.md
+[0.11]: ./release-notes/release-notes-0.11.md
We list cert-manager releases on [GitHub](https://github.com/cert-manager/cert-manager/releases),
and release notes on [cert-manager.io](https://cert-manager.io/docs/release-notes/).
-We also maintain detailed [upgrade instructions](https://cert-manager.io/docs/installation/upgrading/).
+We also maintain detailed [upgrade instructions](https://cert-manager.io/docs/releases/upgrading/).
## Support policy
@@ -117,7 +123,8 @@ branch is actually supported.
April 1, 2021
```
-
Technical support
+
+### Technical support
Technical assistance is offered on a best-effort basis for supported
releases only. You can request support from the community on [Kubernetes
@@ -128,7 +135,8 @@ Google group.
[discussions]: https://github.com/cert-manager/cert-manager/discussions
[group]: https://groups.google.com/g/cert-manager-dev
-
Security and bug fixes
+
+### Security and bug fixes
We back-port important bug fixes — including security fixes — to all
currently supported releases.
@@ -137,12 +145,14 @@ currently supported releases.
- [Critical bugs](#critical-bugs),
- [Long-standing bugs](#long-standing-bugs).
-
Security issues
+
+#### Security issues
**Security issues** are fixed as soon as possible. They get back-ported to
the last two releases, and a new patch release is immediately created for them.
-
Critical bugs
+
+#### Critical bugs
**Critical bugs** include both regression bugs as well as upgrade bugs.
@@ -159,7 +169,8 @@ this category.
Fixes for critical bugs are (usually) immediately back-ported by creating a new
patch release for the currently supported releases.
-
Long-standing bugs
+
+#### Long-standing bugs
**Long-standing bug**: sometimes a bug exists for a long time, and may have
known workarounds. [#3444][] is an example of a long-standing bug.
@@ -168,14 +179,16 @@ Where we feel that back-porting would be difficult or might be a stability
risk to clusters running cert-manager, we'll make the fix in a major
release but avoid back-porting the fix.
-
Breaking changes
+
+#### Breaking changes
Breaking changes are changes that intentionally break the cert-manager
Kubernetes API or the command line flags. We avoid making breaking changes
where possible, and where they're required we'll give as much notice as
possible.
-
Other back-ports
+
+#### Other back-ports
We aim to be conservative in what we back-port. That applies especially for anything which
could be a _runtime_ change - that is, a change which might alter behavior for someone
@@ -201,7 +214,8 @@ Generally we'll seek to be pragmatic. A rule of thumb might be to ask:
[#5209]: https://github.com/cert-manager/cert-manager/pull/5209 "release-1.8: rclone"
-
How we determine supported Kubernetes versions
+
+## How we determine supported Kubernetes versions
The list of supported Kubernetes versions displayed in the [Supported Releases](#supported-releases) section
depends on what the cert-manager maintainers think is reasonable to support and to test.
@@ -210,14 +224,14 @@ In practice, this is largely determined based on what versions of [kind](https:/
are available for testing, and which versions of Kubernetes are provided by major upstream cloud Kubernetes vendors
including EKS, GKE, AKS and OpenShift.
-| Vendor | Oldest Kubernetes Release\* | Other Older Kubernetes Releases |
-|:-----------------:|------------------------------|---------------------------------------------------------------|
-| [EKS][eks] | 1.21 (EOL Feb 2023) | 1.22 (EOL May 2023) |
-| [GKE][gke] | 1.21 (EOL Feb 2023) | 1.22 (EOL May 2023) |
-| [AKS][aks] | 1.23 (EOL ~Feb 2023) | |
-| [OpenShift 4][os] | 1.21 (4.8 EUS, EOL Feb 2023) | 1.22 (4.9, EOL Apr 2023) |
+| Vendor | Oldest Kubernetes Release\* | Other Older Kubernetes Releases |
+|:-----------------:|-----------------------------|------------------------------------------------------------------------------------|
+| [EKS][eks] | 1.23 (EOL Oct 2023) | 1.24 (EOL Jan 2024), 1.25 (EOL May 2024), 1.26 (EOL Jun 2024), 1.28 (EOL Nov 2024) |
+| [GKE][gke] | 1.24 (EOL Oct 2023) | 1.25 (EOL Feb 2024), 1.26 (EOL May 2024), 1.27 (EOL Jan 2025), 1.28 (EOL -) |
+| [AKS][aks] | 1.25 (EOL Dec 2023) | 1.26 (EOL Mar 2024), 1.27 (EOL Jun 2024), 1.28 (EOL -) |
+| [OpenShift 4][os] | 1.23 (4.10, EOL Sep 2023) | 1.24 (4.11, EOL Feb 2024), 1.25 (4.12, EOL Jan 2025), 1.25 (4.13, EOL Nov 2024) |
-\*Oldest release relevant to the next cert-manager release, as of 2022-07-18
+\*Oldest release relevant to the next cert-manager release, as of 2023-09-13
[eks]: https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html#kubernetes-release-calendar
[gke]: https://cloud.google.com/kubernetes-engine/docs/release-schedule
@@ -233,6 +247,8 @@ For convenience, the following table shows these version mappings:
| OpenShift versions | Kubernetes version |
|--------------------|--------------------|
+| 4.15 | 1.28 |
+| 4.14 | 1.27 |
| 4.13 | 1.26 |
| 4.12 | 1.25 |
| 4.11 | 1.24 |
diff --git a/content/docs/release-notes/release-notes-0.1.md b/content/docs/releases/release-notes/release-notes-0.1.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.1.md
rename to content/docs/releases/release-notes/release-notes-0.1.md
diff --git a/content/docs/release-notes/release-notes-0.10.md b/content/docs/releases/release-notes/release-notes-0.10.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.10.md
rename to content/docs/releases/release-notes/release-notes-0.10.md
diff --git a/content/docs/release-notes/release-notes-0.11.md b/content/docs/releases/release-notes/release-notes-0.11.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.11.md
rename to content/docs/releases/release-notes/release-notes-0.11.md
diff --git a/content/docs/release-notes/release-notes-0.12.md b/content/docs/releases/release-notes/release-notes-0.12.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.12.md
rename to content/docs/releases/release-notes/release-notes-0.12.md
diff --git a/content/docs/release-notes/release-notes-0.13.md b/content/docs/releases/release-notes/release-notes-0.13.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.13.md
rename to content/docs/releases/release-notes/release-notes-0.13.md
diff --git a/content/docs/release-notes/release-notes-0.14.md b/content/docs/releases/release-notes/release-notes-0.14.md
similarity index 98%
rename from content/docs/release-notes/release-notes-0.14.md
rename to content/docs/releases/release-notes/release-notes-0.14.md
index 7f6ccb6713..46f972d34b 100644
--- a/content/docs/release-notes/release-notes-0.14.md
+++ b/content/docs/releases/release-notes/release-notes-0.14.md
@@ -11,7 +11,7 @@ The `v0.14` release has a few focus areas:
* Support for older Kubernetes and OpenShift versions
* Experimental 'bundle' output format for Certificates
-As usual, please read the [upgrade notes](../installation/upgrading/upgrading-0.13-0.14.md) before upgrading.
+As usual, please read the [upgrade notes](../upgrading/upgrading-0.13-0.14.md) before upgrading.
## Webhook changes
@@ -53,7 +53,7 @@ Thanks to this conversion webhook, this upgrade and future upgrades after it sho
these kinds of changes to our API will enable the `v1beta1` API version to be released in a seamless manner in an
upcoming release too.
-More information on the webhook can be found in the [concepts section](../concepts/webhook.md).
+More information on the webhook can be found in the [concepts section](../../concepts/webhook.md).
## Support for Kubernetes 1.11 and OpenShift 3.11
diff --git a/content/docs/release-notes/release-notes-0.15.md b/content/docs/releases/release-notes/release-notes-0.15.md
similarity index 98%
rename from content/docs/release-notes/release-notes-0.15.md
rename to content/docs/releases/release-notes/release-notes-0.15.md
index a91f110a8b..47ca5264f9 100644
--- a/content/docs/release-notes/release-notes-0.15.md
+++ b/content/docs/releases/release-notes/release-notes-0.15.md
@@ -12,7 +12,7 @@ The `v0.15` release has a few focus areas:
* General Availability of JKS and PKCS#12 keystore support
* kubectl cert-manager CLI plugin allowing manual renewal and API version conversion
-As usual, please read the [upgrade notes](../installation/upgrading/upgrading-0.14-0.15.md) before upgrading.
+As usual, please read the [upgrade notes](../upgrading/upgrading-0.14-0.15.md) before upgrading.
## Experimental controllers
diff --git a/content/docs/release-notes/release-notes-0.16.md b/content/docs/releases/release-notes/release-notes-0.16.md
similarity index 89%
rename from content/docs/release-notes/release-notes-0.16.md
rename to content/docs/releases/release-notes/release-notes-0.16.md
index 40b98c2292..2862c52f4b 100644
--- a/content/docs/release-notes/release-notes-0.16.md
+++ b/content/docs/releases/release-notes/release-notes-0.16.md
@@ -10,7 +10,7 @@ The `v0.16` release has a few focus areas:
* `v1beta1` API
-As usual, please read the [upgrade notes](../installation/upgrading/upgrading-0.15-0.16.md) before upgrading.
+As usual, please read the [upgrade notes](../upgrading/upgrading-0.15-0.16.md) before upgrading.
## New certificate controller
@@ -40,12 +40,12 @@ private key and X.509 certificate in `my-cr.key` and `my-cr.crt` respectively.
$ kubectl cert-manager create certificaterequest my-cr --from-certificate-file my-certificate.yaml --fetch-certificate --timeout 20m
```
-More information can be found on our [kubectl plugin page](../reference/cmctl.md#legacy-kubectl-plugin).
+More information can be found on our [kubectl plugin page](../../reference/cmctl.md#legacy-kubectl-plugin).
## `v1beta1` API
We are soon reaching cert-manager `v1.0` and the new `v1beta1` API is our first step towards a stable `v1` API.
-The biggest change users may notice is the improved API documentation. We took the time to review and update all the user-facing APIs. You can view the [updated API documentation online](../reference/api-docs.md), or use `kubectl explain` after installing this version of cert-manager.
+The biggest change users may notice is the improved API documentation. We took the time to review and update all the user-facing APIs. You can view the [updated API documentation online](../../reference/api-docs.md), or use `kubectl explain` after installing this version of cert-manager.
`v1beta1` does not contain many big changes, this version is focused on streamlining field names and general clean up of the API in preparation for the release of the `v1` release.
These are the changes made (for reference, our conversion will take care of everything for you):
@@ -88,4 +88,4 @@ The `kubectl cert-manager convert` command will be able to convert your manifest
$ kubectl cert-manager convert --output-version cert-manager.io/v1beta1 cert.yaml
```
-More information can be found on our [kubectl plugin page](../reference/cmctl.md#legacy-kubectl-plugin).
+More information can be found on our [kubectl plugin page](../../reference/cmctl.md#legacy-kubectl-plugin).
diff --git a/content/docs/release-notes/release-notes-0.2.md b/content/docs/releases/release-notes/release-notes-0.2.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.2.md
rename to content/docs/releases/release-notes/release-notes-0.2.md
diff --git a/content/docs/release-notes/release-notes-0.3.md b/content/docs/releases/release-notes/release-notes-0.3.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.3.md
rename to content/docs/releases/release-notes/release-notes-0.3.md
diff --git a/content/docs/release-notes/release-notes-0.4.md b/content/docs/releases/release-notes/release-notes-0.4.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.4.md
rename to content/docs/releases/release-notes/release-notes-0.4.md
diff --git a/content/docs/release-notes/release-notes-0.5.md b/content/docs/releases/release-notes/release-notes-0.5.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.5.md
rename to content/docs/releases/release-notes/release-notes-0.5.md
diff --git a/content/docs/release-notes/release-notes-0.6.md b/content/docs/releases/release-notes/release-notes-0.6.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.6.md
rename to content/docs/releases/release-notes/release-notes-0.6.md
diff --git a/content/docs/release-notes/release-notes-0.7.md b/content/docs/releases/release-notes/release-notes-0.7.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.7.md
rename to content/docs/releases/release-notes/release-notes-0.7.md
diff --git a/content/docs/release-notes/release-notes-0.8.md b/content/docs/releases/release-notes/release-notes-0.8.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.8.md
rename to content/docs/releases/release-notes/release-notes-0.8.md
diff --git a/content/docs/release-notes/release-notes-0.9.md b/content/docs/releases/release-notes/release-notes-0.9.md
similarity index 100%
rename from content/docs/release-notes/release-notes-0.9.md
rename to content/docs/releases/release-notes/release-notes-0.9.md
diff --git a/content/docs/release-notes/release-notes-1.0.md b/content/docs/releases/release-notes/release-notes-1.0.md
similarity index 98%
rename from content/docs/release-notes/release-notes-1.0.md
rename to content/docs/releases/release-notes/release-notes-1.0.md
index 94e67568f2..5101c235af 100644
--- a/content/docs/release-notes/release-notes-1.0.md
+++ b/content/docs/releases/release-notes/release-notes-1.0.md
@@ -27,7 +27,7 @@ The `v1.0` release is a stability release with a few focus areas:
* ACME improvements
-As usual, please read the [upgrade notes](../installation/upgrading/upgrading-0.16-1.0.md) before upgrading.
+As usual, please read the [upgrade notes](../upgrading/upgrading-0.16-1.0.md) before upgrading.
## `v1` API
@@ -48,7 +48,7 @@ This change makes these 2 SANs consistent with the other SANs as well as the Go
If you're using Kubernetes 1.16 or higher, conversion webhooks will allow you seamlessly interact with `v1alpha2`, `v1alpha3`, `v1beta1` and `v1` API versions at the same time. This allows you to use the new API version without having to modify or redeploy your older resources.
We highly recommend upgrading your manifests to the `v1` API as older versions will soon be deprecated.
-Users of the `legacy` version of cert-manager will still only have the `v1` API, migration steps can be found in the [upgrade notes](../installation/upgrading/upgrading-0.16-1.0.md).
+Users of the `legacy` version of cert-manager will still only have the `v1` API, migration steps can be found in the [upgrade notes](../upgrading/upgrading-0.16-1.0.md).
## `kubectl cert-manager status` command
@@ -150,7 +150,7 @@ With this change we reduced the number of logs when you don't need to have a deb
Tip: My default cert-manager runs on level 2 (Info), you can set this using `global.logLevel` in the Helm chart.
-*Note*: Looking at the logs while troubleshooting cert-manager should be last resort behavior, for more info check out our [troubleshooting guide](../troubleshooting/README.md)
+*Note*: Looking at the logs while troubleshooting cert-manager should be last resort behavior, for more info check out our [troubleshooting guide](../../troubleshooting/README.md)
## ACME improvements
diff --git a/content/docs/release-notes/release-notes-1.1.md b/content/docs/releases/release-notes/release-notes-1.1.md
similarity index 94%
rename from content/docs/release-notes/release-notes-1.1.md
rename to content/docs/releases/release-notes/release-notes-1.1.md
index 082caaa095..d3ca28683b 100644
--- a/content/docs/release-notes/release-notes-1.1.md
+++ b/content/docs/releases/release-notes/release-notes-1.1.md
@@ -20,7 +20,7 @@ All help is very appreciated and very welcome!
Interested in knowing what will happen in the next releases of cert-manager? Go check out [our road map](https://github.com/cert-manager/cert-manager/blob/master/ROADMAP.md)!
-As usual, please read the [upgrade notes](../installation/upgrading/upgrading-1.0-1.1.md) before upgrading.
+As usual, please read the [upgrade notes](../upgrading/upgrading-1.0-1.1.md) before upgrading.
## ACME Improvements
@@ -48,5 +48,5 @@ This allows you to get more insight into any rate limiting or other errors your
## Improvements for Venafi TPP Authentication
-It is now possible to use a long lived access-token for authentication when configuring [Venafi TPP `Issuer` and `ClusterIssuer` types](../configuration/venafi.md).
+It is now possible to use a long lived access-token for authentication when configuring [Venafi TPP `Issuer` and `ClusterIssuer` types](../../configuration/venafi.md).
This authentication mechanism is supported by `Venafi TPP >= 19.2`.
\ No newline at end of file
diff --git a/content/docs/release-notes/release-notes-1.10.md b/content/docs/releases/release-notes/release-notes-1.10.md
similarity index 100%
rename from content/docs/release-notes/release-notes-1.10.md
rename to content/docs/releases/release-notes/release-notes-1.10.md
diff --git a/content/docs/release-notes/release-notes-1.11.md b/content/docs/releases/release-notes/release-notes-1.11.md
similarity index 74%
rename from content/docs/release-notes/release-notes-1.11.md
rename to content/docs/releases/release-notes/release-notes-1.11.md
index 65a014fa55..316fc75b7e 100644
--- a/content/docs/release-notes/release-notes-1.11.md
+++ b/content/docs/releases/release-notes/release-notes-1.11.md
@@ -3,13 +3,58 @@ title: Release 1.11
description: 'cert-manager release notes: cert-manager 1.11'
---
+## v1.11.5
+
+- Use Go 1.19.9 to fix a security issue in Go's `crypto/tls` library. ([#6317](https://github.com/cert-manager/cert-manager/pull/6317), [@maelvls](https://github.com/maelvls))
+
+## v1.11.4
+
+### Other
+
+- Resolved docker/docker trivy CVE alert ([#6164](https://github.com/cert-manager/cert-manager/pull/6164), [@inteon](https://github.com/inteon))
+- Upgraded base images ([#6128](https://github.com/cert-manager/cert-manager/pull/6128), [@SgtCoDFish](https://github.com/SgtCoDFish))
+
+## v1.11.3
+
+cert-manager `v1.11.3` mostly contains ACME library changes. API Priority and Fairness feature is now disabled in the external webhook's extension apiserver.
+
+### Other
+
+- API Priority and Fairness controller is now disabled in extension apiserver for DNS webhook implementation. ([#6092](https://github.com/cert-manager/cert-manager/pull/6092), [@irbekrm](https://github.com/irbekrm))
+- Adds a warning for folks to not use controller feature gates helm value to configure webhook feature gates ([#6101](https://github.com/cert-manager/cert-manager/pull/6101), [@irbekrm](https://github.com/irbekrm))
+
+## v1.11.2
+
+### Bug or Regression
+
+- Build with go 1.19.9 ([#6014](https://github.com/cert-manager/cert-manager/pull/6014), [@SgtCoDFish](https://github.com/SgtCoDFish))
+
+### Other
+- Bump the distroless base images ([#5930](https://github.com/cert-manager/cert-manager/pull/5930), [@maelvls](https://github.com/maelvls))
+- Bumps Docker libraries to fix vulnerability scan alert for `CVE-2023-28840`, `CVE-2023-28841`, `CVE-2023-28842` ([#6037](https://github.com/cert-manager/cert-manager/pull/6037), [@irbekrm](https://github.com/irbekrm)) - cert-manager was not actually affected by these CVEs which are all to do with Docker daemon's overlay network.
+- Bumps Kubernetes libraries `v0.26.0` -> `v0.26.4` ([#6038](https://github.com/cert-manager/cert-manager/pull/6038), [@irbekrm](https://github.com/irbekrm)) - this might help with running cert-manager v1.11 on Kubernetes `v1.27`
+
+
+## v1.11.1
+
+### Bug or Regression
+
+- Bump helm and other dependencies to fix CVEs, along with upgrading go and base images ([#5815](https://github.com/cert-manager/cert-manager/pull/5815), [@SgtCoDFish](https://github.com/SgtCoDFish))
+- Bump the distroless base images ([#5930](https://github.com/cert-manager/cert-manager/pull/5930), [@maelvls](https://github.com/maelvls))
+- The auto-retry mechanism added in VCert 4.23.0 and part of cert-manager 1.11.0 ([#5674](https://github.com/cert-manager/cert-manager/pull/5674)) has been found to be faulty. Until this issue is fixed upstream, we now use a patched version of VCert. This patch will slowdown the issuance of certificates by 9% in case of heavy load on TPP. We aim to release at an ulterior date a patch release of cert-manager to fix this slowdown. ([#5819](https://github.com/cert-manager/cert-manager/pull/5819), [@maelvls](https://github.com/maelvls))
+- Use a fake kube-apiserver version when generating helm template in `cmctl x install`, to work around a hardcoded Kubernetes version in Helm. ([#5726](https://github.com/cert-manager/cert-manager/pull/5726), [@SgtCoDFish](https://github.com/SgtCoDFish))
+
+### Other
+
+- Bump keystore-go to v4.4.1 to work around an upstream rewrite of history ([#5730](https://github.com/cert-manager/cert-manager/pull/5730), [@SgtCoDFish](https://github.com/SgtCoDFish))
+
+## v1.11.0
+
cert-manager `v1.11.0` includes a drastic reduction in cert-manager's runtime memory usage,
a slew of improvements to AKS integrations and various other tweaks, fixes and improvements,
all towards cert-manager's goal of being the best way to handle certificates in modern
Cloud Native applications.
-## Major Themes
-
### Support for Azure Workload Identity Federation with Azure DNS and ACME DNS-01
cert-manager can now authenticate using [Azure Workload Identity Federation](https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation) to manage ACME DNS-01 records in Azure DNS.
@@ -18,9 +63,9 @@ Instead cert-manager authenticates to Azure using a short lived Kubernetes Servi
This is now the recommended authentication method because it is more secure and easier to maintain than the other methods,
and it should be used instead of the [deprecated pod-managed identify mechanism](https://github.com/Azure/aad-pod-identity#-announcement).
-> 📖 Read about [configuring the ACME issuer with Azure DNS](../configuration/acme/dns01/azuredns.md).
+> 📖 Read about [configuring the ACME issuer with Azure DNS](../../configuration/acme/dns01/azuredns.md).
>
-> 📖 Read the [AKS + LoadBalancer + Let's Encrypt tutorial](../tutorials/getting-started-aks-letsencrypt/README.md) for an end-to-end example of this authentication method.
+> 📖 Read the [AKS + LoadBalancer + Let's Encrypt tutorial](../../tutorials/getting-started-aks-letsencrypt/README.md) for an end-to-end example of this authentication method.
>
> 🔗 See [pull request #5570](https://github.com/cert-manager/cert-manager/pull/5570) for the implementation
@@ -31,7 +76,7 @@ complies with the ACME spec for the ACME issuer, but some users had issues when
either that they ignore certificate validation (which is insecure) or that they hack their certificate into the cert-manager trust store.
Now, users can set a caBundle flag on their ACME issuer, specifying the trust store that cert-manager should use when communicating with the
-server. For more details, see [Private ACME Servers](../configuration/acme/README.md#private-acme-servers)
+server. For more details, see [Private ACME Servers](../../configuration/acme/README.md#private-acme-servers)
### `LiteralSubject` Improvements
@@ -51,7 +96,7 @@ Unless you've _explicitly_ opted in to using the Gateway API support, you don't
anything. If you've been using the support, however, you might need to take some actions
to ensure there aren't any breakages when you update.
-Check out the [upgrade guide](../installation/upgrading/upgrading-1.10-1.11.md) for more
+Check out the [upgrade guide](../upgrading/upgrading-1.10-1.11.md) for more
details on what you'll need to do.
## Community
diff --git a/content/docs/release-notes/release-notes-1.12.md b/content/docs/releases/release-notes/release-notes-1.12.md
similarity index 80%
rename from content/docs/release-notes/release-notes-1.12.md
rename to content/docs/releases/release-notes/release-notes-1.12.md
index 9a048ec28e..ebb3b26a57 100644
--- a/content/docs/release-notes/release-notes-1.12.md
+++ b/content/docs/releases/release-notes/release-notes-1.12.md
@@ -3,14 +3,107 @@ title: Release 1.12
description: 'cert-manager release notes: cert-manager 1.12'
---
+## v1.12.6
+
+v1.12.6 fixes some CVE alerts and a Venafi issuer bug
+
+### Changes
+
+#### Bug or Regression
+
+- Bump `golang.org/x/net v0.15.0 => v0.17.0` as part of addressing `CVE-2023-44487` / `CVE-2023-39325` (#6431, @SgtCoDFish)
+- The Venafi issuer now properly resets the certificate and should no longer get stuck with `WebSDK CertRequest Module Requested Certificate` or `This certificate cannot be processed while it is in an error state. Fix any errors, and then click Retry.`. (#6401, @jetstack-bot)
+
+#### Other (Cleanup or Flake)
+
+- Bump go to 1.20.10 to address `CVE-2023-39325`. Also bumps base images. (#6412, @SgtCoDFish)
+
+## v1.12.5
+
+v1.12.5 contains a backport for a name collision bug that was found in v1.13.0
+
+### Changes
+
+#### Bug or Regression
+
+- BUGFIX: fix CertificateRequest name collision bug in StableCertificateRequestName feature. (#6359, @jetstack-bot)
+
+#### Other (Cleanup or Flake)
+
+- Updated base images to the latest version. (#6372, @inteon)
+- Upgrade Go from 1.20.7 to 1.20.8. (#6371, @jetstack-bot)
+
+## v1.12.4
+
+v1.12.4 contains an important security fix that
+addresses [CVE-2023-29409](https://cve.report/CVE-2023-29409).
+
+### Changes
+
+- Fixes an issue where cert-manager would incorrectly reject two IP addresses as
+ being unequal when they should have compared equal. This would be most
+ noticeable when using an IPv6 address which doesn't match how Go's
+ `net.IP.String()` function would have printed that address.
+ ([#6297](https://github.com/cert-manager/cert-manager/pull/6297),
+ [@SgtCoDFish](https://github.com/SgtCoDFish))
+- Use Go 1.20.7 to fix a security issue in Go's `crypto/tls` library.
+ ([#6318](https://github.com/cert-manager/cert-manager/pull/6318),
+ [@maelvls](https://github.com/maelvls))
+
+## v1.12.3
+
+v1.12.3 contains a bug fix for the cainjector which addresses a memory leak!
+
+### Changes
+
+- BUGFIX\[cainjector\]: 1-character bug was causing invalid log messages and a memory leak (#6235, @jetstack-bot)
+
+## v1.12.2
+
+v1.12.2 is a bugfix release, but includes a known issue. You should prefer
+upgrading to the latest patch version available for 1.12.
+
+### Known issues
+
+- cainjector contains a memory leak due to re-assignment of a log variable (see https://github.com/cert-manager/cert-manager/issues/6217). The fix will be released in v1.12.3. See https://github.com/cert-manager/cert-manager/pull/6232 for context.
+
+### Changes
+
+- BUGFIX: `cmctl check api --wait 0` exited without output; we now make sure we perform the API check at least once (#6116, @jetstack-bot)
+
+## v1.12.1
+
+The v1.12.1 release contains a couple dependency bumps and changes to ACME
+external webhook library. Note that v1.12.1 contains a known issue, and you
+should prefer upgrading to the latest patch version available for 1.12.
+
+### Known issues
+
+- [`cmctl` API check](https://cert-manager.io/docs/installation/verify/) is broken in v1.12.1. We suggest that you do not upgrade `cmctl` to this version. The fix will be released in v1.12.2.
+See #6116 for context.
+- cainjector contains a memory leak due to re-assignment of a log variable (see https://github.com/cert-manager/cert-manager/issues/6217). The fix will be released in v1.12.3.
+See https://github.com/cert-manager/cert-manager/pull/6232 for context.
+
+### Other
+
+- Don't run API Priority and Fairness controller in webhook's extension apiserver ([#6085](https://github.com/cert-manager/cert-manager/pull/6085), [@irbekrm](https://github.com/irbekrm))
+- Adds a warning for folks to not use controller feature gates helm value to configure webhook feature gates ([#6100](https://github.com/cert-manager/cert-manager/pull/6100), [@irbekrm](https://github.com/irbekrm))
+
+### Uncategorized
+
+- Updates Kubernetes libraries to `v0.27.2`. ([#6077](https://github.com/cert-manager/cert-manager/pull/6077), [@lucacome](https://github.com/lucacome))
+- Updates controller-runtime to `v0.15.0` ([#6098](https://github.com/cert-manager/cert-manager/pull/6098), [@lucacome](https://github.com/lucacome))
+
+## v1.12.0
+
cert-manager 1.12 brings support for JSON logging, a lower memory footprint, the
support for ephemeral service account tokens with Vault, and the support of the
`ingressClassName` field. We also improved on our ability to patch
vulnerabilities.
-## Major Themes
+### Major Themes
-### Support for JSON logging
+#### Support for JSON logging
JSON logs are now available in cert-manager! A massive thank you to
[@malovme](https://github.com/malovme) for going the extra mile to get
@@ -30,17 +123,17 @@ helm upgrade --install cert-manager jetstack/cert-manager --namespace cert-manag
--set cainjector.extraArgs='{--logging-format=json}'
```
-### Lower memory footprint
+#### Lower memory footprint
In 1.12 we continued the work started in 1.11 to reduce cert-manager component's
memory consumption.
-#### Controller
+##### Controller
Caching of the full contents of all cluster `Secret`s can now be disabled by
setting a `SecretsFilteredCaching` alpha feature gate to true. This will ensure
that only `Secret` resources that are labelled with
-`controller.cert-manager.io/fao` label are cached in full. Cert-manager
+`controller.cert-manager.io/fao` label [^1] are cached in full. Cert-manager
automatically adds this label to all `Certificate` `Secret`s.
This change has been placed behind alpha feature gate as it could potentially
@@ -60,9 +153,9 @@ Additionally, controller no longer watches and caches all `Pod` and `Service`
resources.
See [`cert-manager#5976`](https://github.com/cert-manager/cert-manager/pull/5976) for implementation.
-#### Cainjector
+##### Cainjector
-[Cainjector's](../concepts/ca-injector.md) control loops have been refactored, so by default it should
+[Cainjector's](../../concepts/ca-injector.md) control loops have been refactored, so by default it should
consume up to half as much memory as before, see
[`cert-manager#5746`](https://github.com/cert-manager/cert-manager/pull/5746).
@@ -88,7 +181,7 @@ See [`cert-manager#5766`](https://github.com/cert-manager/cert-manager/pull/5766
A big thanks to everyone who put in time reporting and writing up issues
describing performance problems in large scale installations.
-### Faster Response to CVEs By Reducing Transitive Dependencies
+#### Faster Response to CVEs By Reducing Transitive Dependencies
In cert-manager 1.12, we have worked on reducing the impacts that unsupported
dependencies have on our ability to patch CVEs.
@@ -108,7 +201,7 @@ your `go.mod` files or potential version conflicts between cert-manager and your
other dependencies.
The caveat here is that we still only recommend importing cert-manager in [very
-specific circumstances](../contributing/importing.md), and the module changes
+specific circumstances](../../contributing/importing.md), and the module changes
mean that if you imported some paths (specifically under `cmd` or some paths
under `test`) you might see broken imports when you try to upgrade.
@@ -119,7 +212,7 @@ impact, and there should be no runtime impact either.
You can read more about this change in the design document
[`20230302.gomod.md`](https://github.com/cert-manager/cert-manager/blob/master/design/20230302.gomod.md).
-### Support for ephemeral service account tokens in Vault
+#### Support for ephemeral service account tokens in Vault
cert-manager can now authenticate to Vault using ephemeral service account
tokens (JWT). cert-manager already knew to authenticate to Vault using the
@@ -130,20 +223,31 @@ cert-manager in a secretless manner. With this new feature, cert-manager will
create an ephemeral service account token on your behalf and use that to
authenticate to Vault.
-> 📖 Read about [Secretless Authentication with a Service Account](../configuration/vault.md#secretless-authentication-with-a-service-account).
+> 📖 Read about [Secretless Authentication with a Service Account](../../configuration/vault.md#secretless-authentication-with-a-service-account).
This change was implemented in the pull request
[`cert-manager#5502`](https://github.com/cert-manager/cert-manager/pull/5502).
-### Support for `ingressClassName` in the HTTP-01 solver
+#### Support for `ingressClassName` in the HTTP-01 solver
cert-manager now supports the `ingressClassName` field in the HTTP-01 solver. We
recommend using `ingressClassName` instead of the field `class` in your Issuers
and ClusterIssuers.
-> 📖 Read more about `ingressClassName` in the documentation page [HTTP01](../configuration/acme/http01/#ingressclassname).
+> 📖 Read more about `ingressClassName` in the documentation page [HTTP01](../../configuration/acme/http01/#ingressclassname).
-## Community
+#### Liveness probe and healthz endpoint in the controller
+
+A healthz HTTP server has been added to the controller component.
+It serves a `/livez` endpoint, which reports the health status of the leader election system.
+If the leader process has failed to renew its lease but has unexpectedly failed to exit,
+the `/livez` endpoint will return an error code and an error message.
+In conjunction with a new liveness probe in the controller Pod,
+this will cause the controller to be restarted by the kubelet.
+
+> 📖 Read more about this new feature in [Best Practice: Use Liveness Probes](../../installation/best-practice.md#use-liveness-probes).
+
+### Community
We extend our gratitude to all the open-source contributors who have made
commits in this release, including:
@@ -193,9 +297,9 @@ the Private CA Issuer.
In addition, massive thanks to Jetstack (by Venafi) for contributing developer
time and resources towards the continued maintenance of cert-manager projects.
-## Changes since v1.11.0
+### Changes
-### Feature
+#### Feature
- Helm: Added PodDisruptionBudgets for cert-manager components to the Helm chart (disabled by default). ([#3931](https://github.com/cert-manager/cert-manager/pull/3931), [@e96wic](https://github.com/e96wic))
- Added support for JSON logging (using `--logging-format=json`) ([#5828](https://github.com/cert-manager/cert-manager/pull/5828), [@malovme](https://github.com/malovme))
@@ -218,11 +322,11 @@ time and resources towards the continued maintenance of cert-manager projects.
- The cainjector controller can now use server-side apply to patch mutatingwebhookconfigurations, validatingwebhookconfigurations, apiservices, and customresourcedefinitions. This feature is currently in alpha and is not enabled by default. To enable server-side apply for the cainjector, add the flag --feature-gates=ServerSideApply=true to the deployment. ([#5991](https://github.com/cert-manager/cert-manager/pull/5991), [@inteon](https://github.com/inteon))
- Helm: Egress 6443/TCP is now allowed in the webhook. This is required for OpenShift and OKD clusters for which the Kubernetes API server listens on port 6443 instead of 443. ([#5788](https://github.com/cert-manager/cert-manager/pull/5788), [@ExNG](https://github.com/ExNG))
-### Documentation
+#### Documentation
- Helm: the dead links in `values.yaml` are now working ([#5999](https://github.com/cert-manager/cert-manager/pull/5999), [@SgtCoDFish](https://github.com/SgtCoDFish))
-### Bug or Regression
+#### Bug or Regression
- When using the `literalSubject` field on a Certificate resource, the IPs, URIs, DNS names, and email addresses segments are now properly compared. ([#5747](https://github.com/cert-manager/cert-manager/pull/5747), [@inteon](https://github.com/inteon))
- When using the `jks` and `pkcs12` fields on a Certificate resource with a CA issuer that doesn't set the `ca.crt` in the Secret resource, cert-manager no longer loop trying to copy `ca.crt` into `truststore.jks` or `truststore.p12`. ([#5972](https://github.com/cert-manager/cert-manager/pull/5972), [@vinzent](https://github.com/vinzent))
@@ -235,7 +339,7 @@ time and resources towards the continued maintenance of cert-manager projects.
- Upgrade to go 1.19.6 along with newer helm and containerd versions and updated base images ([#5813](https://github.com/cert-manager/cert-manager/pull/5813), [@SgtCoDFish](https://github.com/SgtCoDFish))
- cmctl: In order work around a hardcoded Kubernetes version in Helm, we now use a fake kube-apiserver version when generating the helm template when running `cmctl x install`. ([#5720](https://github.com/cert-manager/cert-manager/pull/5720), [@irbekrm](https://github.com/irbekrm))
-### Other (Cleanup or Flake)
+#### Other (Cleanup or Flake)
- ACME account registration is now re-verified if account key is manually changed. ([#5949](https://github.com/cert-manager/cert-manager/pull/5949), [@TrilokGeer](https://github.com/TrilokGeer))
- Add `make go-workspace` target for generating a go.work file for local development ([#5935](https://github.com/cert-manager/cert-manager/pull/5935), [@SgtCoDFish](https://github.com/SgtCoDFish))
@@ -265,6 +369,8 @@ time and resources towards the continued maintenance of cert-manager projects.
- Validates that `certificate.spec.secretName` is a valid `Secret` name ([#5967](https://github.com/cert-manager/cert-manager/pull/5967), [@avi-08](https://github.com/avi-08))
- `certificate.spec.secretName` Secrets will now be labelled with `controller.cert-manager.io/fao` label ([#5660](https://github.com/cert-manager/cert-manager/pull/5660), [@irbekrm](https://github.com/irbekrm))
-### Uncategorized
+#### Uncategorized
- We have replaced our python boilerplate checker with an installed Go version, removing the need to have Python installed when developing or building cert-manager. ([#6000](https://github.com/cert-manager/cert-manager/pull/6000), [@SgtCoDFish](https://github.com/SgtCoDFish))
+
+[^1]: fao = 'for attention of'
diff --git a/content/docs/releases/release-notes/release-notes-1.13.md b/content/docs/releases/release-notes/release-notes-1.13.md
new file mode 100644
index 0000000000..dd72d96aad
--- /dev/null
+++ b/content/docs/releases/release-notes/release-notes-1.13.md
@@ -0,0 +1,164 @@
+---
+title: Release 1.13
+description: 'cert-manager release notes: cert-manager 1.13'
+---
+
+## v1.13.2
+
+v1.13.2 fixes some CVE alerts and contains fixes for:
+1. a CertificateRequest runaway situation in case two Certificate resources point to the same Secret target resource
+2. a small bug in the Helm chart (feature gate options)
+3. a Venafi issuer bug
+
+### Changes
+
+#### Bug or Regression
+
+- Bump `golang.org/x/net v0.15.0 => v0.17.0` as part of addressing `CVE-2023-44487` / `CVE-2023-39325` (#6432, @SgtCoDFish)
+- BUGFIX[helm]: Fix issue where webhook feature gates were only set if controller feature gates are set. (#6381, @jetstack-bot)
+- Fix runaway bug caused by multiple Certificate resources that point to the same Secret resource. (#6425, @jetstack-bot)
+- The Venafi issuer now properly resets the certificate and should no longer get stuck with `WebSDK CertRequest Module Requested Certificate` or `This certificate cannot be processed while it is in an error state. Fix any errors, and then click Retry.`. (#6402, @jetstack-bot)
+
+#### Other (Cleanup or Flake)
+
+- Bump go to 1.20.10 to address `CVE-2023-39325`. Also bumps base images. (#6411, @SgtCoDFish)
+
+## v1.13.1
+
+v1.13.1 contains a bugfix for a name collision bug in the StableCertificateRequestName feature that was enabled by default in v1.13.0.
+
+### Changes
+
+#### Bug or Regression
+
+- BUGFIX: fix CertificateRequest name collision bug in StableCertificateRequestName feature. (#6358, @jetstack-bot)
+
+#### Other (Cleanup or Flake)
+
+- Upgrade `github.com/emicklei/go-restful/v3` to `v3.11.0` because `v3.10.2` is labeled as "DO NOT USE". (#6368, @inteon)
+- Upgrade Go from 1.20.7 to 1.20.8. (#6370, @jetstack-bot)
+
+## v1.13.0
+
+cert-manager 1.13 brings support for DNS over HTTPS, support for loading options from a versioned
+config file for the cert-manager controller, and more. This release also includes the promotion of
+the `StableCertificateRequestName` and `SecretsFilteredCaching` feature gates to Beta.
+
+### Major Themes
+
+#### Load cert-manager controller options from a versioned config file
+
+It is now possible to load the cert-manager controller options from a versioned config file.
+This was supported for the webhook already, but not for the controller. This is very useful
+way to better manage these options and it allows us to change the options in the future without
+breaking backwards compatibility by introducing a new config file version.
+
+#### DNS over HTTPS (DoH) support
+
+It is now possible to use DNS over HTTPS (DoH) for doing the self-checks during the ACME
+DNS01 verification. The DNS self-check method to be used is controlled through the command line flag:
+`--dns01-recursive-nameservers-only=true` in combination with
+`--dns01-recursive-nameservers=https://` (e.g. `https://1.1.1.1/dns-query`)
+
+This is very useful in case all traffic must be HTTP(S) traffic, e.g. when using a `HTTPS_PROXY`.
+
+#### `StableCertificateRequestName` and `SecretsFilteredCaching` feature gates promoted to Beta
+
+The `StableCertificateRequestName` and `SecretsFilteredCaching` feature gates have been promoted to Beta.
+This means that they are enabled by default and that we will not remove them in the future. In case you
+are experiencing issues with these features, please let us know. The feature gates can still be disabled
+by setting the feature gate to false (e.g. in case you are experiencing issues with these features). We
+plan to promote these feature gates to GA in the future, which will mean that they can no longer be disabled.
+
+### Community
+
+Welcome to these new cert-manager members (more info - https://github.com/cert-manager/cert-manager/pull/6260):
+@jsoref
+@FlorianLiebhart
+@hawksight
+@erikgb
+
+Thanks again to all open-source contributors with commits in this release, including:
+@AcidLeroy
+@FlorianLiebhart
+@lucacome
+@cypres
+@erikgb
+@ubergesundheit
+@jkroepke
+@jsoref
+@gdvalle
+@rouke-broersma
+@schrodit
+@zhangzhiqiangcs
+@arukiidou
+@hawksight
+@Richardds
+@kahirokunn
+
+Thanks also to the following cert-manager maintainers for their contributions during this release:
+@SgtCoDFish
+@maelvls
+@irbekrm
+@inteon
+
+Equally thanks to everyone who provided feedback, helped users and raised issues on GitHub and Slack and joined our meetings!
+
+Special thanks to @AcidLeroy for adding "load options from a versioned config file" support for the cert-manager controller! This has been on our wishlist for a very long time. (see https://github.com/cert-manager/cert-manager/pull/5337)
+
+Also, thanks a lot to @FlorianLiebhart for adding support for DNS over HTTPS for the ACME DNS self-check. This is very useful in case all traffic must be HTTP(S) traffic, e.g. when using a `HTTPS_PROXY`. (see https://github.com/cert-manager/cert-manager/pull/5003)
+
+Thanks also to the [CNCF](https://www.cncf.io/), which provides resources and support, and to the AWS open source team for being good community members and for their maintenance of the [PrivateCA Issuer](https://github.com/cert-manager/aws-privateca-issuer).
+
+In addition, massive thanks to [Venafi](https://www.venafi.com/) for contributing developer time and resources towards the continued maintenance of cert-manager projects.
+
+### Changes
+
+#### Feature
+
+- Add support for logging options to webhook config file. (https://github.com/cert-manager/cert-manager/pull/6243, https://github.com/inteon)
+- Add view permissions to the well-known (OpenShift) user-facing `cluster-reader` aggregated cluster role (https://github.com/cert-manager/cert-manager/pull/6241, https://github.com/erikgb)
+- Certificate Shim: distinguish DNS names and IP address in certificate (https://github.com/cert-manager/cert-manager/pull/6267, https://github.com/zhangzhiqiangcs)
+- Cmctl can now be imported by third parties. (https://github.com/cert-manager/cert-manager/pull/6049, https://github.com/SgtCoDFish)
+- Make `enableServiceLinks` configurable for all Deployments and `startupapicheck` Job in Helm chart. (https://github.com/cert-manager/cert-manager/pull/6292, https://github.com/ubergesundheit)
+- Promoted the `StableCertificateRequestName` and `SecretsFilteredCaching` feature gates to Beta (enabled by default). (https://github.com/cert-manager/cert-manager/pull/6298, https://github.com/inteon)
+- The cert-manager controller options are now configurable using a configuration file. (https://github.com/cert-manager/cert-manager/pull/5337, https://github.com/AcidLeroy)
+- The `pki.CertificateTemplate*` functions now perform validation of the CSR blob, making sure we sign a Certificate that matches the `IsCA` and `(Extended)KeyUsages` that are defined in the CertificateRequest resource. (https://github.com/cert-manager/cert-manager/pull/6199, https://github.com/inteon)
+- [helm] Add `prometheus.servicemonitor.endpointAdditionalProperties` to define additional properties on a ServiceMonitor endpoint, e.g. relabelings (https://github.com/cert-manager/cert-manager/pull/6110, https://github.com/jkroepke)
+
+#### Design
+
+- DNS over HTTPS (DoH) is now possible for doing the self-checks during the ACME verification.
+ The DNS check method to be used is controlled through the command line flag: `--dns01-recursive-nameservers-only=true` in combination with `--dns01-recursive-nameservers=https://<` (e.g. `https://8.8.8.8/dns-query`). It keeps using DNS lookup as a default method. (https://github.com/cert-manager/cert-manager/pull/5003, https://github.com/FlorianLiebhart)
+
+#### Bug or Regression
+
+- Allow overriding default PDB `.minAvailable` with `.maxUnavailable` without setting `.minAvailable` to null (https://github.com/cert-manager/cert-manager/pull/6087, https://github.com/rouke-broersma)
+- BUGFIX[ctl]: `cmctl check api --wait 0` exited without output and exit code 1; we now make sure we perform the API check at least once and return with the correct error code (https://github.com/cert-manager/cert-manager/pull/6109, https://github.com/inteon)
+- BUGFIX[controller]: the issuer and certificate-name annotations on a Secret were incorrectly updated when other fields are changed. (https://github.com/cert-manager/cert-manager/pull/6147, https://github.com/inteon)
+- BUGFIX[cainjector]: 1-character bug was causing invalid log messages and a memory leak (https://github.com/cert-manager/cert-manager/pull/6232, https://github.com/inteon)
+- Fix CloudDNS issuers stuck in propagation check, when multiple instances are issuing for the same FQDN (https://github.com/cert-manager/cert-manager/pull/6088, https://github.com/cypres)
+- Fix indentation of Webhook NetworkPolicy `matchLabels` in helm chart. (https://github.com/cert-manager/cert-manager/pull/6220, https://github.com/ubergesundheit)
+- Fixed Cloudflare DNS01 challenge provider race condition when validating multiple domains (https://github.com/cert-manager/cert-manager/pull/6191, https://github.com/Richardds)
+- Fixes a bug where webhook was pulling in controller's feature gates.
+ ⚠️ ⚠️ BREAKING ⚠️ ⚠️ : If you deploy cert-manager using helm and have `.featureGates` value set, the features defined there will no longer be passed to cert-manager webhook, only to cert-manager controller. Use `webhook.featureGates` field instead to define features to be enabled on webhook.
+ **Potentially breaking**: If you were, for some reason, passing cert-manager controller's features to webhook's `--feature-gates` flag, this will now break (unless the webhook actually has a feature by that name). (https://github.com/cert-manager/cert-manager/pull/6093, https://github.com/irbekrm)
+- Fixes an issue where cert-manager would incorrectly reject two IP addresses as being unequal when they should have compared equal. This would be most noticeable when using an IPv6 address which doesn't match how Go's `net.IP.String()` function would have printed that address. (https://github.com/cert-manager/cert-manager/pull/6293, https://github.com/SgtCoDFish)
+- We disabled the `enableServiceLinks` option for our ACME HTTP solver pods, because the option caused the pod to be in a crash loop in a cluster with lot of services. (https://github.com/cert-manager/cert-manager/pull/6143, https://github.com/schrodit)
+- ⚠️ possibly breaking: Webhook validation of CertificateRequest resources is stricter now: all `KeyUsages` and `ExtendedKeyUsages` must be defined directly in the CertificateRequest resource, the encoded CSR can never contain more usages that defined there. (https://github.com/cert-manager/cert-manager/pull/6182, https://github.com/inteon)
+
+#### Other (Cleanup or Flake)
+
+- A subset of the klog flags have been deprecated and will be removed in the future. (https://github.com/cert-manager/cert-manager/pull/5879, https://github.com/maelvls)
+- All service links in helm chart deployments have been disabled. (https://github.com/cert-manager/cert-manager/pull/6144, https://github.com/schrodit)
+- Cert-manager will now re-issue a certificate if the public key in the latest CertificateRequest resource linked to a Certificate resource does not match the public key of the key encoded in the Secret linked to that Certificate resource (https://github.com/cert-manager/cert-manager/pull/6168, https://github.com/inteon)
+- Chore: When `hostNetwork` is enabled, `dnsPolicy` is now set to `ClusterFirstWithHostNet`. (https://github.com/cert-manager/cert-manager/pull/6156, https://github.com/kahirokunn)
+- Cleanup the controller config file structure by introducing nested structs. (https://github.com/cert-manager/cert-manager/pull/6242, https://github.com/inteon)
+- Don't run API Priority and Fairness controller in webhook's extension apiserver (https://github.com/cert-manager/cert-manager/pull/6085, https://github.com/irbekrm)
+- Helm: Add apache 2.0 license annotation (https://github.com/cert-manager/cert-manager/pull/6225, https://github.com/arukiidou)
+- Make `apis/acme/v1/ACMEIssuer.PreferredChain` optional in JSON serialization. (https://github.com/cert-manager/cert-manager/pull/6034, https://github.com/gdvalle)
+- The `SecretPostIssuancePolicyChain` now also makes sure that the `cert-manager.io/common-name`, `cert-manager.io/alt-names`, ... annotations on Secrets are kept at their correct value. (https://github.com/cert-manager/cert-manager/pull/6176, https://github.com/inteon)
+- The cmctl logging has been improved and support for JSON logging has been added. (https://github.com/cert-manager/cert-manager/pull/6247, https://github.com/inteon)
+- Updates Kubernetes libraries to `v0.27.2`. (https://github.com/cert-manager/cert-manager/pull/6077, https://github.com/lucacome)
+- Updates Kubernetes libraries to `v0.27.4`. (https://github.com/cert-manager/cert-manager/pull/6227, https://github.com/lucacome)
+- We now only check that the issuer name, kind and group annotations on a Secret match in case those annotations are set. (https://github.com/cert-manager/cert-manager/pull/6152, https://github.com/inteon)
diff --git a/content/docs/release-notes/release-notes-1.2.md b/content/docs/releases/release-notes/release-notes-1.2.md
similarity index 96%
rename from content/docs/release-notes/release-notes-1.2.md
rename to content/docs/releases/release-notes/release-notes-1.2.md
index eb729ae383..12cc382d93 100644
--- a/content/docs/release-notes/release-notes-1.2.md
+++ b/content/docs/releases/release-notes/release-notes-1.2.md
@@ -7,7 +7,7 @@ description: 'cert-manager release notes: cert-manager v1.2'
This release adds new features for several issuers and fixes several bugs.
-Please read the [upgrade notes](../installation/upgrading/upgrading-1.1-1.2.md) before upgrading.
+Please read the [upgrade notes](../upgrading/upgrading-1.1-1.2.md) before upgrading.
Aside from that, there have been numerous bug fixes and features summarized below.
@@ -15,7 +15,7 @@ Aside from that, there have been numerous bug fixes and features summarized belo
1. The `--renew-before-expiration-duration` flag of the cert-manager controller-manager has been deprecated. Please set the `Certificate.Spec.RenewBefore` field instead. This flag will be removed in the next release.
-2. As Kubernetes `v1.16` is now the earliest supported version, The `legacy` manifests have now been removed. You can read more [here](../installation/supported-releases.md).
+2. As Kubernetes `v1.16` is now the earliest supported version, The `legacy` manifests have now been removed. You can read more [here](../README.md).
3. The `User-Agent` request header has been changed from `jetstack-cert-manager/` to `cert-manager/`. This may affect functionality if you rely on an a User-Agent allowlist in a corporate environment.
diff --git a/content/docs/release-notes/release-notes-1.3.md b/content/docs/releases/release-notes/release-notes-1.3.md
similarity index 97%
rename from content/docs/release-notes/release-notes-1.3.md
rename to content/docs/releases/release-notes/release-notes-1.3.md
index b9bc9641b2..4f7a0a5f31 100644
--- a/content/docs/release-notes/release-notes-1.3.md
+++ b/content/docs/releases/release-notes/release-notes-1.3.md
@@ -35,7 +35,7 @@ Special thanks to the external contributors who contributed to this release:
* [@OmairK](https://github.com/OmairK)
* [@justinkillen](https://github.com/justinkillen)
-Please read the [upgrade notes](../installation/upgrading/upgrading-1.2-1.3.md) before upgrading.
+Please read the [upgrade notes](../upgrading/upgrading-1.2-1.3.md) before upgrading.
As always, the full change log is available on the [GitHub release](https://github.com/cert-manager/cert-manager/releases/tag/v1.3.0).
diff --git a/content/docs/release-notes/release-notes-1.4.md b/content/docs/releases/release-notes/release-notes-1.4.md
similarity index 98%
rename from content/docs/release-notes/release-notes-1.4.md
rename to content/docs/releases/release-notes/release-notes-1.4.md
index 4620620ae4..a73c1310c4 100644
--- a/content/docs/release-notes/release-notes-1.4.md
+++ b/content/docs/releases/release-notes/release-notes-1.4.md
@@ -42,7 +42,7 @@ and which is therefore available on
Please uninstall the existing cert-manager package and re-install
by following the [OLM Installation Documentation][].
-[OLM Installation Documentation]: ../installation/operator-lifecycle-manager.md
+[OLM Installation Documentation]: ../../installation/operator-lifecycle-manager.md
### Upgrading cert-manager CRDs and stored versions of cert-manager custom resources
@@ -65,7 +65,7 @@ resources are stored in `etcd` at `v1` version and that cert-manager CRDs do not
reference the deprecated APIs **by the time you upgrade to `v1.6`**.
This is explained in more detail in the [Upgrading existing cert-manager
-resources](../installation/upgrading/remove-deprecated-apis.md#upgrading-existing-cert-manager-resources)
+resources](../upgrading/remove-deprecated-apis.md#upgrading-existing-cert-manager-resources)
page.
@@ -168,7 +168,7 @@ Note that you will still need to manually approve the CSR object before
cert-manager can sign the CSR.
The documentation is available on the [the Kubernetes CSR usage
-page](../usage/kube-csr.md).
+page](../../usage/kube-csr.md).
Implemented in cert-manager PR [#4064][].
diff --git a/content/docs/release-notes/release-notes-1.5.md b/content/docs/releases/release-notes/release-notes-1.5.md
similarity index 99%
rename from content/docs/release-notes/release-notes-1.5.md
rename to content/docs/releases/release-notes/release-notes-1.5.md
index 8e585335e8..d3e03aa619 100644
--- a/content/docs/release-notes/release-notes-1.5.md
+++ b/content/docs/releases/release-notes/release-notes-1.5.md
@@ -36,7 +36,7 @@ Most people won't have any trouble upgrading from a version that contains the re
If you are using Traefik, Istio, Ambassador, or ingress-nginx _and_ you are using a non-default value for the class (e.g., `istio-internal`), or if you experience any issues with your HTTP-01 challenges please read the [notes on Ingress v1 compatibility].
-[notes on Ingress v1 compatibility]: https://cert-manager.io/docs/installation/upgrading/ingress-class-compatibility/
+[notes on Ingress v1 compatibility]: https://cert-manager.io/docs/releases/upgrading/ingress-class-compatibility/
#### Bug or Regression
@@ -110,7 +110,7 @@ cert-manager 1.5 is now compatible with both Ingress `v1` and `v1beta1`.
cert-manager will default to using `v1` Ingress, and fall back to `v1beta1` when
`v1` is not available.
-Please read the [Ingress class compatibility](../installation/upgrading/ingress-class-compatibility.md)
+Please read the [Ingress class compatibility](../upgrading/ingress-class-compatibility.md)
notes to see if your Ingress controller has any known issues.
Additionally, the cert-manager API versions `v1alpha2`, `v1alpha3` and `v1beta1`
diff --git a/content/docs/release-notes/release-notes-1.6.md b/content/docs/releases/release-notes/release-notes-1.6.md
similarity index 96%
rename from content/docs/release-notes/release-notes-1.6.md
rename to content/docs/releases/release-notes/release-notes-1.6.md
index 26d4460efa..74a9ce2809 100644
--- a/content/docs/release-notes/release-notes-1.6.md
+++ b/content/docs/releases/release-notes/release-notes-1.6.md
@@ -43,7 +43,7 @@ Most people won't have any trouble upgrading from 1.6.0 or 1.6.1 to 1.6.2. If yo
If you are using Traefik, Istio, Ambassador, or ingress-nginx _and_ you are using a non-default value for the class (e.g., `istio-internal`), or if you experience any issues with your HTTP-01 challenges please read the [notes on Ingress v1 compatibility].
-[notes on Ingress v1 compatibility]: https://cert-manager.io/docs/installation/upgrading/ingress-class-compatibility/
+[notes on Ingress v1 compatibility]: https://cert-manager.io/docs/releases/upgrading/ingress-class-compatibility/
### Changelog since v1.6.1
@@ -73,7 +73,7 @@ If you are using Traefik, Istio, Ambassador, or ingress-nginx _and_ you are usin
Following their deprecation in version 1.4, the cert-manager API versions `v1alpha2, v1alpha3, and v1beta1` are no longer served.
-This means if your deployment manifests contain any of these API versions, you will not be able to deploy them after upgrading. Our new `cmctl` utility or old `kubectl cert-manager` plugin can [convert](../reference/cmctl.md#convert) old manifests to `v1` for you.
+This means if your deployment manifests contain any of these API versions, you will not be able to deploy them after upgrading. Our new `cmctl` utility or old `kubectl cert-manager` plugin can [convert](../../reference/cmctl.md#convert) old manifests to `v1` for you.
@@ -82,7 +82,7 @@ cert-manager < `v1.0.0`, you will need to ensure that all cert-manager custom
resources are stored in `etcd` at `v1` version and that cert-manager CRDs do not
reference the deprecated APIs **before you upgrade to `v1.6`**.
-This is explained in more detail in the [Upgrading existing cert-manager resources](../installation/upgrading/remove-deprecated-apis.md#upgrading-existing-cert-manager-resources)
+This is explained in more detail in the [Upgrading existing cert-manager resources](../upgrading/remove-deprecated-apis.md#upgrading-existing-cert-manager-resources)
page.
@@ -99,7 +99,7 @@ If you are using a shorter password, certificates would have failed to renew,
and the only observable error was in the cert-manager logs.
This was fixed in cert-manager `v1.6.1`.
-[jks-keystore]: ../reference/api-docs.md#cert-manager.io/v1.CertificateKeystores
+[jks-keystore]: ../../reference/api-docs.md#cert-manager.io/v1.CertificateKeystores
[jks-keystore-upgrade-pr]: https://github.com/cert-manager/cert-manager/pull/4428
### Major Themes
@@ -110,11 +110,11 @@ The cert-manager kubectl plugin has been redesigned as a [standalone utility: `c
While the kubectl plugin functionality remains intact, using `cmctl` allows for full tab completion.
-[cmctl]: ../reference/cmctl.md
+[cmctl]: ../../reference/cmctl.md
#### Supply Chain Security
-As part of the wider ecosystem's push for greater supply chain security we are aiming to achieve [SLSA 3](https://slsa.dev/levels#level-requirements) by the 1.7 release date. cert-manager 1.6 has achieved the requirements for SLSA 2 when installed via helm. Our helm chart's signature can be verified with the cert-manager maintainers' public key [published on our website](../installation/code-signing.md).
+As part of the wider ecosystem's push for greater supply chain security we are aiming to achieve [SLSA 3](https://slsa.dev/levels#level-requirements) by the 1.7 release date. cert-manager 1.6 has achieved the requirements for SLSA 2 when installed via helm. Our helm chart's signature can be verified with the cert-manager maintainers' public key [published on our website](../../installation/code-signing.md).
Our container images will be signed using sigstore's [cosign](https://github.com/sigstore/cosign) as soon as our OCI registry supports it.
diff --git a/content/docs/release-notes/release-notes-1.7.md b/content/docs/releases/release-notes/release-notes-1.7.md
similarity index 98%
rename from content/docs/release-notes/release-notes-1.7.md
rename to content/docs/releases/release-notes/release-notes-1.7.md
index 06853b8157..8727e00d09 100644
--- a/content/docs/release-notes/release-notes-1.7.md
+++ b/content/docs/releases/release-notes/release-notes-1.7.md
@@ -54,7 +54,7 @@ Please [download `cmctl-v1.7.1`] and read [Migrating Deprecated API Resources]
for full instructions.
[download `cmctl-v1.7.1`]: https://github.com/cert-manager/cert-manager/releases/tag/v1.7.1
-[Migrating Deprecated API Resources]: https://cert-manager.io/docs/installation/upgrading/remove-deprecated-apis/
+[Migrating Deprecated API Resources]: https://cert-manager.io/docs/releases/upgrading/remove-deprecated-apis/
#### Ingress Class Semantics
@@ -87,7 +87,7 @@ Most people won't have any trouble upgrading from a version that contains the re
If you are using Traefik, Istio, Ambassador, or ingress-nginx _and_ you are using a non-default value for the class (e.g., `istio-internal`), or if you experience any issues with your HTTP-01 challenges please read the [notes on Ingress v1 compatibility].
-[notes on Ingress v1 compatibility]: https://cert-manager.io/docs/installation/upgrading/ingress-class-compatibility/
+[notes on Ingress v1 compatibility]: https://cert-manager.io/docs/releases/upgrading/ingress-class-compatibility/
#### Upgrading with Server Side Apply
@@ -128,7 +128,7 @@ can be requested for the same certificate.
Read [Additional Certificate Output Formats] for more details and
thanks to [@seuf](https://github.com/seuf) for getting this across the line!
-[Additional Certificate Output Formats]: ../usage/certificate.md#additional-certificate-output-formats
+[Additional Certificate Output Formats]: ../../usage/certificate.md#additional-certificate-output-formats
#### Server-Side Apply
@@ -178,7 +178,7 @@ Thanks again to all open-source contributors with commits in this release, inclu
And thanks as usual to [coderanger](https://github.com/coderanger) for helping people
out on the [`#cert-manager` Slack channel]; it's a huge help and much appreciated.
-[`#cert-manager` Slack channel]: ../contributing/README.md#slack
+[`#cert-manager` Slack channel]: ../../contributing/README.md#slack
### Changelog since v1.6.0
diff --git a/content/docs/release-notes/release-notes-1.8.md b/content/docs/releases/release-notes/release-notes-1.8.md
similarity index 98%
rename from content/docs/release-notes/release-notes-1.8.md
rename to content/docs/releases/release-notes/release-notes-1.8.md
index 22221af56e..e5cc204636 100644
--- a/content/docs/release-notes/release-notes-1.8.md
+++ b/content/docs/releases/release-notes/release-notes-1.8.md
@@ -47,7 +47,7 @@ Version 1.8 also marks our first release in which the Go import path for cert-ma
#### Validation of the `rotationPolicy` field
-The field `spec.privateKey.rotationPolicy` on Certificate resources is now validated. Valid options are Never and Always. If you are using a GitOps flow and one of your YAML manifests contains a Certificate with an invalid value, you will need to update it with a valid value to prevent your GitOps tool from failing on the new validation. Please follow the instructions listed on the page [Upgrading from v1.7 to v1.8](https://cert-manager.io/docs/installation/upgrading/upgrading-1.7-1.8/). ([#4913](https://github.com/cert-manager/cert-manager/pull/4913), [@jahrlin](https://github.com/jahrlin))
+The field `spec.privateKey.rotationPolicy` on Certificate resources is now validated. Valid options are Never and Always. If you are using a GitOps flow and one of your YAML manifests contains a Certificate with an invalid value, you will need to update it with a valid value to prevent your GitOps tool from failing on the new validation. Please follow the instructions listed on the page [Upgrading from v1.7 to v1.8](https://cert-manager.io/docs/releases/upgrading/upgrading-1.7-1.8/). ([#4913](https://github.com/cert-manager/cert-manager/pull/4913), [@jahrlin](https://github.com/jahrlin))
##### What happens if I upgrade to 1.8.0 without doing the above steps?
@@ -123,7 +123,7 @@ These conflicts aren't usually actually a problem which will block the issuance
reconcile loops. Server-side apply cleans things up, which should mean less noise in logs and fewer pointless reconcile loops.
If you want to test it out, you can enable alpha-level cert-manager Server-Side Apply support through the
-`--feature-gates` [controller flag](../cli/controller.md).
+`--feature-gates` [controller flag](../../cli/controller.md).
#### From Bazel to Make
@@ -149,7 +149,7 @@ Previously, a failed issuance was retried every hour which — especially in lar
are now retried with a binary exponential backoff starting with `1h` then `2h`, `4h` up to a maximum of `32h`. As part of the new backoff behavior, a new `failedIssuanceAttempts` field was added to the
`Certificate` spec to track the number of currently failed issuances.
-The `cmctl renew` [command](../cli/cmctl.md) command can still be used to force `Certificate` renewal immediately.
+The `cmctl renew` [command](../../cli/cmctl.md) command can still be used to force `Certificate` renewal immediately.
We're also considering reducing the initial backoff from 1 hour. If you have a use case where this would be useful please do comment on [our tracking issue](https://github.com/cert-manager/cert-manager/issues/4786).
diff --git a/content/docs/release-notes/release-notes-1.9.md b/content/docs/releases/release-notes/release-notes-1.9.md
similarity index 100%
rename from content/docs/release-notes/release-notes-1.9.md
rename to content/docs/releases/release-notes/release-notes-1.9.md
diff --git a/content/docs/installation/upgrading/ingress-class-compatibility.md b/content/docs/releases/upgrading/ingress-class-compatibility.md
similarity index 100%
rename from content/docs/installation/upgrading/ingress-class-compatibility.md
rename to content/docs/releases/upgrading/ingress-class-compatibility.md
diff --git a/content/docs/installation/upgrading/remove-deprecated-apis.md b/content/docs/releases/upgrading/remove-deprecated-apis.md
similarity index 100%
rename from content/docs/installation/upgrading/remove-deprecated-apis.md
rename to content/docs/releases/upgrading/remove-deprecated-apis.md
diff --git a/content/docs/installation/upgrading/upgrading-0.10-0.11.md b/content/docs/releases/upgrading/upgrading-0.10-0.11.md
similarity index 95%
rename from content/docs/installation/upgrading/upgrading-0.10-0.11.md
rename to content/docs/releases/upgrading/upgrading-0.10-0.11.md
index d79aea493f..183d9fc643 100644
--- a/content/docs/installation/upgrading/upgrading-0.10-0.11.md
+++ b/content/docs/releases/upgrading/upgrading-0.10-0.11.md
@@ -20,17 +20,17 @@ resources, will need to be updated to reflect these changes.
This upgrade should be performed in a few steps:
1. Back up existing cert-manager resources, as per the
- [backup and restore guide](../../tutorials/backup.md).
+ [backup and restore guide](../../devops-tips/backup.md).
-2. [Uninstall cert-manager](../uninstall.md).
+2. [Uninstall cert-manager](../../installation/uninstall.md).
3. Ensure the old cert-manager CRD resources have also been deleted: `kubectl get crd | grep certmanager.k8s.io`
4. Update the `apiVersion` on all your backed up resources from
`certmanager.k8s.io/v1alpha1` to `cert-manager.io/v1alpha2`.
-5. Re-install cert-manager from scratch according to the [installation
- guide](../README.md).
+5. Re-install cert-manager from scratch according to the
+ [installation guide](../../installation/upgrade.md).
You must be sure to properly **backup**, **uninstall**, **re-install** and
**restore** your installation in order to ensure the upgrade is successful.
diff --git a/content/docs/installation/upgrading/upgrading-0.11-0.12.md b/content/docs/releases/upgrading/upgrading-0.11-0.12.md
similarity index 95%
rename from content/docs/installation/upgrading/upgrading-0.11-0.12.md
rename to content/docs/releases/upgrading/upgrading-0.11-0.12.md
index 582e5b0c4a..a2a8c1da07 100644
--- a/content/docs/installation/upgrading/upgrading-0.11-0.12.md
+++ b/content/docs/releases/upgrading/upgrading-0.11-0.12.md
@@ -9,7 +9,7 @@ minimal changes that effect end users bar two changes which require action when
upgrading.
After addressing the following points, you should then follow the standard
-upgrade process [here](./README.md).
+upgrade process [here](../../installation/upgrade.md).
## Changes to the Vault Kubernetes Auth Mount Path
If you are using Kubernetes authentication for Vault `Issuers` then there has
diff --git a/content/docs/installation/upgrading/upgrading-0.12-0.13.md b/content/docs/releases/upgrading/upgrading-0.12-0.13.md
similarity index 72%
rename from content/docs/installation/upgrading/upgrading-0.12-0.13.md
rename to content/docs/releases/upgrading/upgrading-0.12-0.13.md
index 8fdb8adeb9..7f8ce01e48 100644
--- a/content/docs/installation/upgrading/upgrading-0.12-0.13.md
+++ b/content/docs/releases/upgrading/upgrading-0.12-0.13.md
@@ -4,4 +4,4 @@ description: 'cert-manager installation: Upgrading v0.12 to v0.13'
---
When upgrading from `v0.12` to `v0.13`, no special upgrade steps are required.
-Follow the regular upgrade process [here](./README.md).
\ No newline at end of file
+Follow the regular upgrade process [here](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-0.13-0.14.md b/content/docs/releases/upgrading/upgrading-0.13-0.14.md
similarity index 94%
rename from content/docs/installation/upgrading/upgrading-0.13-0.14.md
rename to content/docs/releases/upgrading/upgrading-0.13-0.14.md
index ab170dd47a..22921cae0c 100644
--- a/content/docs/installation/upgrading/upgrading-0.13-0.14.md
+++ b/content/docs/releases/upgrading/upgrading-0.13-0.14.md
@@ -27,4 +27,4 @@ Version `v0.14` now comes in 2 versions of static manifests, you will need to us
The webhook is now a required component, meaning that `no-webhook` variant of the manifests are no longer available in this release. Please use the appropriate manifests as mentioned above according to your Kubernetes version.
-From here on you can follow the [regular upgrade process](./README.md).
\ No newline at end of file
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-0.14-0.15.md b/content/docs/releases/upgrading/upgrading-0.14-0.15.md
similarity index 91%
rename from content/docs/installation/upgrading/upgrading-0.14-0.15.md
rename to content/docs/releases/upgrading/upgrading-0.14-0.15.md
index 1815550067..629e556079 100644
--- a/content/docs/installation/upgrading/upgrading-0.14-0.15.md
+++ b/content/docs/releases/upgrading/upgrading-0.14-0.15.md
@@ -23,4 +23,4 @@ attached to the GitHub release. You will need to select the appropriate
'legacy' or full manifest variant depending on the Kubernetes or
OpenShift version you are running.
-From here on you can follow the [regular upgrade process](./README.md).
\ No newline at end of file
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-0.15-0.16.md b/content/docs/releases/upgrading/upgrading-0.15-0.16.md
similarity index 90%
rename from content/docs/installation/upgrading/upgrading-0.15-0.16.md
rename to content/docs/releases/upgrading/upgrading-0.15-0.16.md
index f6505fdc59..beb13e4459 100644
--- a/content/docs/installation/upgrading/upgrading-0.15-0.16.md
+++ b/content/docs/releases/upgrading/upgrading-0.15-0.16.md
@@ -13,4 +13,4 @@ Versions of `kubectl` of `v1.15.x` or below are not being supported anymore as t
### Helm
Helm users who use `installCRDs=true` MUST upgrade to Helm `v3.3.1` before upgrading.
-From here on you can follow the [regular upgrade process](./README.md).
\ No newline at end of file
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-0.16-1.0.md b/content/docs/releases/upgrading/upgrading-0.16-1.0.md
similarity index 92%
rename from content/docs/installation/upgrading/upgrading-0.16-1.0.md
rename to content/docs/releases/upgrading/upgrading-0.16-1.0.md
index 2358ec40a3..54fd19eb24 100644
--- a/content/docs/installation/upgrading/upgrading-0.16-1.0.md
+++ b/content/docs/releases/upgrading/upgrading-0.16-1.0.md
@@ -20,7 +20,7 @@ Helm users who use `installCRDs=true` MUST upgrade to Helm `v3.3.1` or later bef
### Kubernetes `1.16` and above
These are the upgrade instructions to upgrade from cert-manager `v0.14.0` or higher, please consult other upgrade guides first before upgrading to `v1.0` if you run an older version of cert-manager.
-No special requirements, you can follow the [regular upgrade process](./README.md).
+No special requirements, you can follow the [regular upgrade process](../../installation/upgrade.md).
### Kubernetes `1.15.x`
@@ -48,9 +48,9 @@ However you should convert the (Cluster)Issuers and delete the old CRD versions.
This upgrade MUST be performed in the following sequence of steps:
-1. [Back up](../../tutorials/backup.md) existing cert-manager resources. See the backup section.
+1. [Back up](../../devops-tips/backup.md) existing cert-manager resources. See the backup section.
-2. [Uninstall cert-manager](../uninstall.md).
+2. [Uninstall cert-manager](../../installation/uninstall.md).
3. Update the `apiVersion` on all your backed up resources from
`cert-manager.io/v1alpha2` to `cert-manager.io/v1`. See the converting section for that.
@@ -58,8 +58,8 @@ This upgrade MUST be performed in the following sequence of steps:
4. Ensure the old cert-manager CRD resources have also been deleted: `kubectl get crd | grep cert-manager.io`
-5. Re-install cert-manager `v1.0` from scratch according to the [installation
- guide](../README.md).
+5. Re-install cert-manager `v1.0` from scratch according to the
+ [installation guide](../../installation/upgrade.md).
6. Apply the backed up resources again.
@@ -114,10 +114,10 @@ kubectl delete crd issuers.cert-manager.io
kubectl delete crd orders.acme.cert-manager.io
```
-For more info see the [uninstall cert-manager guide](../uninstall.md).
+For more info see the [uninstall cert-manager guide](../../installation/uninstall.md).
#### Reinstall and restore
-To install cert-manager again you can follow the normal [installation guide](../README.md).
+To install cert-manager again you can follow the normal [installation guide](../../installation/upgrade.md).
Once it has been fully installed you can re-apply the converted resources:
```bash
diff --git a/content/docs/installation/upgrading/upgrading-0.2-0.3.md b/content/docs/releases/upgrading/upgrading-0.2-0.3.md
similarity index 100%
rename from content/docs/installation/upgrading/upgrading-0.2-0.3.md
rename to content/docs/releases/upgrading/upgrading-0.2-0.3.md
diff --git a/content/docs/installation/upgrading/upgrading-0.3-0.4.md b/content/docs/releases/upgrading/upgrading-0.3-0.4.md
similarity index 100%
rename from content/docs/installation/upgrading/upgrading-0.3-0.4.md
rename to content/docs/releases/upgrading/upgrading-0.3-0.4.md
diff --git a/content/docs/installation/upgrading/upgrading-0.4-0.5.md b/content/docs/releases/upgrading/upgrading-0.4-0.5.md
similarity index 100%
rename from content/docs/installation/upgrading/upgrading-0.4-0.5.md
rename to content/docs/releases/upgrading/upgrading-0.4-0.5.md
diff --git a/content/docs/installation/upgrading/upgrading-0.5-0.6.md b/content/docs/releases/upgrading/upgrading-0.5-0.6.md
similarity index 87%
rename from content/docs/installation/upgrading/upgrading-0.5-0.6.md
rename to content/docs/releases/upgrading/upgrading-0.5-0.6.md
index ab9a92770c..9fbc721e4a 100644
--- a/content/docs/installation/upgrading/upgrading-0.5-0.6.md
+++ b/content/docs/releases/upgrading/upgrading-0.5-0.6.md
@@ -25,7 +25,7 @@ Due to issues with the way Helm handles CRD resources in Helm charts, we have
now moved the installation of these resources into a separate YAML manifest
that must be installed with `kubectl apply` before upgrading the chart.
-You can follow the [regular upgrade guide](./README.md) as usual in order to upgrade
+You can follow the [regular upgrade guide](../../installation/upgrade.md) as usual in order to upgrade
from `v0.5` to `v0.6`.
## Upgrading with static manifests
@@ -37,7 +37,7 @@ We now also no longer ship different manifests for different configurations, in
favor of a single `cert-manager.yaml` file which should work for all Kubernetes
clusters from Kubernetes `v1.9` onward.
-You can follow the [regular upgrade guide](./README.md) as usual in order to upgrade from
+You can follow the [regular upgrade guide](../../installation/upgrade.md) as usual in order to upgrade from
`v0.5` to `v0.6`.
## Upgrading from older versions using Helm
@@ -50,7 +50,7 @@ This **will not** delete the Secret resources being used by your apps.
Before upgrading you will need to:
-1. Read and follow the [backup guide](../../tutorials/backup.md) to create a
+1. Read and follow the [backup guide](../../devops-tips/backup.md) to create a
backup of your configuration.
2. Delete the existing cert-manager Helm release (replacing 'cert-manager' with
@@ -69,7 +69,7 @@ $ kubectl delete crd \
clusterissuers.certmanager.k8s.io
```
-3. Perform a fresh install (as per the [installation guide](../README.md)
+3. Perform a fresh install (as per the [installation guide](../../installation/upgrade.md)
Install the cert-manager CRDs
```bash
@@ -91,7 +91,7 @@ $ helm install \
stable/cert-manager
```
-4. Follow the steps in the [restore guide](../../tutorials/backup.md) to
+4. Follow the steps in the [restore guide](../../devops-tips/backup.md) to
restore your configuration.
5. Verify that your Issuers and Certificate resources are 'Ready':
diff --git a/content/docs/installation/upgrading/upgrading-0.6-0.7.md b/content/docs/releases/upgrading/upgrading-0.6-0.7.md
similarity index 100%
rename from content/docs/installation/upgrading/upgrading-0.6-0.7.md
rename to content/docs/releases/upgrading/upgrading-0.6-0.7.md
diff --git a/content/docs/installation/upgrading/upgrading-0.7-0.8.md b/content/docs/releases/upgrading/upgrading-0.7-0.8.md
similarity index 98%
rename from content/docs/installation/upgrading/upgrading-0.7-0.8.md
rename to content/docs/releases/upgrading/upgrading-0.7-0.8.md
index d77a253205..084e1487a0 100644
--- a/content/docs/installation/upgrading/upgrading-0.7-0.8.md
+++ b/content/docs/releases/upgrading/upgrading-0.7-0.8.md
@@ -3,8 +3,8 @@ title: Upgrading from v0.7 to v0.8
description: 'cert-manager installation: Upgrading v0.7 to v0.8'
---
-Upgrading from `v0.7` to `v0.8` is possible using the regular [upgrade
-guide](./README.md).
+Upgrading from `v0.7` to `v0.8` is possible using the regular
+[upgrade guide](../../installation/upgrade.md).
All resources should continue to operate as before.
diff --git a/content/docs/installation/upgrading/upgrading-0.8-0.9.md b/content/docs/releases/upgrading/upgrading-0.8-0.9.md
similarity index 86%
rename from content/docs/installation/upgrading/upgrading-0.8-0.9.md
rename to content/docs/releases/upgrading/upgrading-0.8-0.9.md
index 3aa60c22c0..4adef854be 100644
--- a/content/docs/installation/upgrading/upgrading-0.8-0.9.md
+++ b/content/docs/releases/upgrading/upgrading-0.8-0.9.md
@@ -8,7 +8,7 @@ Due to a change in the API group that cert-manager deployments use
before applying the new version. This will cause downtime until the new version
has been applied. No data loss will occur during this operation however it is
always advised to backup your data during an upgrade, which you can follow
-[here](../../tutorials/backup.md). To perform this action run:
+[here](../../devops-tips/backup.md). To perform this action run:
```bash
$ kubectl delete deployments --namespace cert-manager \
@@ -18,4 +18,4 @@ $ kubectl delete deployments --namespace cert-manager \
```
After this operation, follow the standard upgrade process as defined in the
-[upgrade guide](./README.md).
\ No newline at end of file
+[upgrade guide](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-0.9-0.10.md b/content/docs/releases/upgrading/upgrading-0.9-0.10.md
similarity index 100%
rename from content/docs/installation/upgrading/upgrading-0.9-0.10.md
rename to content/docs/releases/upgrading/upgrading-0.9-0.10.md
diff --git a/content/docs/installation/upgrading/upgrading-1.0-1.1.md b/content/docs/releases/upgrading/upgrading-1.0-1.1.md
similarity index 68%
rename from content/docs/installation/upgrading/upgrading-1.0-1.1.md
rename to content/docs/releases/upgrading/upgrading-1.0-1.1.md
index 9c514a5193..86de90149e 100644
--- a/content/docs/installation/upgrading/upgrading-1.0-1.1.md
+++ b/content/docs/releases/upgrading/upgrading-1.0-1.1.md
@@ -4,4 +4,4 @@ description: 'cert-manager installation: Upgrading v1.0 to v1.1'
---
When upgrading from `v1.0` to `v1.1`, no special upgrade steps are required 🎉.
-From here on you can follow the [regular upgrade process](./README.md).
\ No newline at end of file
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-1.1-1.2.md b/content/docs/releases/upgrading/upgrading-1.1-1.2.md
similarity index 80%
rename from content/docs/installation/upgrading/upgrading-1.1-1.2.md
rename to content/docs/releases/upgrading/upgrading-1.1-1.2.md
index b97e85b9d7..18877b54ca 100644
--- a/content/docs/installation/upgrading/upgrading-1.1-1.2.md
+++ b/content/docs/releases/upgrading/upgrading-1.1-1.2.md
@@ -7,15 +7,15 @@ In an effort to introduce new features whilst keeping the project maintainable,
cert-manager now only supports Kubernetes down to version `v1.16`. This means
the `legacy` manifests have now been removed. Some users experience issues when
upgrading the legacy `CRD`s to `v1.2`. To solve this, you could replace the `CRD`s:
-1. Backup `cert-manager` resources as described in [the docs](../../tutorials/backup.md)
+1. Backup `cert-manager` resources as described in [the docs](../../devops-tips/backup.md)
2. Run `kubectl replace -f https://github.com/cert-manager/cert-manager/releases/download/v1.2.0/cert-manager.crds.yaml` to replace the CRDs.
3. Follow the standard upgrade process.
You can read more about supported Kubernetes versions
- [here](../supported-releases.md).
+ [here](../README.md).
In this release some features have been deprecated. Please read the [version
-1.2 release notes](../../release-notes/release-notes-1.2.md) for more details
+1.2 release notes](../../releases/release-notes/release-notes-1.2.md) for more details
and consider whether you are using any of these deprecated features before you
proceed with the upgrade.
-From here on you can follow the [regular upgrade process](./README.md).
\ No newline at end of file
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-1.10-1.11.md b/content/docs/releases/upgrading/upgrading-1.10-1.11.md
similarity index 91%
rename from content/docs/installation/upgrading/upgrading-1.10-1.11.md
rename to content/docs/releases/upgrading/upgrading-1.10-1.11.md
index ddbfd11e8b..caaf203f1e 100644
--- a/content/docs/installation/upgrading/upgrading-1.10-1.11.md
+++ b/content/docs/releases/upgrading/upgrading-1.10-1.11.md
@@ -22,4 +22,4 @@ There are additional details in the [Gateway API usage](../../usage/gateway.md)
## Next Steps
-From here on you can follow the [regular upgrade process](./README.md).
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
diff --git a/content/docs/releases/upgrading/upgrading-1.11-1.12.md b/content/docs/releases/upgrading/upgrading-1.11-1.12.md
new file mode 100644
index 0000000000..78348421c1
--- /dev/null
+++ b/content/docs/releases/upgrading/upgrading-1.11-1.12.md
@@ -0,0 +1,10 @@
+---
+title: Upgrading from v1.11 to v1.12
+description: 'cert-manager installation: Upgrading v1.11 to v1.12'
+---
+
+There are no breaking changes between cert-manager 1.11 and 1.12.
+
+## Next Steps
+
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
diff --git a/content/docs/releases/upgrading/upgrading-1.12-1.13.md b/content/docs/releases/upgrading/upgrading-1.12-1.13.md
new file mode 100644
index 0000000000..6cd4d4e503
--- /dev/null
+++ b/content/docs/releases/upgrading/upgrading-1.12-1.13.md
@@ -0,0 +1,21 @@
+---
+title: Upgrading from v1.12 to v1.13
+description: 'cert-manager installation: Upgrading v1.12 to v1.13'
+---
+
+When upgrading cert-manager from 1.12 to 1.13, in few cases you might need to take additional steps to ensure a smooth upgrade:
+
+1. **IMPORTANT NOTE**: If upgrading from a version below v1.12, upgrade to the latest v1.12 release before upgrading to v1.13. Otherwise, some certificates may be unexpectedly re-issued (see https://github.com/cert-manager/cert-manager/issues/6494#issuecomment-1816112309)
+
+2. BREAKING: If you deploy cert-manager using helm and have `.featureGates` value set, the features defined
+there will no longer be passed to cert-manager webhook, only to cert-manager controller. Use `webhook.featureGates` field
+instead to define features to be enabled on webhook. (https://github.com/cert-manager/cert-manager/pull/6093, https://github.com/irbekrm)
+
+3. Potentially breaking: If you were, for some reason, passing cert-manager controller's features to webhook's --feature-gates flag,
+this will now break (unless the webhook actually has a feature by that name). (https://github.com/cert-manager/cert-manager/pull/6093, https://github.com/irbekrm)
+
+4. Potentially breaking: Webhook validation of CertificateRequest resources is stricter now: all `KeyUsages` and `ExtendedKeyUsages` must be defined directly in the CertificateRequest resource, the encoded CSR can never contain more usages that defined there. (https://github.com/cert-manager/cert-manager/pull/6182, https://github.com/inteon)
+
+## Next Steps
+
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
diff --git a/content/docs/installation/upgrading/upgrading-1.2-1.3.md b/content/docs/releases/upgrading/upgrading-1.2-1.3.md
similarity index 94%
rename from content/docs/installation/upgrading/upgrading-1.2-1.3.md
rename to content/docs/releases/upgrading/upgrading-1.2-1.3.md
index 2aa5394fc8..a7a56e390b 100644
--- a/content/docs/installation/upgrading/upgrading-1.2-1.3.md
+++ b/content/docs/releases/upgrading/upgrading-1.2-1.3.md
@@ -29,4 +29,4 @@ This means users will need to create an Application in `OutagePREDICT` and assoc
## Next Steps
-You should now follow the [regular upgrade process](./README.md).
\ No newline at end of file
+You should now follow the [regular upgrade process](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-1.3-1.4.md b/content/docs/releases/upgrading/upgrading-1.3-1.4.md
similarity index 86%
rename from content/docs/installation/upgrading/upgrading-1.3-1.4.md
rename to content/docs/releases/upgrading/upgrading-1.3-1.4.md
index 71dce12965..d7befe89e1 100644
--- a/content/docs/installation/upgrading/upgrading-1.3-1.4.md
+++ b/content/docs/releases/upgrading/upgrading-1.3-1.4.md
@@ -24,8 +24,8 @@ and which is therefore available on
Please uninstall the existing cert-manager package and re-install
by following the [OLM Installation Documentation][].
-[OLM Installation Documentation]: ../operator-lifecycle-manager.md
+[OLM Installation Documentation]: ../../installation/operator-lifecycle-manager.md
## Now Follow the Regular Upgrade Process
-From here on you can follow the [regular upgrade process](./README.md).
\ No newline at end of file
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-1.4-1.5.md b/content/docs/releases/upgrading/upgrading-1.4-1.5.md
similarity index 82%
rename from content/docs/installation/upgrading/upgrading-1.4-1.5.md
rename to content/docs/releases/upgrading/upgrading-1.4-1.5.md
index f991809419..46385192ce 100644
--- a/content/docs/installation/upgrading/upgrading-1.4-1.5.md
+++ b/content/docs/releases/upgrading/upgrading-1.4-1.5.md
@@ -8,4 +8,4 @@ notes to see if your Ingress controller has any known issues with the migration
## Now Follow the Regular Upgrade Process
-From here on you can follow the [regular upgrade process](./README.md).
\ No newline at end of file
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-1.5-1.6.md b/content/docs/releases/upgrading/upgrading-1.5-1.6.md
similarity index 93%
rename from content/docs/installation/upgrading/upgrading-1.5-1.6.md
rename to content/docs/releases/upgrading/upgrading-1.5-1.6.md
index 4524d702db..e819e77947 100644
--- a/content/docs/installation/upgrading/upgrading-1.5-1.6.md
+++ b/content/docs/releases/upgrading/upgrading-1.5-1.6.md
@@ -27,4 +27,4 @@ notes to see if your Ingress controller has any known issues with the migration
## Now Follow the Regular Upgrade Process
-From here on you can follow the [regular upgrade process](./README.md).
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
diff --git a/content/docs/installation/upgrading/upgrading-1.6-1.7.md b/content/docs/releases/upgrading/upgrading-1.6-1.7.md
similarity index 92%
rename from content/docs/installation/upgrading/upgrading-1.6-1.7.md
rename to content/docs/releases/upgrading/upgrading-1.6-1.7.md
index d53d1eaf81..4b5e012dd4 100644
--- a/content/docs/installation/upgrading/upgrading-1.6-1.7.md
+++ b/content/docs/releases/upgrading/upgrading-1.6-1.7.md
@@ -21,4 +21,4 @@ on supported versions before `v1.22`.
## Now Follow the Regular Upgrade Process
-From here on you can follow the [regular upgrade process](./README.md).
\ No newline at end of file
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
\ No newline at end of file
diff --git a/content/docs/installation/upgrading/upgrading-1.7-1.8.md b/content/docs/releases/upgrading/upgrading-1.7-1.8.md
similarity index 97%
rename from content/docs/installation/upgrading/upgrading-1.7-1.8.md
rename to content/docs/releases/upgrading/upgrading-1.7-1.8.md
index 1faec63bf2..b65538b5ba 100644
--- a/content/docs/installation/upgrading/upgrading-1.7-1.8.md
+++ b/content/docs/releases/upgrading/upgrading-1.7-1.8.md
@@ -88,4 +88,4 @@ and add the `parentRefs`:
## Now, Follow the Regular Upgrade Process
-From here on you can follow the [regular upgrade process](./README.md).
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
diff --git a/content/docs/installation/upgrading/upgrading-1.8-1.9.md b/content/docs/releases/upgrading/upgrading-1.8-1.9.md
similarity index 80%
rename from content/docs/installation/upgrading/upgrading-1.8-1.9.md
rename to content/docs/releases/upgrading/upgrading-1.8-1.9.md
index b45f6cfb3c..5c61e8293a 100644
--- a/content/docs/installation/upgrading/upgrading-1.8-1.9.md
+++ b/content/docs/releases/upgrading/upgrading-1.8-1.9.md
@@ -8,4 +8,4 @@ If running Kubernetes versions before `v1.22`, the
feature gate _must_ be enabled in the cluster. This beta feature is enabled by default
on supported versions before `v1.22`.
-From here on you can follow the [regular upgrade process](./README.md).
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
diff --git a/content/docs/installation/upgrading/upgrading-1.9-1.10.md b/content/docs/releases/upgrading/upgrading-1.9-1.10.md
similarity index 81%
rename from content/docs/installation/upgrading/upgrading-1.9-1.10.md
rename to content/docs/releases/upgrading/upgrading-1.9-1.10.md
index 4a4f1310ec..76695893ba 100644
--- a/content/docs/installation/upgrading/upgrading-1.9-1.10.md
+++ b/content/docs/releases/upgrading/upgrading-1.9-1.10.md
@@ -10,8 +10,8 @@ is set to `RuntimeDefault`.
On some versions and configurations of OpenShift this can cause the Pod to be rejected by the
[Security Context Constraints admission webhook](https://docs.openshift.com/container-platform/4.10/authentication/managing-security-context-constraints.html#admission_configuring-internal-oauth).
-> 📖 Read the [Breaking Changes section in the 1.10 release notes](../../release-notes/release-notes-1.10.md) before upgrading.
+> 📖 Read the [Breaking Changes section in the 1.10 release notes](../../releases/release-notes/release-notes-1.10.md) before upgrading.
## Next Steps
-From here on you can follow the [regular upgrade process](./README.md).
+From here on you can follow the [regular upgrade process](../../installation/upgrade.md).
diff --git a/content/docs/troubleshooting/webhook.md b/content/docs/troubleshooting/webhook.md
index b842dcb9de..b749a9d40f 100644
--- a/content/docs/troubleshooting/webhook.md
+++ b/content/docs/troubleshooting/webhook.md
@@ -216,7 +216,6 @@ the webhook deployment, the argument `--healthz-port=6081` was mismatched with
the readiness configuration.
-
## Error: `i/o timeout` (connectivity issue)
> This error message was reported 26 times on Slack. To list these messages, do a search with `in:#cert-manager in:#cert-manager-dev "443: i/o timeout"`. The error message was reported in 2 GitHub issues ([#2811](https://github.com/cert-manager/cert-manager/issues/2811 "i/o timeout from apiserver when connecting to webhook on k3s"), [#4073](https://github.com/cert-manager/cert-manager/issues/4073 "Internal error occurred: failed calling webhook"))
@@ -242,7 +241,6 @@ inside the webhook's net namespace, we would see:
This issue is caused by the `SYN` packet being dropped somewhere.
-
### Cause 1: GKE Private Cluster
The default Helm configuration should work with GKE private clusters, but
@@ -552,7 +550,6 @@ Error from server (InternalError): error when creating "STDIN":
([1](https://kubernetes.slack.com/archives/C4NV3DWUC/p1632849763397100)).
-
## Error: `context deadline exceeded`
> This error message was reported in GitHub issues ([2319](https://github.com/cert-manager/cert-manager/issues/2319 "Documenting context deadline exceeded errors relating to the webhook, on bare metal"), [2706](https://github.com/cert-manager/cert-manager/issues/2706 "") [5189](https://github.com/cert-manager/cert-manager/issues/5189 "Post https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=10s: context deadline exceeded"), [5004](https://github.com/cert-manager/cert-manager/issues/5004 "After installing cert-manager using kubectl, cmctl check api fails with https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=10s: context deadline exceeded")), and once [on Stack Overflow](https://stackoverflow.com/questions/72059332/how-can-i-fix-failed-calling-webhook-webhook-cert-manager-io).
diff --git a/content/docs/trust/README.md b/content/docs/trust/README.md
new file mode 100644
index 0000000000..f8c86c1d40
--- /dev/null
+++ b/content/docs/trust/README.md
@@ -0,0 +1,30 @@
+---
+title: Trusting certificates
+description: "Managing client trust stores"
+---
+
+
+
+When configuring a client to connect to a TLS server with a serving certificate that is signed by a private CA,
+you will need to provide the client with the CA certificate in order for it to verify the server.
+`ca.crt` will likely contain the certificate you need to trust,
+but __do not mount the same `Secret` as the server__ to access `ca.crt`.
+This is because:
+
+1. That `Secret` also contains the private key of the server, which should only be accessible to the server.
+ You should use RBAC to ensure that the `Secret` containing the serving certificate and private key are only accessible to Pods that need it.
+2. Rotating CA certificates safely relies on being able to have both the old and new CA certificates trusted at the same time.
+ By consuming the CA directly from the source, this isn't possible;
+ you'll be _forced_ to have some down-time in order to rotate certificates.
+
+
+
+When configuring the client you should independently choose and fetch the CA certificates that you want to trust.
+Download the CA out of band and store it in a `Secret` or `ConfigMap` separate from the `Secret` containing the server's private key and certificate.
+[trust-manager](trust-manager) can be used to manage these certificates and automatically distribute them to multiple namespaces.
+
+This ensures that if the material in the `Secret` containing the server key and certificate is tampered with,
+the client will fail to connect to the compromised server.
+
+The same concept also applies when configuring a server for mutually-authenticated TLS;
+don't give the server access to Secret containing the client certificate and private key.
diff --git a/content/docs/projects/trust-manager/README.md b/content/docs/trust/trust-manager/README.md
similarity index 75%
rename from content/docs/projects/trust-manager/README.md
rename to content/docs/trust/trust-manager/README.md
index 30e388fbe1..3b88dd1957 100644
--- a/content/docs/projects/trust-manager/README.md
+++ b/content/docs/trust/trust-manager/README.md
@@ -21,19 +21,19 @@ and enables cluster administrators to easily automate providing a secure bundle
to worry about rebuilding containers to update trust stores.
It's designed to complement cert-manager and works well when consuming CA certificates from a
-cert-manager `Issuer` or `ClusterIssuer` but can be used entirely independently from cert-manager
+cert-manager `Issuer` or `ClusterIssuer` but can be used entirely independently of cert-manager
if needed.
## Usage
-trust-manager is intentionally simple, and adds one new Kubernetes `CustomResourceDefintion`: `Bundle`.
+trust-manager is intentionally simple, adding just one new Kubernetes `CustomResourceDefintion`: `Bundle`.
-A `Bundle` represents a set of PEM-encoded X.509 certificates that should be distributed and made
-available across the cluster. `Bundle`s are cluster scoped.
+A `Bundle` represents a set of X.509 certificates that should be distributed across a cluster.
-Users specify a list of `sources`, which trust-manager will query and concatenate certificate data from.
-The only other required field is the `target`, which describes how and where the resulting bundle will
-be written.
+All `Bundle`s are cluster scoped.
+
+`Bundle`s comprise a list of `sources` from which trust-manager will assemble the final bundle, along with
+a `target` describing how and where the resulting bundle will be written.
An example `Bundle` might look like this:
@@ -49,12 +49,12 @@ spec:
# those issued by Let's Encrypt, Google, Amazon and others.
- useDefaultCAs: true
- # A Secret in the trust-manager namespace
+ # A Secret in the "trust" namespace; see "Trust Namespace" below for further details
- secret:
name: "my-db-tls"
key: "ca.crt"
- # A ConfigMap in the trust-manager namespace
+ # A ConfigMap in the "trust" namespace; see "Trust Namespace" below for further details
- configMap:
name: "my-org.net"
key: "root-certs.pem"
@@ -67,10 +67,18 @@ spec:
0V3NCaQrXoh+3xrXgX/vMdijYLUSo/YPEWmo
-----END CERTIFICATE-----
target:
- # Data synced to the ConfigMap `my-org.com` at the key `root-certs.pem` in
- # every namespace that has the label "linkerd.io/inject=enabled".
+ # Sync the bundle to a ConfigMap called `my-org.com` in every namespace which
+ # has the label "linkerd.io/inject=enabled"
+ # All ConfigMaps will include a PEM-formatted bundle, here named "root-certs.pem"
+ # and in this case we also request binary formatted bundles in JKS and PKCS#12 formats,
+ # here named "bundle.jks" and "bundle.p12".
configMap:
key: "root-certs.pem"
+ additionalFormats:
+ jks:
+ key: "bundle.jks"
+ pkcs12:
+ key: "bundle.p12"
namespaceSelector:
matchLabels:
linkerd.io/inject: "enabled"
@@ -83,8 +91,23 @@ spec:
- `inLine` - a manually specified string containing at least one certificate
- `useDefaultCAs` - usually, a bundle of publicly trusted certificates
-These sources, along with the single currently supported target type (`configMap`)
-are documented in the trust-manager [API reference documentation](./api-reference.md).
+`ConfigMap` is the default target type, but as of v0.7.0 trust-manager also supports `Secret` resources as targets.
+
+Support for `Secret` targets must be explicitly enabled in the trust-manager controller; see details below under "Enable Secret targets".
+
+All sources and target options are documented in the trust-manager [API reference documentation](./api-reference.md).
+
+#### Targets
+
+All `Bundle` targets are written to `ConfigMap`s (and/or `Secret`s) whose name matches that of the
+`Bundle`, and every target has a PEM-formatted bundle included.
+
+Users can also optionally choose to write JKS/PKCS#12 formatted binary trust store(s) to targets.
+JKS has been supported since v0.5.0, and PKCS#12 since v0.7.0.
+
+Applications consuming JKS and PKCS#12 trust stores often require a password to be set for legacy reasons. These passwords are often security theater - either they use very weak encryption or the passwords are provided in plaintext next to the files they encrypt which defeats the purpose of having them.
+
+Trust bundles do not contain private keys, and so for most use cases there wouldn't be any security benefit to encrypting them. As such, passwords for trust stores are hard-coded to `changeit` for JKS and `""` (the empty string or "password-less") for PKCS#12. Future releases of trust-manager may make these passwords configurable.
#### Namespace Selector
@@ -117,12 +140,50 @@ helm upgrade -i -n cert-manager cert-manager jetstack/cert-manager --set install
helm upgrade -i -n cert-manager trust-manager jetstack/trust-manager --wait
```
+#### Enable Secret targets
+
+`Secret` targets are supported as of trust-manager v0.7.0, but need to be explicitly enabled on the controller.
+The feature can be enabled with a Helm value `--set secretTargets.enabled=true`, but since the controller needs
+RBAC to read and update secrets, you also need to set `secretTargets.authorizedSecretsAll` or `secretTargets.authorizedSecrets`.
+Please consult the
+[trust-manager Helm chart docs](https://github.com/cert-manager/trust-manager/blob/main/deploy/charts/trust-manager/README.md#values)
+for details and trade-offs.
+
+#### approver-policy Integration
+
+If you're running [approver-policy](../../policy/approval/approver-policy/README.md) then cert-manager's default approver will be disabled which will mean that
+trust-manager's webhook certificate will - by default - block when you install the Helm chart until it's manually approved.
+
+As of trust-manager v0.6.0 you can choose to automatically add an approver-policy `CertificateRequestPolicy` which
+will approve the trust-manager webhook certificate:
+
+```bash
+helm upgrade -i -n cert-manager trust-manager jetstack/trust-manager --set app.webhook.tls.approverPolicy.enabled=true --set app.webhook.tls.approverPolicy.certManagerNamespace=cert-manager --wait
+```
+
+Note that if you've installed cert-manager to a different namespace, you'll need to pass that namespace in `app.webhook.tls.approverPolicy.certManagerNamespace`!
+
### Manual Installation
We strongly recommend that you install trust-manager using Helm and we don't currently support manually installed
versions of trust-manager. This is so that we can focus on continuing to improve trust-manager with the resources
we currently have available.
+### Trust Namespace
+
+One of the more important configuration options you might need to consider at install time is which "trust namespace" to use,
+which can be set via the Helm value `app.trust.namespace`.
+
+By default, the trust namespace is the only namespace where`Secret`s will be read. This restriction is in place
+for security reasons - we don't want to give trust-manager the permission to read all `Secret`s in all namespaces. With additional configuration, secrets may be read from or written to other namespaces.
+
+The trust namespace defaults to `cert-manager`, but there's no need for it to be set to the namespace that cert-manager
+is installed in - trust-manager has no runtime dependency on cert-manager at all! - so we'd recommend setting the trust
+namespace to whichever is most appropriate for your environment.
+
+An ideal deployment would be a fresh namespace dedicated entirely to trust-manager, to minimize the number of actors in your
+cluster that can modify your trust sources.
+
## Quick Start Example
Let's get started with an example of creating our own `Bundle`!
diff --git a/content/docs/projects/trust-manager/api-reference.md b/content/docs/trust/trust-manager/api-reference.md
similarity index 64%
rename from content/docs/projects/trust-manager/api-reference.md
rename to content/docs/trust/trust-manager/api-reference.md
index 994e70ce3b..d0448f061f 100644
--- a/content/docs/projects/trust-manager/api-reference.md
+++ b/content/docs/trust/trust-manager/api-reference.md
@@ -226,6 +226,13 @@ Target is the target location in all namespaces to sync source data to.
@@ -239,6 +246,95 @@ Target is the target location in all namespaces to sync source data to.
NamespaceSelector will, if set, only sync the target resource in Namespaces which match the selector.
+ Secret is the target Secret that all Bundle source data will be synced to. Using Secrets as targets is only supported if enabled at trust-manager startup. By default, trust-manager has no permissions for writing to secrets and can only read secrets in the trust namespace.
+
+
false
+
+
+
+
+### `Bundle.spec.target.additionalFormats`
+
+
+AdditionalFormats specifies any additional formats to write to the target
+
+
+ PKCS12 requests a PKCS12-formatted binary trust bundle to be written to the target. The bundle is created without a password.
+
+
false
+
+
+
+
+### `Bundle.spec.target.additionalFormats.jks`
+
+
+JKS requests a JKS-formatted binary trust bundle to be written to the target. The bundle is created with the hardcoded password "changeit".
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
key
+
string
+
+ Key is the key of the entry in the object's `data` field to be used.
+
+
true
+
+
+
+
+### `Bundle.spec.target.additionalFormats.pkcs12`
+
+
+PKCS12 requests a PKCS12-formatted binary trust bundle to be written to the target. The bundle is created without a password.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
key
+
string
+
+ Key is the key of the entry in the object's `data` field to be used.
+
+
true
@@ -293,6 +389,31 @@ NamespaceSelector will, if set, only sync the target resource in Namespaces whic
+### `Bundle.spec.target.secret`
+
+
+Secret is the target Secret that all Bundle source data will be synced to. Using Secrets as targets is only supported if enabled at trust-manager startup. By default, trust-manager has no permissions for writing to secrets and can only read secrets in the trust namespace.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
key
+
string
+
+ Key is the key of the entry in the object's `data` field to be used.
+
+
true
+
+
+
+
### `Bundle.status`
@@ -411,6 +532,13 @@ Target is the current Target that the Bundle is attempting or has completed sync
@@ -424,6 +552,95 @@ Target is the current Target that the Bundle is attempting or has completed sync
NamespaceSelector will, if set, only sync the target resource in Namespaces which match the selector.
+ Secret is the target Secret that all Bundle source data will be synced to. Using Secrets as targets is only supported if enabled at trust-manager startup. By default, trust-manager has no permissions for writing to secrets and can only read secrets in the trust namespace.
+
+
false
+
+
+
+
+### `Bundle.status.target.additionalFormats`
+
+
+AdditionalFormats specifies any additional formats to write to the target
+
+
+ PKCS12 requests a PKCS12-formatted binary trust bundle to be written to the target. The bundle is created without a password.
+
+
false
+
+
+
+
+### `Bundle.status.target.additionalFormats.jks`
+
+
+JKS requests a JKS-formatted binary trust bundle to be written to the target. The bundle is created with the hardcoded password "changeit".
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
key
+
string
+
+ Key is the key of the entry in the object's `data` field to be used.
+
+
true
+
+
+
+
+### `Bundle.status.target.additionalFormats.pkcs12`
+
+
+PKCS12 requests a PKCS12-formatted binary trust bundle to be written to the target. The bundle is created without a password.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
key
+
string
+
+ Key is the key of the entry in the object's `data` field to be used.
+
+
true
@@ -476,3 +693,28 @@ NamespaceSelector will, if set, only sync the target resource in Namespaces whic
false
+
+
+### `Bundle.status.target.secret`
+
+
+Secret is the target Secret that all Bundle source data will be synced to. Using Secrets as targets is only supported if enabled at trust-manager startup. By default, trust-manager has no permissions for writing to secrets and can only read secrets in the trust namespace.
+
+
+
+
+
Name
+
Type
+
Description
+
Required
+
+
+
+
key
+
string
+
+ Key is the key of the entry in the object's `data` field to be used.
+
+
true
+
+
diff --git a/content/docs/tutorials/README.md b/content/docs/tutorials/README.md
index cc839b6b10..b286d96594 100644
--- a/content/docs/tutorials/README.md
+++ b/content/docs/tutorials/README.md
@@ -12,8 +12,6 @@ for you to learn from. Take a look!
Learn how to deploy cert-manager on Google Kubernetes Engine and how to configure it to get certificates for Ingress, from Let's Encrypt.
- [AKS + LoadBalancer + Let's Encrypt](getting-started-aks-letsencrypt/README.md):
Learn how to deploy cert-manager on Azure Kubernetes Service (AKS) and how to configure it to get certificates for an HTTPS web server, from Let's Encrypt.
-- [Backup and Restore Resources](./backup.md): Backup the cert-manager resources
- in your cluster and then restore them.
- [Pomerium Ingress](./acme/pomerium-ingress.md): Tutorial on using the Pomerium Ingress Controller with cert-manager.
- [Issuing an ACME Certificate using DNS Validation](./acme/dns-validation.md):
Tutorial on how to resolve DNS ownership validation using DNS01 challenges.
@@ -26,8 +24,6 @@ for you to learn from. Take a look!
certificate.
- [Securing an Istio service mesh with cert-manager](./istio-csr/istio-csr.md): Tutorial for
securing an Istio service mesh using a cert-manager issuer.
-- [Syncing Secrets Across Namespaces](./syncing-secrets-across-namespaces.md):
- Learn how to synchronize Kubernetes Secret resources across namespaces using extensions such as: reflector, kubed and kubernetes-replicator.
- [Obtaining SSL certificates with the ZeroSSL](./zerossl/zerossl.md): Tutorial describing usage of the ZeroSSL as external ACME server.
### External Tutorials
diff --git a/content/docs/tutorials/acme/example/staging-issuer.yaml b/content/docs/tutorials/acme/example/staging-issuer.yaml
index baea1537f9..9b0f337256 100644
--- a/content/docs/tutorials/acme/example/staging-issuer.yaml
+++ b/content/docs/tutorials/acme/example/staging-issuer.yaml
@@ -1,18 +1,18 @@
- apiVersion: cert-manager.io/v1
- kind: Issuer
- metadata:
- name: letsencrypt-staging
- spec:
- acme:
- # The ACME server URL
- server: https://acme-staging-v02.api.letsencrypt.org/directory
- # Email address used for ACME registration
- email: user@example.com
- # Name of a secret used to store the ACME account private key
- privateKeySecretRef:
- name: letsencrypt-staging
- # Enable the HTTP-01 challenge provider
- solvers:
- - http01:
- ingress:
- ingressClassName: nginx
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ # The ACME server URL
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ # Email address used for ACME registration
+ email: user@example.com
+ # Name of a secret used to store the ACME account private key
+ privateKeySecretRef:
+ name: letsencrypt-staging
+ # Enable the HTTP-01 challenge provider
+ solvers:
+ - http01:
+ ingress:
+ ingressClassName: nginx
diff --git a/content/docs/tutorials/acme/http-validation.md b/content/docs/tutorials/acme/http-validation.md
index b61bf7c14b..5abc937c04 100644
--- a/content/docs/tutorials/acme/http-validation.md
+++ b/content/docs/tutorials/acme/http-validation.md
@@ -84,7 +84,7 @@ spec:
The Certificate resource describes our desired certificate and the possible
methods that can be used to obtain it. You can learn more about the Certificate
-resource in the [docs](../../concepts/certificate.md). If the certificate is
+resource in the [docs](../../usage/certificate.md). If the certificate is
obtained successfully, the resulting key pair will be stored in a secret called
`example-com-tls` in the same namespace as the Certificate.
diff --git a/content/docs/tutorials/acme/nginx-ingress.md b/content/docs/tutorials/acme/nginx-ingress.md
index 6b98f348e3..c7cf9f1568 100644
--- a/content/docs/tutorials/acme/nginx-ingress.md
+++ b/content/docs/tutorials/acme/nginx-ingress.md
@@ -136,7 +136,7 @@ it is saved:
```bash
kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/ingress.yaml
-# expected output: ingress.extensions "kuard" created
+# expected output: ingress.networking.k8s.io/kuard created
```
> Note: The ingress example we show above has a `host` definition within it. The
@@ -237,7 +237,7 @@ when you might choose to use each can be found on [Issuer concepts](../../concep
Certificates resources allow you to specify the details of the certificate you
want to request. They reference an issuer to define _how_ they'll be issued.
-For more information, see [Certificate concepts](../../concepts/certificate.md).
+For more information, see [Certificate concepts](../../usage/certificate.md).
## Step 6 - Configure a Let's Encrypt Issuer
@@ -348,7 +348,7 @@ and apply it:
```bash
kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/ingress-tls.yaml
-# expected output: ingress.extensions "kuard" configured
+# expected output: ingress.networking.k8s.io/kuard configured
```
Cert-manager will read these annotations and use them to create a certificate,
@@ -447,7 +447,7 @@ can update the annotations in the ingress to specify the production issuer:
```bash
$ kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/ingress-tls-final.yaml
-ingress.extensions "kuard" configured
+ingress.networking.k8s.io/kuard configured
```
You will also need to delete the existing secret, which cert-manager is watching
diff --git a/content/docs/tutorials/getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/README.md b/content/docs/tutorials/getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/README.md
index 80f233aee7..21bde539ca 100644
--- a/content/docs/tutorials/getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/README.md
+++ b/content/docs/tutorials/getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/README.md
@@ -628,7 +628,7 @@ Events:
When you create a Certificate, cert-manager will create a collection of temporary resources
which each contain information about the status of certificate signing process.
-You can read more about these in the [Certificate Lifecycle](../../concepts/certificate.md#certificate-lifecycle) section.
+You can read more about these in the [Certificate Lifecycle](../../usage/certificate.md#certificate-lifecycle) section.
Use the `cmctl status` command to view details of all these resources and all the associated Events and error messages.
You may see some temporary errors, like:
diff --git a/content/docs/tutorials/getting-started-with-trust-manager/README.md b/content/docs/tutorials/getting-started-with-trust-manager/README.md
new file mode 100644
index 0000000000..afeec714f1
--- /dev/null
+++ b/content/docs/tutorials/getting-started-with-trust-manager/README.md
@@ -0,0 +1,603 @@
+---
+title: Managing public trust in kubernetes with trust-manager
+description: Learn how to deploy and configure trust-manager to automatically distribute your approved Public CA configuration to your Kubernetes cluster.
+---
+
+*Last Verified: 19 June 2023*
+
+In this tutorial we will walk through how we can use
+[trust-manager](https://cert-manager.io/docs/trust/trust-manager/) to
+distribute publicly trusted Certificate Authority (CA) certificates inside
+a Kubernetes cluster. Once distributed we will also show:
+
+- How you can automatically reload applications when your trust bundle changes
+- How you can enforce applications to use your distributed CA bundle
+
+From there we will use a simple `curl` pod to show how to automatically mount
+the trusted CA `Bundle`, so it can be used without having to configure curl
+manually. This mimics how an application would not need any additional
+configuration to make use of your trusted CA certificates bundle.
+
+In this tutorial we will be limiting the scope of our changes to only impact
+the `team-a` namespace. To get the most out of these features you will want
+to remove this limitation.
+
+> **Note:** All resources provided are demonstrative and should be reviewed
+ properly before using in production environments.
+
+## Prerequisites
+
+**💻 Software**
+
+1. [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl): The Kubernetes
+command-line tool which allows you to configure Kubernetes clusters.
+1. [helm](https://helm.sh/): A package manager for Kubernetes.
+1. [yq](https://github.com/mikefarah/yq#install): A command line tool for
+parsing YAML with helpful coloring.
+
+## Distribute Public CA Trust
+
+Let us first setup trust-manager and have our public CAs distributed to our
+demo namespace: `team-a`.
+
+### Setup Application & Bundle
+
+1) Install trust-manager following the
+ [instructions here](../../trust/trust-manager/README.md#installation).
+
+1) Create your first `Bundle` resource including only Public CA certificates
+
+ ```yaml file=./trust/bundle-public.yaml
+ ```
+
+ ```shell
+ kubectl apply -f - < **Note**: this is to limit the scope of our trust bundle to only the
+ `team-a` namespace as mentioned previously.
+
+1) Verify that the trust-manager controller has correctly propagated the
+ CA bundle to the namespace:
+
+ ```shell
+ kubectl get configmap -n team-a public-bundle -o yaml
+ ```
+
+ Note that this output should be quite long. This is because the default
+ public bundle that we use has a lot of public CAs in it.
+
+### Mount Trust Bundle to Application with Automatic Use
+
+To use our trusted CAs we will mount them to the application in a default
+location that most applications expect to find a `ca-certificates.crt` file.
+The benefit to this approach is that most application code inside the container
+will use this file by default and not require any additional configuration. There is the added benefit that you will be mounting over the top of
+`/etc/ssl/certs` which will remove existing CA certificates, usually
+present from a container base image or pulled in during CI builds.
+
+> **WARNING:** We have chosen one well known location in this example which
+ is used by alpine and `curl` for sourcing trusted CAs. This is not the only
+ location that can be used, so a container may have other default locations.
+ If you want to see where default CAs are located you can use
+ [paranoia](https://github.com/jetstack/paranoia) to inspect a built container
+ image.
+
+1) Apply the application deployment:
+
+ ```yaml file=./trust/deploy-auto.yaml
+ ```
+
+ ```shell
+ kubectl apply -f - < ..data/ca-certificates.crt
+ ```
+
+ Note that normally this container image the output would look something
+ like the following, when there is no volume overriding this directory:
+
+ ```
+ ~ $ ls -ltr /etc/ssl/certs/
+ total 608
+ -rw-r--r-- 1 root root 214222 Apr 14 01:11 ca-certificates.crt
+ lrwxrwxrwx 1 root root 52 Apr 14 01:11 ca-cert-vTrus_Root_CA.pem -> /usr/share/ca-certificates/mozilla/vTrus_Root_CA.crt
+ lrwxrwxrwx 1 root root 56 Apr 14 01:11 ca-cert-vTrus_ECC_Root_CA.pem -> /usr/share/ca-certificates/mozilla/vTrus_ECC_Root_CA.crt
+ ...
+ lrwxrwxrwx 1 root root 53 Apr 14 01:11 02265526.0 -> ca-cert-Entrust_Root_Certification_Authority_-_G2.pem
+ lrwxrwxrwx 1 root root 31 Apr 14 01:11 002c0b4f.0 -> ca-cert-GlobalSign_Root_R46.pem
+ ```
+
+1) Make a HTTPS call out to a well known site to validate `curl` works without
+having to pass the additional `--cacert` flag:
+
+ ```shell
+ curl -v https://bbc.co.uk/news
+ ```
+
+ Success will result in a valid TLS connection such as:
+
+ ```
+ * Trying 151.101.0.81:443...
+ * Connected to bbc.co.uk (151.101.0.81) port 443 (#0)
+ * ALPN: offers h2,http/1.1
+ * TLSv1.3 (OUT), TLS handshake, Client hello (1):
+ * CAfile: /etc/ssl/certs/ca-certificates.crt
+ * CApath: none
+ * TLSv1.3 (IN), TLS handshake, Server hello (2):
+ * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
+ * TLSv1.3 (IN), TLS handshake, Certificate (11):
+ * TLSv1.3 (IN), TLS handshake, CERT verify (15):
+ * TLSv1.3 (IN), TLS handshake, Finished (20):
+ * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
+ * TLSv1.3 (OUT), TLS handshake, Finished (20):
+ * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
+ * ALPN: server accepted h2
+ * Server certificate:
+ * subject: C=GB; ST=London; L=London; O=BRITISH BROADCASTING CORPORATION; CN=www.bbc.com
+ * start date: Mar 14 06:16:13 2023 GMT
+ * expire date: Apr 14 06:16:12 2024 GMT
+ * subjectAltName: host "bbc.co.uk" matched cert's "bbc.co.uk"
+ * issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign RSA OV SSL CA 2018
+ * SSL certificate verify ok.
+ ```
+
+1. Exit the container: `exit`
+
+## Configure Real Applications
+
+Based on the example above, Kubernetes is able to mount over the top of the
+default CA certificate bundle. You can use this with applications assuming you
+know where the default locations they retrieve CA certificates from.
+
+For example with `Go` your application is configurable with either
+`SSL_CERT_FILE` or `SSL_CERT_DIR` to point to the default CA certificate
+file location.
+
+See more details [here](https://go.dev/src/crypto/x509/root_unix.go) and
+for the default locations on various OS bases, check
+[here](https://go.dev/src/crypto/x509/root_linux.go)
+
+```go
+// Possible certificate files; stop after finding one.
+var certFiles = []string{
+ "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
+ "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
+ "/etc/ssl/ca-bundle.pem", // OpenSUSE
+ "/etc/pki/tls/cacert.pem", // OpenELEC
+ "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
+ "/etc/ssl/cert.pem", // Alpine Linux
+}
+
+// Possible directories with certificate files; all will be read.
+var certDirectories = []string{
+ "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139
+ "/etc/pki/tls/certs", // Fedora/RHEL
+ "/
+```
+
+Having checked Python the `ssl` library uses the same two environment variables
+for finding the trusted CAs: `SSL_CERT_DIR` and / or `SSL_CERT_FILE`. You can
+verify this [in documentation](https://docs.python.org/3/library/ssl.html#ssl.get_default_verify_paths)
+and from a `python3` runtime:
+
+```python3
+>>> import ssl
+>>> ssl.get_default_verify_paths()
+DefaultVerifyPaths(cafile=None, capath='/usr/lib/ssl/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/lib/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/lib/ssl/certs')
+```
+
+This should mean that any CAs mounted in a file and any of the following files
+will be trusted by any python application runtime, similar to `Go`:
+
+- '/usr/lib/ssl/cert.pem'
+- '/usr/lib/ssl/certs/*'
+
+Similar could be achieved with other languages.
+
+## Automate and Enforce
+
+So now we have mounted trust-manager's bundle manually, you might be thinking:
+
+- What happens if the CA Bundle is changed, how do I get that change to my
+ application?
+- How do I ensure that my CA Bundle is mounted to all applications in my
+ cluster without having to request changes from my tenants?
+
+Let's tackle both of these scenarios using additional Open Source tools.
+
+### Rollout CA Bundle Changes
+
+If your CA bundle changes, those changes will be synced to the namespaces
+pretty quickly. This change will be reflected in the volume attached to the
+container, but most applications will not pickup on the file system change.
+The common approach is restarting the client application deployment, through
+the use of `kubectl rollout restart deployment `. There is an
+option to automate this process through a third party piece of open-source
+software.
+
+Using [Stakater Reloader](https://github.com/stakater/Reloader) it is
+possible to reload or rollout a deployment whenever a `ConfigMap` or `Secret`
+changes. So whenever the `Bundle`'s target is synced, the Reloader component
+can pick up this change and rollout applications mounting those resource
+as volumes or environment variables.
+
+**Please note** that there are many alternative pieces of software that you
+could bundle or write into your application container. They would simply watch
+the file system for changes and trigger a reload of the application process.
+Such an approach requires container image or code changes and this could be
+difficult to implement with many tenants. The advantage to using reloader here
+is that it's a generic solution, applicable to all applications running in a
+cluster.
+
+1. Continuing with the reloader, it can be installed with helm:
+
+ ```shell
+ helm repo add stakater https://stakater.github.io/stakater-charts
+ helm repo update
+ helm install reloader stakater/reloader -n stakater-reloader --create-namespace --set fullnameOverride=reloader
+ ```
+
+1. We can reuse the deployment `sleep-auto` from the previous section and
+ configured it to enabled the reload functionality:
+
+ ```shell
+ kubectl annotate deployment -n team-a sleep-auto reloader.stakater.com/auto="true"
+ ```
+
+ **Please note** there are several configuration options to configure
+ the reloader tooling and this is only the most basic example. Refer to
+ [the documentation](https://github.com/stakater/Reloader#how-to-use-reloader)
+ for more detailed examples.
+
+1. In another terminal watch the application rollout:
+
+ ```shell
+ kubectl get po -n team-a -w
+ ```
+
+1. To test this change we can edit our `Bundle` resource to remove all the
+ default Public CA certificates and only provide one CA certificate instead:
+
+ ```yaml file=./trust/bundle-one-ca.yaml
+ ```
+
+ ```shell
+ kubectl apply -f - <
+
+
+
Once an [`Issuer`](../configuration/README.md) has been configured, you're ready to issue your first certificate!
There are several use cases and methods for requesting certificates through cert-manager:
-- [Certificate Resources](./certificate.md): The simplest and most common method for
- requesting signed certificates.
- [Securing Ingress Resources](./ingress.md): A method to secure ingress resources
in your cluster.
- [Securing OpenFaaS functions](https://docs.openfaas.com/reference/ssl/kubernetes-with-cert-manager/):
@@ -16,16 +18,13 @@ There are several use cases and methods for requesting certificates through cert
- [Integration with Garden](https://docs.garden.io/guides/cert-manager-integration): Garden is a
developer tool for developing Kubernetes applications which has first class
support for integrating cert-manager.
-- [Securing Knative](https://knative.dev/docs/serving/using-auto-tls/): Secure
+- [Securing Knative](https://knative.dev/docs/serving/encryption/enabling-automatic-tls-certificate-provisioning/): Secure
your Knative services with trusted HTTPS certificates.
- [Enable mTLS on Pods with CSI](./csi.md): Using the cert-manager CSI
driver to provide unique keys and certificates that share the lifecycle of
pods.
- [Securing Istio Gateway](https://istio.io/docs/tasks/traffic-management/ingress/ingress-certmgr/):
Secure your Istio Gateway in Kubernetes using cert-manager.
-- [Securing Istio Service Mesh](./istio.md): Using the cert-manager
+- [Securing Istio Service Mesh](./istio-csr.md): Using the cert-manager
[Istio](https://istio.io) integration, secure the mTLS PKI for each pod
through cert-manager managed certificates.
-- [Policy for cert-manager certificates](./approver-policy.md): Manage
- what cert-manager certificates are able to be signed or rejected through
- custom resource defined policy.
diff --git a/content/docs/usage/certificate.md b/content/docs/usage/certificate.md
index d0bce92755..264a798067 100644
--- a/content/docs/usage/certificate.md
+++ b/content/docs/usage/certificate.md
@@ -1,12 +1,23 @@
---
-title: Certificate Resources
+title: Certificate resource
description: 'cert-manager usage: Certificates'
---
-In cert-manager, the [`Certificate`](../concepts/certificate.md) resource
-represents a human readable definition of a certificate request that is to be
-honored by an issuer which is to be kept up-to-date. This is the usual way that
-you will interact with cert-manager to request signed certificates.
+> **apiVersion:** cert-manager.io/v1
+> **kind:** Certificate
+
+
+
+
+
+In cert-manager, the `Certificate` resource represents a human readable definition
+of a certificate request. cert-manager uses this input to generate a private key
+and [`CertificateRequest`](./certificaterequest.md) resource in order to obtain
+a signed certificate from an [`Issuer`](../configuration/README.md) or
+[`ClusterIssuer`](../configuration/README.md). The signed certificate and private
+key are then stored in the specified `Secret` resource. cert-manager will ensure
+that the certificate is [auto-renewed before it expires](#renewal-reissuance) and
+[re-issued if requested](#non-renewal-reissuance).
In order to issue any certificates, you'll need to configure an
[`Issuer`](../configuration/README.md) or [`ClusterIssuer`](../configuration/README.md)
@@ -117,7 +128,33 @@ The `Certificate` will be issued using the issuer named `ca-issuer` in the
A full list of the fields supported on the Certificate resource can be found in
the [API reference documentation](../reference/api-docs.md#cert-manager.io/v1.CertificateSpec).
-
X.509 key usages and extended key usages
+### Target Secret
+
+When a certificate is issued by an intermediate CA and the `Issuer` can provide
+the issued certificate's chain, the contents of `tls.crt` will be the requested
+certificate followed by the certificate chain.
+
+Additionally, if the Certificate Authority is known, the corresponding CA
+certificate will be stored in the secret with key `ca.crt`. For example, with
+the ACME issuer, the CA is not known and `ca.crt` will not exist in the Secret.
+The `ca.crt` value at the time of issuance can be copied to the trust store of
+the application that is using the certificate. However, DO NOT directly mount
+the `ca.crt` value into the application's trust store, as it will be updated
+when the certificate is renewed (see [Trusting certificates](../trust/README.md) for more details).
+
+cert-manager intentionally avoids adding root certificates to `tls.crt`, because they
+are useless in a situation where TLS is being done securely. For more information,
+see [RFC 5246 section 7.4.2](https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.2)
+which contains the following explanation:
+
+> Because certificate validation requires that root keys be distributed
+> independently, the self-signed certificate that specifies the root
+> certificate authority MAY be omitted from the chain, under the
+> assumption that the remote end must already possess it in order to
+> validate it in any case.
+
+
+### X.509 key usages and extended key usages
cert-manager supports requesting certificates that have a number of [custom key
usages](https://tools.ietf.org/html/rfc5280#section-4.2.1.3) and [extended key
@@ -134,34 +171,163 @@ certificate does not match the current key usage set.
An exhaustive list of supported key usages can be found in the [API reference
documentation](../reference/api-docs.md#cert-manager.io/v1.KeyUsage).
-
Temporary Certificates while Issuing
-On old GKE versions (`1.10.7-gke.1` and below), when requesting certificates
-[using the ingress-shim](./ingress.md) alongside the
-[`ingress-gce`](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress)
-ingress controller, `ingress-gce`
-[required](https://github.com/kubernetes/ingress-gce/pull/388) a temporary
-certificate must be present while waiting for the issuance of a signed
-certificate. Note that this issue was
-[solved](https://github.com/cert-manager/cert-manager/issues/606#issuecomment-424397233)
-in `1.10.7-gke.2`.
+### Additional Certificate Output Formats
+
+
+
+⛔️ The additional certificate output formats feature is currently in an
+_experimental_ alpha state, and is subject to breaking changes or complete
+removal in future releases. This feature is only enabled by adding it to the
+`--feature-gates` flag on the cert-manager controller and webhook components:
+
+```bash
+--feature-gates=AdditionalCertificateOutputFormats=true
+```
+
+
+
+`additionalOutputFormats` is a field on the Certificate `spec` that allows
+specifying additional supplementary formats of issued certificates and their
+private key. There are currently two supported additional output formats:
+`CombinedPEM` and `DER`. Both output formats can be specified on the same
+Certificate.
```yaml
-# Required for GKE 1.10.7-gke.1 and below.
-cert-manager.io/issue-temporary-certificate": "true"
+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:
+ tls.key:
+ tls.crt:
+ tls-combined.pem:
+ key.der:
```
-That made sure that a temporary self-signed certificate was present in the
-`Secret`. The self-signed certificate was replaced with the signed certificate
-later on.
+#### `CombinedPEM`
+
+The `CombinedPEM` type will create a new key entry in the resulting
+Certificate's Secret `tls-combined.pem`. This entry will contain the PEM encoded
+private key, followed by at least one new line character, followed by the PEM
+encoded signed certificate chain-
+
+```text
+ + "\n" +
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: my-cert-tls
+type: kubernetes.io/tls
+data:
+ tls-combined.pem:
+ ...
+```
+
+#### `DER`
+
+The `DER` type will create a new key entry in the resulting Certificate's Secret
+`key.der`. This entry will contain the DER binary format of the private key.
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: my-cert-tls
+type: kubernetes.io/tls
+data:
+ key.der:
+ ...
+```
+
+## Issuance triggers
+
+
+### Reissuance triggered by expiry (renewal)
+
+cert-manager will automatically renew `Certificate`s. It will calculate _when_ to renew a `Certificate` based on the issued X.509 certificate's duration and a 'renewBefore' value which specifies _how long_ before expiry a certificate should be renewed.
+
+`spec.duration` and `spec.renewBefore` fields on a `Certificate` can be used to specify an X.509 certificate's duration and a 'renewBefore' value. Default value for `spec.duration` is 90 days. Some issuers might be configured to only issue certificates with a set duration, so the actual duration may be different.
+Minimum value for `spec.duration` is 1 hour and minimum value for `spec.renewBefore` is 5 minutes.
+It is also required that `spec.duration` > `spec.renewBefore`.
+
+Once an X.509 certificate has been issued, cert-manager will calculate the renewal time for the `Certificate`. By default this will be 2/3 through the X.509 certificate's duration. If `spec.renewBefore` has been set, it will be `spec.renewBefore` amount of time before expiry. cert-manager will set `Certificate`'s `status.RenewalTime` to the time when the renewal will be attempted.
+
+
+
+### Reissuance triggered by user actions
+
+A certificate object is reissued under the following circumstances:
+
+- when a change is made to one of the following fields on the Certificate's
+ spec: `commonName`, `dnsNames`, `ipAddresses`, `uris`, `emailAddresses`,
+ `subject`, `isCA`, `usages`, `duration` or `issuerRef`;
+ A more detailed explanation can be found on the [FAQ page](../faq/README.md#when-do-certs-get-re-issued).
+- when a reissuance is manually triggered with the following:
+ ```sh
+ cmctl renew cert-1
+ ```
+ Note that the above command requires [cmctl](../reference/cmctl.md#renew).
+
+
+
+**❌** Deleting the Secret resource associated with a Certificate resource is
+**not a recommended solution** for manually rotating the private key. The
+recommended way to manually rotate the private key is to trigger the reissuance
+of the Certificate resource with the following command (requires
+[`cmctl`](../reference/cmctl.md#renew)):
+
+```sh
+cmctl renew cert-1
+```
+
+
-
Rotation of the private key
+
+## Issuance behavior: Temporary Certificates while Issuing
+
+When requesting certificates [using the ingress-shim](./ingress.md), the
+component `ingress-gce`, if used, requires that a temporary certificate is
+present while waiting for the issuance of a signed certificate when serving. To
+facilitate this, if the following annotation:
+
+ ```yaml
+ cert-manager.io/issue-temporary-certificate: "true"
+ ```
+
+is present on the certificate, a self-signed temporary certificate will be
+present on the `Secret` until it is overwritten once the signed certificate has
+been issued.
+
+Adding the following annotation on an ingress will automatically set "issue-temporary-certificate" on the certificate:
+
+ ```yaml
+ acme.cert-manager.io/http01-edit-in-place: "true"
+ ```
+
+
+## Issuance behavior: Rotation of the private key
By default, the private key won't be rotated automatically. Using the setting
`rotationPolicy: Always`, the private key Secret associated with a Certificate
-object can be configured to be rotated as soon as an action triggers the
-reissuance of the Certificate object (see
-[Actions that will trigger a rotation of the private key](#actions-triggering-private-key-rotation) below).
+object can be configured to be rotated as soon as an the Certificate is reissued (see
+[Issuance triggers](#issuance-triggers)).
With `rotationPolicy: Always`, cert-manager waits until the Certificate
object is correctly signed before overwriting the `tls.key` file in the
@@ -201,38 +367,7 @@ spec:
rotationPolicy: Always # 🔰 Here.
```
-
Actions that will trigger a rotation of the private key
-
-Setting the `rotationPolicy: Always` won't rotate the private key immediately.
-In order to rotate the private key, the certificate objects must be reissued. A
-certificate object is reissued under the following circumstances:
-
-- when the X.509 certificate is nearing expiry, which is when the Certificate's
- `status.renewalTime` is reached;
-- when a change is made to one of the following fields on the Certificate's
- spec: `commonName`, `dnsNames`, `ipAddresses`, `uris`, `emailAddresses`,
- `subject`, `isCA`, `usages`, `duration` or `issuerRef`;
-- when a reissuance is manually triggered with the following:
- ```sh
- cmctl renew cert-1
- ```
- Note that the above command requires [cmctl](../reference/cmctl.md#renew).
-
-
-
-**❌** Deleting the Secret resource associated with a Certificate resource is
-**not a recommended solution** for manually rotating the private key. The
-recommended way to manually rotate the private key is to trigger the reissuance
-of the Certificate resource with the following command (requires
-[`cmctl`](../reference/cmctl.md#renew)):
-
-```sh
-cmctl renew cert-1
-```
-
-
-
-### The `rotationPolicy` setting
+#### The `rotationPolicy` setting
The possible values for `rotationPolicy` are:
@@ -273,96 +408,8 @@ The `Secret` needs to be manually deleted if it is no longer needed.
If you would prefer the `Secret` to be deleted automatically when the `Certificate` is deleted, you need to configure your installation to pass the `--enable-certificate-owner-ref` flag to the controller.
-## Renewal
-
-cert-manager will automatically renew `Certificate`s. It will calculate _when_ to renew a `Certificate` based on the issued X.509 certificate's duration and a 'renewBefore' value which specifies _how long_ before expiry a certificate should be renewed.
-
-`spec.duration` and `spec.renewBefore` fields on a `Certificate` can be used to specify an X.509 certificate's duration and a 'renewBefore' value. Default value for `spec.duration` is 90 days. Some issuers might be configured to only issue certificates with a set duration, so the actual duration may be different.
-Minimum value for `spec.duration` is 1 hour and minimum value for `spec.renewBefore` is 5 minutes.
-It is also required that `spec.duration` > `spec.renewBefore`.
-
-Once an X.509 certificate has been issued, cert-manager will calculate the renewal time for the `Certificate`. By default this will be 2/3 through the X.509 certificate's duration. If `spec.renewBefore` has been set, it will be `spec.renewBefore` amount of time before expiry. cert-manager will set `Certificate`'s `status.RenewalTime` to the time when the renewal will be attempted.
-
-## Additional Certificate Output Formats
-
-
-
-⛔️ The additional certificate output formats feature is currently in an
-_experimental_ alpha state, and is subject to breaking changes or complete
-removal in future releases. This feature is only enabled by adding it to the
-`--feature-gates` flag on the cert-manager controller and webhook components:
-
-```bash
---feature-gates=AdditionalCertificateOutputFormats=true
-```
-
-
-
-`additionalOutputFormats` is a field on the Certificate `spec` that allows
-specifying additional supplementary formats of issued certificates and their
-private key. There are currently two supported additional output formats:
-`CombinedPEM` and `DER`. Both output formats can be specified on the same
-Certificate.
-
-```yaml
-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:
- tls.key:
- tls.crt:
- tls-combined.pem:
- key.der:
-```
-
-#### `CombinedPEM`
-
-The `CombinedPEM` type will create a new key entry in the resulting
-Certificate's Secret `tls-combined.pem`. This entry will contain the PEM encoded
-private key, followed by at least one new line character, followed by the PEM
-encoded signed certificate chain-
-
-```text
- + "\n" +
-```
-
-```yaml
-apiVersion: v1
-kind: Secret
-metadata:
- name: my-cert-tls
-type: kubernetes.io/tls
-data:
- tls-combined.pem:
- ...
-```
-
-#### `DER`
+## Inner workings diagram for developers
-The `DER` type will create a new key entry in the resulting Certificate's Secret
-`key.der`. This entry will contain the DER binary format of the private key.
+
-```yaml
-apiVersion: v1
-kind: Secret
-metadata:
- name: my-cert-tls
-type: kubernetes.io/tls
-data:
- key.der:
- ...
-```
+[1] https://cert-manager.io/docs/usage/certificaterequest
diff --git a/content/docs/usage/certificaterequest.md b/content/docs/usage/certificaterequest.md
new file mode 100644
index 0000000000..2b5a27c927
--- /dev/null
+++ b/content/docs/usage/certificaterequest.md
@@ -0,0 +1,272 @@
+---
+title: CertificateRequest resource
+description: 'cert-manager core concepts: CertificateRequests'
+---
+
+> **apiVersion:** cert-manager.io/v1
+> **kind:** CertificateRequest
+
+
+
+
+
+The `CertificateRequest` is a namespaced resource in cert-manager that is used
+to request X.509 certificates from an [`Issuer`](../concepts/issuer.md). The resource
+contains a base64 encoded string of a PEM encoded certificate request which is
+sent to the referenced issuer. A successful issuance will return a signed
+certificate, based on the certificate signing request. `CertificateRequests` are
+typically consumed and managed by controllers or other systems and should not be
+used by humans - unless specifically needed.
+
+A simple `CertificateRequest` looks like the following:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: CertificateRequest
+metadata:
+ name: my-ca-cr
+spec:
+ request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQzNqQ0NBY1lDQVFBd2daZ3hDekFKQmdOVkJBWVRBbHBhTVE4d0RRWURWUVFJREFaQmNHOXNiRzh4RFRBTApCZ05WQkFjTUJFMXZiMjR4RVRBUEJnTlZCQW9NQ0VwbGRITjBZV05yTVJVd0V3WURWUVFMREF4alpYSjBMVzFoCmJtRm5aWEl4RVRBUEJnTlZCQU1NQ0dwdmMyaDJZVzVzTVN3d0tnWUpLb1pJaHZjTkFRa0JGaDFxYjNOb2RXRXUKZG1GdWJHVmxkWGRsYmtCcVpYUnpkR0ZqYXk1cGJ6Q0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQwpBUW9DZ2dFQkFLd01tTFhuQkNiRStZdTIvMlFtRGsxalRWQ3BvbHU3TlZmQlVFUWl1bDhFMHI2NFBLcDRZQ0c5Cmx2N2kwOHdFMEdJQUgydnJRQmxVd3p6ZW1SUWZ4YmQvYVNybzRHNUFBYTJsY2NMaFpqUlh2NEVMaER0aVg4N3IKaTQ0MWJ2Y01OM0ZPTlRuczJhRkJYcllLWGxpNG4rc0RzTEVuZmpWdXRiV01Zeis3M3ptaGZzclRJUjRzTXo3cQpmSzM2WFM4UkRjNW5oVVcyYU9BZ3lnbFZSOVVXRkxXNjNXYXVhcHg2QUpBR1RoZnJYdVVHZXlZUUVBSENxZmZmCjhyOEt3YTFYK1NwYm9YK1ppSVE0Nk5jQ043OFZnL2dQVHNLZmphZURoNWcyNlk1dEVidHd3MWdRbWlhK0MyRHIKWHpYNU13RzJGNHN0cG5kUnRQckZrU1VnMW1zd0xuc0NBd0VBQWFBQU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQgpBUUFXR0JuRnhaZ0gzd0N3TG5IQ0xjb0l5RHJrMUVvYkRjN3BJK1VVWEJIS2JBWk9IWEFhaGJ5RFFLL2RuTHN3CjJkZ0J3bmlJR3kxNElwQlNxaDBJUE03eHk5WjI4VW9oR3piN0FVakRJWHlNdmkvYTJyTVhjWjI1d1NVQmxGc28Kd005dE1QU2JwcEVvRERsa3NsOUIwT1BPdkFyQ0NKNnZGaU1UbS9wMUJIUWJSOExNQW53U0lUYVVNSFByRzJVMgpjTjEvRGNMWjZ2enEyeENjYVoxemh2bzBpY1VIUm9UWmV1ZEp6MkxmR0VHM1VOb2ppbXpBNUZHd0RhS3BySWp3ClVkd1JmZWZ1T29MT1dNVnFNbGRBcTlyT24wNHJaT3Jnak1HSE9tTWxleVdPS1AySllhaDNrVDdKU01zTHhYcFYKV0ExQjRsLzFFQkhWeGlKQi9Zby9JQWVsCi0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
+ isCA: false
+ usages:
+ - signing
+ - digital signature
+ - server auth
+ # 90 days
+ duration: 2160h
+ 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
+ group: cert-manager.io
+```
+
+This `CertificateRequest` will make cert-manager attempt to request the `Issuer`
+`ca-issuer` in the default issuer group `cert-manager.io`, return a
+certificate based upon the certificate signing request. Other groups can be
+specified inside the `issuerRef` which will change the targeted issuer to other
+external, third party issuers you may have installed.
+
+The resource also exposes the option for stating the certificate as CA, Key
+Usages, and requested validity duration.
+
+All fields within the `spec` of the `CertificateRequest`, as well as any managed
+cert-manager annotations, are immutable and cannot be modified after creation.
+
+A successful issuance of the certificate signing request will cause an update to
+the resource, setting the status with the signed certificate, the CA of the
+certificate (if available), and setting the `Ready` condition to `True`.
+
+Whether issuance of the certificate signing request was successful or not, a retry of the
+issuance will _not_ happen. It is the responsibility of some other controller to
+manage the logic and life cycle of `CertificateRequests`.
+
+## Conditions
+`CertificateRequests` have a set of strongly defined conditions that should be
+used and relied upon by controllers or services to make decisions on what
+actions to take next on the resource.
+
+### Ready
+Each ready condition consists of the pair `Ready` - a boolean value, and
+`Reason` - a string. The set of values and meanings are as follows:
+
+| Ready | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| False | Pending | The `CertificateRequest` is currently pending, waiting for some other operation to take place. This could be that the `Issuer` does not exist yet or the `Issuer` is in the process of issuing a certificate. |
+| False | Failed | The certificate has failed to be issued - either the returned certificate failed to be decoded or an instance of the referenced issuer used for signing failed. No further action will be taken on the `CertificateRequest` by its controller and it can be considered terminally failed. |
+| True | Issued | A signed certificate has been successfully issued by the referenced `Issuer`. |
+
+This condition should be set by the issuer.
+
+### Denied
+| Denied | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| True | \ | The `CertificateRequest` was Denied by an approver. This `CertificateRequest` can be considered terminally failed.
+
+This condition should only be set by an approver.
+
+### Approved
+| Approved | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| True | \ | The `CertificateRequest` was approved by the approver. This `CertificateRequest` is approved and can be issued by the issuer.
+
+This condition should only be set by an approver.
+
+### InvalidRequest
+| InvalidRequest | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| True | \ | The `CertificateRequest` is invalid. This `CertificateRequest` can be considered terminally failed.
+
+
+## UserInfo
+
+`CertificateRequests` include a set of `UserInfo` fields as part of the spec,
+namely: `username`, `groups`, `uid`, and `extra`. These values contain the user
+who created the `CertificateRequest`. This user will be cert-manager itself in
+the case that the `CertificateRequest` was created by a
+[`Certificate`](../usage/certificate.md) resource, or instead the user who created the
+`CertificateRequest` directly.
+
+> **Warning**: These fields are managed by cert-manager and should _never_ be
+> set or modified by anything else. When the `CertificateRequest` is created,
+> these fields will be overridden, and any request attempting to modify them
+> will be rejected.
+
+
+### Approval
+CertificateRequests can be `Approved` or `Denied`. These mutually exclusive
+conditions gate a CertificateRequest from being signed by its managed signer.
+
+- A signer should _not_ sign a managed CertificateRequest without an Approved condition
+- A signer _will_ sign a managed CertificateRequest with an Approved condition
+- A signer will _never_ sign a managed CertificateRequest with a Denied condition
+
+These conditions are _permanent_, and cannot be modified or changed once set.
+
+```bash
+NAMESPACE NAME APPROVED DENIED READY ISSUER REQUESTOR AGE
+istio-system service-mesh-ca-whh5b True True mesh-ca system:serviceaccount:istio-system:istiod 16s
+istio-system my-app-fj9sa True mesh-ca system:serviceaccount:my-app:my-app 4s
+```
+
+
+#### Behavior
+
+The Approved and Denied conditions are two distinct condition types on the
+CertificateRequest. These conditions must only have the status of True, and
+are mutually exclusive (i.e. a CertificateRequest cannot have an Approved and
+Denied condition simultaneously). This behavior is enforced in the cert-manager
+validating admission webhook.
+
+An "approver" is an entity that is responsible for setting the Approved/Denied
+conditions. It is up to the approver's implementation as to what
+CertificateRequests are managed by that approver.
+
+The Reason field of the Approved/Denied condition should be set to *who* set the
+condition. Who can be interpreted however makes sense to the approver
+implementation. For example, it may include the API group of an approving policy
+controller, or the client agent of a manual request.
+
+The Message field of the Approved/Denied condition should be set to *why* the
+condition is set. Again, why can be interpreted however makes sense to the
+implementation of the approver. For example, the name of the resource that
+approves this request, the violations which caused the request to be denied, or
+the team to who manually approved the request.
+
+
+#### Approver Controller
+
+By default, cert-manager will run an internal approval controller which will
+automatically approve _all_ CertificateRequests that reference any internal
+issuer type in any namespace: `cert-manager.io/Issuer`,
+`cert-manager.io/ClusterIssuer`.
+
+To disable this controller, add the following argument to the
+cert-manager-controller: `--controllers=*,-certificaterequests-approver`. This
+can be achieved with helm by appending:
+
+```bash
+--set extraArgs={--controllers='*\,-certificaterequests-approver'}
+```
+
+Alternatively, in order for the internal approver controller to approve
+CertificateRequests that reference an external issuer, add the following RBAC to
+the cert-manager-controller Service Account. Please replace the given resource
+names with the relevant names:
+
+```yaml
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: cert-manager-controller-approve:my-issuer-example-com # edit
+rules:
+- apiGroups:
+ - cert-manager.io
+ resources:
+ - signers
+ verbs:
+ - approve
+ resourceNames:
+ - issuers.my-issuer.example.com/* # edit
+ - clusterissuers.my-issuer.example.com/* # edit
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: cert-manager-controller-approve:my-issuer-example-com # edit
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cert-manager-controller-approve:my-issuer-example-com # edit
+subjects:
+- kind: ServiceAccount
+ name: cert-manager
+ namespace: cert-manager
+```
+
+#### RBAC Syntax
+
+When a user or controller attempts to approve or deny a CertificateRequest, the
+cert-manager webhook will evaluate whether it has sufficient permissions to do
+so. These permissions are based upon the request
+itself- specifically the request's IssuerRef:
+
+```yaml
+apiGroups: ["cert-manager.io"]
+resources: ["signers"]
+verbs: ["approve"]
+resourceNames:
+ # namesapced signers
+ - "./."
+ # cluster scoped signers
+ - "./"
+ # all signers of this resource name
+ - "./*"
+```
+
+An example ClusterRole that would grant the permissions to set the Approve and
+Denied conditions of CertificateRequests that reference the cluster scoped
+`myissuers` external issuer, in the group `my-example.io`, with the name `myapp`:
+
+```yaml
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: my-example-io-my-issuer-myapp-approver
+rules:
+ - apiGroups: ["cert-manager.io"]
+ resources: ["signers"]
+ verbs: ["approve"]
+ resourceNames: ["myissuers.my-example.io/myapp"]
+```
+
+If the approver does not have sufficient permissions defined above to set the
+Approved or Denied conditions, the request will be rejected by the cert-manager
+validating admission webhook.
+
+- The RBAC permissions *must* be granted at the cluster scope
+- Namespaced signers are represented by a namespaced resource using the syntax of `./.`
+- Cluster scoped signers are represented using the syntax of `./`
+- An approver can be granted approval for all namespaces via `./*`
+- The apiGroup must *always* be `cert-manager.io`
+- The resource must *always* be `signers`
+- The verb must *always* be `approve`, which grants the approver the permissions to set *both* Approved and Denied conditions
+
+An example of signing all `myissuer` signers in all namespaces, and
+`clustermyissuers` with the name `myapp`, in the `my-example.io` group:
+
+```yaml
+ resourceNames: ["myissuers.my-example.io/*", "clustermyissuers.my-example.io/myapp"]
+```
+
+An example of signing `myissuer` with the name `myapp` in the namespaces `foo`
+and `bar`:
+
+```yaml
+ resourceNames: ["myissuers.my-example.io/foo.myapp", "myissuers.my-example.io/bar.myapp"]
+```
+
+## Inner workings diagram for developers
+
+
diff --git a/content/docs/projects/csi-driver-spiffe.md b/content/docs/usage/csi-driver-spiffe.md
similarity index 96%
rename from content/docs/projects/csi-driver-spiffe.md
rename to content/docs/usage/csi-driver-spiffe.md
index 771ce6a1ae..ca52c22694 100644
--- a/content/docs/projects/csi-driver-spiffe.md
+++ b/content/docs/usage/csi-driver-spiffe.md
@@ -46,7 +46,7 @@ which is used to create and mount Pod volumes from.
When a Pod is created with the CSI volume configured, the
driver will locally generate a private key, and create a cert-manager
-[CertificateRequest](../concepts/certificaterequest.md)
+[CertificateRequest](../usage/certificaterequest.md)
in the same Namespace as the Pod.
The driver uses [CSI Token Request](https://kubernetes-csi.github.io/docs/token-requests.html) to both
@@ -61,7 +61,7 @@ expiry of the signed certificate.
#### Approver
-A distinct [cert-manager approver](../concepts/certificaterequest.md#approval)
+A distinct [cert-manager approver](../usage/certificaterequest.md#approval)
Deployment is responsible for managing the approval and denial condition of
created CertificateRequests that target the configured SPIFFE Trust Domain
signer.
@@ -78,7 +78,7 @@ The approver ensures that requests have:
If any of these checks do not pass, the CertificateRequest will be marked as
Denied, else it will be marked as Approved. The approver will only manage
-CertificateRequests who request from the same [IssuerRef](../concepts/certificaterequest.md)
+CertificateRequests who request from the same [IssuerRef](../usage/certificaterequest.md)
that has been configured.
## Installation
@@ -98,7 +98,7 @@ cert-manager `v1.3` or higher is also required.
csi-driver-spiffe requires cert-manager to be [installed](../installation/README.md) but
a default installation of cert-manager **will not work**.
-> ⚠️ It is **vital** that the [default approver is disabled in cert-manager](../concepts/certificaterequest.md#approver-controller) ⚠️
+> ⚠️ It is **vital** that the [default approver is disabled in cert-manager](../usage/certificaterequest.md#approver-controller) ⚠️
If the default approver is not disabled, the csi-driver-spiffe approver will
race with cert-manager and policy enforcement will become useless.
@@ -149,7 +149,7 @@ cmctl approve -n cert-manager \
Install csi-driver-spiffe into the cluster using the issuer we configured. We
must also configure the issuer resource type and name of the issuer we
-configured so that the approver has [permissions to approve referencing CertificateRequests](../concepts/certificaterequest.md#rbac-syntax).
+configured so that the approver has [permissions to approve referencing CertificateRequests](../usage/certificaterequest.md#rbac-syntax).
Note that the `issuer.name`, `issuer.kind` and `issuer.group` will need to be changed to match
the issuer you're actually using!
diff --git a/content/docs/projects/csi-driver.md b/content/docs/usage/csi-driver.md
similarity index 73%
rename from content/docs/projects/csi-driver.md
rename to content/docs/usage/csi-driver.md
index ab9cc84f60..12428534ce 100644
--- a/content/docs/projects/csi-driver.md
+++ b/content/docs/usage/csi-driver.md
@@ -1,42 +1,36 @@
---
title: csi-driver
-description: ''
+description: 'Mounting cert-manager certificates without secrets'
---
-csi-driver is a Container Storage Interface (CSI) driver plugin for Kubernetes
-to work along cert-manager. The goal for this plugin is to seamlessly request
-and mount certificate key pairs to pods. This is useful for facilitating mTLS,
-or otherwise securing connections of pods with guaranteed present certificates
-whilst having all of the features that cert-manager provides.
-
-## Why a CSI Driver?
-
-- Ensure private keys never leave the node and are never sent over the network.
- All private keys are stored locally on the node.
-- Unique key and certificate per application replica with a grantee to be
- present on application run time.
-- Reduce resource management overhead by defining certificate request spec
- in-line of the Kubernetes Pod template.
-- Automatic renewal of certificates based on expiry of each individual
- certificate.
-- Keys and certificates are destroyed during application termination.
-- Scope for extending plugin behavior with visibility on each replica's
- certificate request and termination.
-
-## Requirements and Installation
-
-This CSI driver plugin makes use of the 'CSI inline volume' feature - Alpha as
-of `v1.15` and beta in `v1.16`. Kubernetes versions `v1.16` and higher require
-no extra configuration however `v1.15` requires the following feature gate set:
-```
---feature-gates=CSIInlineVolume=true
-```
+csi-driver is a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) driver plugin for Kubernetes
+which works alongside cert-manager.
+
+Pods which mount the cert-manager csi-driver will request certificates from cert-manager
+without needing a `Certificate` resource to be created. These certificates will be mounted
+directly into the pod, with no intermediate Secret being created.
+
+## Why use csi-driver?
+
+- Ensure private keys never leave the node and are never sent over the network. Private keys are stored in memory, and shouldn't be written to disk.
+- Unique key and certificate per application replica
+- Fewer `Certificate` resources means writing less YAML
+- Keys and certificates are destroyed when an application terminates
+- No `Secret` resources needed for storing the certificate means less RBAC
+- Great for ephemeral, short-lived certificates which don't need to survive a restart (e.g. certificates for mTLS)
-You must have a working installation of cert-manager present on the cluster.
-Instructions on how to install cert-manager can be found
-[on cert-manager.io](../installation/README.md).
+## Why _not_ use csi-driver?
-To install the csi-driver, use helm install:
+- If you need certificates to be persisted through a node restart
+- If you need the same certificate to be shared by multiple components
+
+## Installation
+
+You must have a working installation of cert-manager present on your cluster and be running at least Kubernetes `v1.16`.
+
+Instructions on how to install cert-manager can be found [on this website](../installation/README.md).
+
+To install csi-driver, use helm:
```terminal
helm repo add jetstack https://charts.jetstack.io --force-update
@@ -55,7 +49,7 @@ You can verify the installation has completed correctly by checking the presence
of the CSIDriver resource as well as a CSINode resource present for each node,
referencing `csi.cert-manager.io`.
-```
+```terminal
$ kubectl get csidrivers
NAME CREATED AT
csi.cert-manager.io 2019-09-06T16:55:19Z
@@ -80,17 +74,15 @@ items:
...
```
-The CSI driver is now installed and is ready to be used for pods in the cluster.
-
## Requesting and Mounting Certificates
-To request certificates from cert-manager, simply define a volume mount where
-the key and certificate will be written to, along with a volume with attributes
-that define the cert-manager request. The following is a dummy app that mounts a
-key certificate pair to `/tls` and has been signed by the `ca-issuer` with a DNS
-name valid for `my-service.sandbox.svc.cluster.local`.
+Requesting a certificate using csi-driver means mounting a volume, with some attributes
+set to define exactly what you need to request.
-```
+The following example is a dummy app that mounts a key certificate pair to `/tls`, signed using
+a cert-manager issuer called `ca-issuer` with a DNS name valid for `my-service.sandbox.svc.cluster.local`.
+
+```yaml
apiVersion: v1
kind: Pod
metadata:
@@ -115,25 +107,21 @@ spec:
csi.cert-manager.io/dns-names: ${POD_NAME}.${POD_NAMESPACE}.svc.cluster.local
```
-Once created, the CSI driver will generate a private key locally, request a
-certificate from cert-manager based on the given attributes, then store both
-locally to be mounted to the pod. The pod will remain in a pending state until
-this process has been completed.
+Once created, the CSI driver will generate a private key locally (for the pod), request a
+certificate from cert-manager based on the given attributes, and store the certificate ready for the pod to use.
-For more information on how to set up issuers for your cluster, refer to the
-cert-manager documentation
-[here](../configuration/README.md). **Note** it is not
-possible to use `SelfSigned` Issuers with the CSI Driver. In order for
-cert-manager to self sign a certificate, it needs access to the secret
-containing the private key that signed the certificate request to sign the end
-certificate. This secret is not used and so not available in the CSI driver use
-case.
+The pod will remain in a pending state until issuance has been completed.
+
+For more information on how to set up issuers for your cluster, refer to the cert-manager documentation
+[here](../configuration/README.md).
+
+**Note** it is not possible to use `SelfSigned` Issuers with csi-driver because `SelfSigned` issuers are a
+special case.
## Supported Volume Attributes
The csi-driver driver aims to have complete feature parity with all possible
-values available through the cert-manager API however currently supports the
-following values;
+values available through the cert-manager API. It currently supports the following values:
| Attribute | Description | Default | Example |
|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|----------------------------------|
@@ -164,17 +152,17 @@ The following attributes support variables that are evaluated when a request is
made for the mounting Pod. These variables are useful for constructing requests
with SANs that contain values from the mounting Pod.
-```
-`csi.cert-manager.io/common-name`
-`csi.cert-manager.io/dns-names`
-`csi.cert-manager.io/uri-sans`
+```text
+csi.cert-manager.io/common-name
+csi.cert-manager.io/dns-names
+csi.cert-manager.io/uri-sans
```
Variables follow the [go `os.Expand`](https://pkg.go.dev/os#Expand) structure,
which is generally what you would expect on a UNIX shell. The CSI driver has
access to the following variables:
-```
+```text
${POD_NAME}
${POD_NAMESPACE}
${POD_UID}
@@ -194,19 +182,19 @@ volumeAttributes:
## Requesting Certificates using the mounting Pod's ServiceAccount
If the flag `--use-token-request` is enabled on the csi-driver DaemonSet, the
-[CertificateRequest](../concepts/certificaterequest.md) resource will be created
-by the mounting Pod's ServiceAccount. This can be pared with
-[approver-policy](./approver-policy.md) to enable advanced policy on a per
-ServiceAccount basis.
+[CertificateRequest](../usage/certificaterequest.md) resource will be created
+by the mounting Pod's ServiceAccount. This can be paired with
+[approver-policy](../policy/approval/approver-policy/README.md) to enable advanced policy control
+on a per-ServiceAccount basis.
-Ensure to give permissions to Pod ServiceAccounts to create CertificateRequests
+Ensure that you give permissions to Pod ServiceAccounts to create CertificateRequests
with this flag enabled, i.e:
```yaml
-# WARNING: This RBAC will enable any identiy in the cluster to create
-# CertificateRequests. This may or may not be problimatic based on your security
-# model. It is likely worth scoping the set of identities in the
-# `ClusterRoleBinding` `subjects` stanza.
+# WARNING: This RBAC will enable any identity in the cluster to create
+# CertificateRequests and is dangerous to use in production. Instead, you should
+# give permissions only to identities which need to be able to create certificates.
+# This would be done via scoping the set of identities in the `ClusterRoleBinding` `subjects` stanza.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
diff --git a/content/docs/usage/csi.md b/content/docs/usage/csi.md
index 5e1a6124b0..913a006b56 100644
--- a/content/docs/usage/csi.md
+++ b/content/docs/usage/csi.md
@@ -3,10 +3,14 @@ title: CSI Driver
description: 'cert-manager usage: CSI driver'
---
+
+
+
+
## Enabling mTLS of Pods using the cert-manager CSI Driver
A [Container Storage Interface (CSI)
-driver](../projects/csi-driver.md) has been created to
+driver](csi-driver.md) has been created to
facilitate mTLS of Pods running inside your cluster through use of cert-manager.
Using this driver will ensure that the private key and corresponding signed
certificate will be unique to each Pod and will be stored on disk to the node
diff --git a/content/docs/usage/gateway.md b/content/docs/usage/gateway.md
index 9aa05cf1a1..bb4bf0b682 100644
--- a/content/docs/usage/gateway.md
+++ b/content/docs/usage/gateway.md
@@ -1,8 +1,15 @@
---
-title: Securing gateway.networking.k8s.io Gateway Resources
+title: Annotated Gateway resource
description: 'cert-manager usage: Kubernetes Gateways'
---
+> **apiVersion:** gateway.networking.k8s.io/v1alpha2
+> **kind:** Gateway
+
+
+
+
+
**FEATURE STATE**: cert-manager 1.5 [alpha]
@@ -369,6 +376,42 @@ Certificate resources:
- `cert-manager.io/common-name`: (optional) this annotation allows you to
configure `spec.commonName` for the Certificate to be generated.
+- `cert-manager.io/email-sans`: (optional) this annotation allows you to
+ configure `spec.emailAddresses` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "me@example.com,you@example.com"
+
+- `cert-manager.io/subject-organizations`: (optional) this annotation allows you to
+ configure `spec.subject.organizations` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "Company 1,Company 2"
+
+- `cert-manager.io/subject-organizationalunits`: (optional) this annotation allows you to
+ configure `spec.subject.organizationalUnits` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "IT Services,Cloud Services"
+
+- `cert-manager.io/subject-countries`: (optional) this annotation allows you to
+ configure `spec.subject.countries` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "Country 1,Country 2"
+
+- `cert-manager.io/subject-provinces`: (optional) this annotation allows you to
+ configure `spec.subject.provinces` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "Province 1,Province 2"
+
+- `cert-manager.io/subject-localities`: (optional) this annotation allows you to
+ configure `spec.subject.localities` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "City 1,City 2"
+
+- `cert-manager.io/subject-postalcodes`: (optional) this annotation allows you to
+ configure `spec.subject.postalCodes` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "123ABC,456DEF"
+
+- `cert-manager.io/subject-streetaddresses`: (optional) this annotation allows you to
+ configure `spec.subject.streetAddresses` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "123 Example St,456 Other Blvd"
+
+- `cert-manager.io/subject-serialnumber`: (optional) this annotation allows you to
+ configure `spec.subject.serialNumber` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "10978342379280287615,1111144445555522228888"
+
- ` cert-manager.io/duration`: (optional) this annotation allows you to
configure `spec.duration` field for the Certificate to be generated.
@@ -400,3 +443,9 @@ Certificate resources:
- `cert-manager.io/private-key-rotation-policy`: (optional) this annotation allows you to
configure `spec.privateKey.rotationPolicy` field to set the rotation policy of the private key for a Certificate.
Valid values are `Never` and `Always`. If unset a rotation policy `Never` will be used.
+
+## Inner workings diagram for developers
+
+
+
+[1] https://cert-manager.io/docs/usage/certificate
diff --git a/content/docs/usage/ingress.md b/content/docs/usage/ingress.md
index d8f58e002e..cc1b9fc04a 100644
--- a/content/docs/usage/ingress.md
+++ b/content/docs/usage/ingress.md
@@ -1,8 +1,15 @@
---
-title: Securing Ingress Resources
+title: Annotated Ingress resource
description: 'cert-manager usage: Kubernetes Ingress'
---
+> **apiVersion:** networking.k8s.io/v1
+> **kind:** Ingress
+
+
+
+
+
A common use-case for cert-manager is requesting TLS signed certificates to
secure your ingress resources. This can be done by simply adding annotations to
your `Ingress` resources and cert-manager will facilitate creating the
@@ -49,13 +56,25 @@ spec:
You can specify the following annotations on Ingress resources in order to
trigger Certificate resources to be automatically created:
-- `cert-manager.io/issuer`: the name of an Issuer to acquire the certificate
- required for this Ingress. The Issuer *must* be in the same namespace as the
- Ingress resource.
+- `cert-manager.io/issuer`: the name of the issuer that should issue the certificate
+ required for this Ingress.
+
+ > ⚠️ This annotation does _not_ assume a namespace scoped issuer. It will
+ default to cert-manager.io Issuer, however in case of external issuer types,
+ this should be used for both namespaced and cluster scoped issuer types.
+
+ > ⚠️ If a namespace scoped issuer is used then the issuer *must* be in
+ the same namespace as the Ingress resource.
+
+- `cert-manager.io/cluster-issuer`: the name of a cert-manager.io ClusterIssuer
+ to acquire the certificate required for this Ingress. It does not matter which
+ namespace your Ingress resides, as ClusterIssuers are non-namespaced
+ resources.
-- `cert-manager.io/cluster-issuer`: the name of a ClusterIssuer to acquire the
- certificate required for this Ingress. It does not matter which namespace your
- Ingress resides, as ClusterIssuers are non-namespaced resources.
+ > ⚠️ This annotation is a shortcut to refer to to
+ cert-manager.io ClusterIssuer without having to specify group and kind. It is
+ _not_ intended to be used to specify an external cluster-scoped issuer- please
+ use `cert-manager.io/issuer` annotation for those.
- `cert-manager.io/issuer-kind`: the kind of the external issuer resource, for
example `AWSPCAIssuer`. This is only necessary for out-of-tree issuers.
@@ -83,13 +102,49 @@ trigger Certificate resources to be automatically created:
This annotation will also add the annotation
`"cert-manager.io/issue-temporary-certificate": "true"` onto created
certificates which will cause a [temporary
- certificate](./certificate.md#temporary-certificates-whilst-issuing) to be set
+ certificate](../usage/certificate.md#temporary-certificates-whilst-issuing) to be set
on the resulting Secret until the final signed certificate has been returned.
This is useful for keeping compatibility with the `ingress-gce` component.
- `cert-manager.io/common-name`: (optional) this annotation allows you to
configure `spec.commonName` for the Certificate to be generated.
+- `cert-manager.io/email-sans`: (optional) this annotation allows you to
+ configure `spec.emailAddresses` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "me@example.com,you@example.com"
+
+- `cert-manager.io/subject-organizations`: (optional) this annotation allows you to
+ configure `spec.subject.organizations` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "Company 1,Company 2"
+
+- `cert-manager.io/subject-organizationalunits`: (optional) this annotation allows you to
+ configure `spec.subject.organizationalUnits` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "IT Services,Cloud Services"
+
+- `cert-manager.io/subject-countries`: (optional) this annotation allows you to
+ configure `spec.subject.countries` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "Country 1,Country 2"
+
+- `cert-manager.io/subject-provinces`: (optional) this annotation allows you to
+ configure `spec.subject.provinces` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "Province 1,Province 2"
+
+- `cert-manager.io/subject-localities`: (optional) this annotation allows you to
+ configure `spec.subject.localities` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "City 1,City 2"
+
+- `cert-manager.io/subject-postalcodes`: (optional) this annotation allows you to
+ configure `spec.subject.postalCodes` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "123ABC,456DEF"
+
+- `cert-manager.io/subject-streetaddresses`: (optional) this annotation allows you to
+ configure `spec.subject.streetAddresses` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "123 Example St,456 Other Blvd"
+
+- `cert-manager.io/subject-serialnumber`: (optional) this annotation allows you to
+ configure `spec.subject.serialNumber` field for the Certificate to be generated.
+ Supports comma-separated values e.g. "10978342379280287615,1111144445555522228888"
+
- ` cert-manager.io/duration`: (optional) this annotation allows you to
configure `spec.duration` field for the Certificate to be generated.
@@ -122,6 +177,10 @@ trigger Certificate resources to be automatically created:
configure `spec.privateKey.rotationPolicy` field to set the rotation policy of the private key for a Certificate.
Valid values are `Never` and `Always`. If unset a rotation policy `Never` will be used.
+## Generate multiple certificates with multiple ingresses
+
+If you need to generate certificates from multiple ingresses make sure it has the issuer annotation.
+Besides the annotation, it is necessary that each ingress possess a unique `tls.secretName`
## Optional Configuration
@@ -160,4 +219,10 @@ guide](../installation/README.md).
## Troubleshooting
-If you do not see a `Certificate` resource being created after applying the ingress-shim annotations check that at least `cert-manager.io/issuer` or `cert-manager.io/cluster-issuer` is set. If you want to use `kubernetes.io/tls-acme: "true"` make sure to have checked all steps above and you might want to look for errors in the cert-manager pod logs if not resolved.
\ No newline at end of file
+If you do not see a `Certificate` resource being created after applying the ingress-shim annotations check that at least `cert-manager.io/issuer` or `cert-manager.io/cluster-issuer` is set. If you want to use `kubernetes.io/tls-acme: "true"` make sure to have checked all steps above and you might want to look for errors in the cert-manager pod logs if not resolved.
+
+## Inner workings diagram for developers
+
+
+
+[1] https://cert-manager.io/docs/usage/certificate
diff --git a/content/docs/projects/istio-csr.md b/content/docs/usage/istio-csr.md
similarity index 89%
rename from content/docs/projects/istio-csr.md
rename to content/docs/usage/istio-csr.md
index 57748517bc..c6a601ab6c 100644
--- a/content/docs/projects/istio-csr.md
+++ b/content/docs/usage/istio-csr.md
@@ -1,8 +1,17 @@
---
-title: istio-csr
-description: ''
+title: Securing Istio Service Mesh
+description: 'cert-manager usage: Istio and istio-csr'
---
+
+
+
+
+cert-manager can be integrated with [Istio](https://istio.io) using the project
+[istio-csr](https://github.com/cert-manager/istio-csr). istio-csr will deploy an
+agent that is responsible for receiving certificate signing requests for all
+members of the Istio mesh, and signing them through cert-manager.
+
istio-csr is an agent that allows for [Istio](https://istio.io) workload and
control plane components to be secured using
[cert-manager](https://cert-manager.io).
diff --git a/content/docs/usage/kube-csr.md b/content/docs/usage/kube-csr.md
index f6abb93f74..09e6b2bd65 100644
--- a/content/docs/usage/kube-csr.md
+++ b/content/docs/usage/kube-csr.md
@@ -1,12 +1,19 @@
---
-title: Kubernetes CertificateSigningRequests
+title: CertificateSigningRequest resource
description: 'cert-manager usage: Kubernetes CertificateSigningRequest resources'
---
+> **apiVersion:** certificates.k8s.io/v1
+> **kind:** CertificateSigningRequest
+
+
+
+
+
Kubernetes has an in-built
[CertificateSigningRequest](https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/)
resource. This resource is similar to the cert-manager
-[CertificateRequest](../concepts/certificaterequest.md) in that it is used to
+[CertificateRequest](../usage/certificaterequest.md) in that it is used to
request an X.509 signed certificate from a referenced Certificate Authority
(CA).
@@ -164,3 +171,7 @@ are not approved by default, so you will likely need to approve it manually:
```bash
$ kubectl certificate approve
```
+
+## Inner workings diagram for developers
+
+
diff --git a/content/pages/homepage.mdx b/content/pages/homepage.mdx
index e0fa2239b4..0e76afe1e5 100644
--- a/content/pages/homepage.mdx
+++ b/content/pages/homepage.mdx
@@ -10,15 +10,15 @@ export const meta = {
stats: [
{
icon: 'github',
- description: '10,000+ GitHub Stars'
+ description: '11,000+ GitHub Stars'
},
{
icon: 'slack',
- description: '7000+ Slack members'
+ description: '8000+ Slack members'
},
{
icon: 'downloads',
- description: '1 million+ daily downloads'
+ description: '5 million+ daily downloads'
}
],
topCta: {
diff --git a/content/pages/support.mdx b/content/pages/support.mdx
index 3e65a73d4e..ea323da02a 100644
--- a/content/pages/support.mdx
+++ b/content/pages/support.mdx
@@ -6,15 +6,15 @@ export const meta = {
description: 'Need a little more help?'
},
intro: {
- heading: 'Jetstack',
+ heading: 'Venafi',
description:
- 'Jetstack is the team who first created cert-manager and offer direct support alongside a commercial product offering to help enterprises and organisations scale effectively with cert-manager.',
+ 'Venafi is the principal maintainer of the cert-manager project and works directly with the CNCF. Commercial support for cert-manager is available as part of the TLS Protect for Kubernetes product which also offers expertise to help organisations scale effectively with cert-manager.',
cta: {
- logo: '/images/jetstack-secure-logo.svg',
+ logo: '/images/venafi-tls-protect-for-kubernetes.svg',
description:
- 'Extending the core value of cert-manager open source project.',
+ 'Extending the core value of the cert-manager open source project.',
caption: 'Find out more',
- href: 'https://www.jetstack.io/jetstack-secure/'
+ href: 'https://venafi.com/tls-protect-for-kubernetes/'
}
}
}
diff --git a/content/v1.0-docs/usage/README.md b/content/v1.0-docs/usage/README.md
index 6cdb93f729..5013606980 100644
--- a/content/v1.0-docs/usage/README.md
+++ b/content/v1.0-docs/usage/README.md
@@ -19,7 +19,7 @@ cases and methods for requesting certificates through cert-manager:
Garden](https://docs.garden.io/guides/cert-manager-integration): Garden is a
developer tool for developing Kubernetes applications which has first class
support for integrating cert-manager.
-- [Securing Knative](https://knative.dev/docs/serving/using-auto-tls/): Secure
+- [Securing Knative](https://knative.dev/docs/serving/encryption/enabling-automatic-tls-certificate-provisioning/): Secure
your Knative services with trusted HTTPS certificates.
- [Enable mTLS on Pods with CSI](./csi.md): Using the cert-manager CSI
driver to provide unique keys and certificates that share the lifecycle of
diff --git a/content/v1.1-docs/usage/README.md b/content/v1.1-docs/usage/README.md
index e9c1994527..246126393a 100644
--- a/content/v1.1-docs/usage/README.md
+++ b/content/v1.1-docs/usage/README.md
@@ -19,7 +19,7 @@ cases and methods for requesting certificates through cert-manager:
Garden](https://docs.garden.io/guides/cert-manager-integration): Garden is a
developer tool for developing Kubernetes applications which has first class
support for integrating cert-manager.
-- [Securing Knative](https://knative.dev/docs/serving/using-auto-tls/): Secure
+- [Securing Knative](https://knative.dev/docs/serving/encryption/enabling-automatic-tls-certificate-provisioning/): Secure
your Knative services with trusted HTTPS certificates.
- [Enable mTLS on Pods with CSI](./csi.md): Using the cert-manager CSI
driver to provide unique keys and certificates that share the lifecycle of
diff --git a/content/v1.10-docs/usage/README.md b/content/v1.10-docs/usage/README.md
index b0d93801a9..451db2ed9d 100644
--- a/content/v1.10-docs/usage/README.md
+++ b/content/v1.10-docs/usage/README.md
@@ -16,7 +16,7 @@ There are several use cases and methods for requesting certificates through cert
- [Integration with Garden](https://docs.garden.io/guides/cert-manager-integration): Garden is a
developer tool for developing Kubernetes applications which has first class
support for integrating cert-manager.
-- [Securing Knative](https://knative.dev/docs/serving/using-auto-tls/): Secure
+- [Securing Knative](https://knative.dev/docs/serving/encryption/enabling-automatic-tls-certificate-provisioning/): Secure
your Knative services with trusted HTTPS certificates.
- [Enable mTLS on Pods with CSI](./csi.md): Using the cert-manager CSI
driver to provide unique keys and certificates that share the lifecycle of
diff --git a/content/v1.11-docs/usage/README.md b/content/v1.11-docs/usage/README.md
index b0d93801a9..451db2ed9d 100644
--- a/content/v1.11-docs/usage/README.md
+++ b/content/v1.11-docs/usage/README.md
@@ -16,7 +16,7 @@ There are several use cases and methods for requesting certificates through cert
- [Integration with Garden](https://docs.garden.io/guides/cert-manager-integration): Garden is a
developer tool for developing Kubernetes applications which has first class
support for integrating cert-manager.
-- [Securing Knative](https://knative.dev/docs/serving/using-auto-tls/): Secure
+- [Securing Knative](https://knative.dev/docs/serving/encryption/enabling-automatic-tls-certificate-provisioning/): Secure
your Knative services with trusted HTTPS certificates.
- [Enable mTLS on Pods with CSI](./csi.md): Using the cert-manager CSI
driver to provide unique keys and certificates that share the lifecycle of
diff --git a/content/v1.12-docs/README.md b/content/v1.12-docs/README.md
new file mode 100644
index 0000000000..c53f1bc99f
--- /dev/null
+++ b/content/v1.12-docs/README.md
@@ -0,0 +1,26 @@
+---
+title: cert-manager
+description: cert-manager documentation homepage
+---
+
+cert-manager adds certificates and certificate issuers as resource types in
+Kubernetes clusters, and simplifies the process of obtaining, renewing and
+using those certificates.
+
+It can issue certificates from a variety of supported sources, including
+[Let's Encrypt](https://letsencrypt.org), [HashiCorp Vault](https://www.vaultproject.io),
+and [Venafi](https://www.venafi.com/) as well as private PKI.
+
+It will ensure certificates are valid and up to date, and attempt to
+renew certificates at a configured time before expiry.
+
+It is loosely based upon the work of
+[kube-lego](https://github.com/jetstack/kube-lego) and has borrowed some
+wisdom from other similar projects such as
+[kube-cert-manager](https://github.com/PalmStoneGames/kube-cert-manager).
+
+![High level overview diagram explaining cert-manager architecture](/images/high-level-overview.svg)
+
+This website provides the full technical documentation for the project, and can be
+used as a reference; if you feel that there's anything missing, please let us know
+or [raise a PR](https://github.com/cert-manager/website/pulls) to add it.
diff --git a/content/v1.12-docs/cli/README.md b/content/v1.12-docs/cli/README.md
new file mode 100644
index 0000000000..0d1a516335
--- /dev/null
+++ b/content/v1.12-docs/cli/README.md
@@ -0,0 +1,7 @@
+---
+title: CLI reference
+description: cert-manager CLI documentation
+---
+
+View the `--help` output from our various CLI tools, including those which run in containers in your cluster.
+This might help if you need to tweak an option or if you need to check which values are valid!
\ No newline at end of file
diff --git a/content/v1.12-docs/cli/acmesolver.md b/content/v1.12-docs/cli/acmesolver.md
new file mode 100644
index 0000000000..baee31aff4
--- /dev/null
+++ b/content/v1.12-docs/cli/acmesolver.md
@@ -0,0 +1,17 @@
+---
+title: acmesolver CLI reference
+description: "cert-manager acmesolver CLI documentation"
+---
+```
+HTTP server used to solve ACME challenges.
+
+Usage:
+ acmesolver [flags]
+
+Flags:
+ --domain string the domain name to verify
+ -h, --help help for acmesolver
+ --key string the challenge key to respond with
+ --listen-port int the port number to listen on for connections (default 8089)
+ --token string the challenge token to verify against
+```
diff --git a/content/v1.12-docs/cli/cainjector.md b/content/v1.12-docs/cli/cainjector.md
new file mode 100644
index 0000000000..0bcdf50014
--- /dev/null
+++ b/content/v1.12-docs/cli/cainjector.md
@@ -0,0 +1,45 @@
+---
+title: cainjector CLI reference
+description: "cert-manager cainjector CLI documentation"
+---
+```
+
+cert-manager CA injector is a Kubernetes addon to automate the injection of CA data into
+webhooks and APIServices from cert-manager certificates.
+
+It will ensure that annotated webhooks and API services always have the correct
+CA data from the referenced certificates, which can then be used to serve API
+servers and webhook servers.
+
+Usage:
+ ca-injector [flags]
+
+Flags:
+ --add_dir_header If true, adds the file directory to the header of the log messages
+ --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
+ --enable-profiling Enable profiling for cainjector
+ --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
+ AllAlpha=true|false (ALPHA - default=false)
+ AllBeta=true|false (BETA - default=false)
+ -h, --help help for ca-injector
+ --kubeconfig string Paths to a kubeconfig. Only required if out-of-cluster.
+ --leader-elect If true, cainjector will perform leader election between instances to ensure no more than one instance of cainjector operates at a time (default true)
+ --leader-election-lease-duration duration The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. This is only applicable if leader election is enabled. (default 1m0s)
+ --leader-election-namespace string Namespace used to perform leader election. Only used if leader election is enabled (default "kube-system")
+ --leader-election-renew-deadline duration The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. This is only applicable if leader election is enabled. (default 40s)
+ --leader-election-retry-period duration The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled. (default 15s)
+ --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+ --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
+ --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
+ --log_file string If non-empty, use this log file (no effect when -logtostderr=true)
+ --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
+ --logtostderr log to standard error instead of files (default true)
+ --namespace string If set, this limits the scope of cainjector to a single namespace. If set, cainjector will not update resources with certificates outside of the configured namespace.
+ --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
+ --profiler-address string Address of the Go profiler (pprof) if enabled. This should never be exposed on a public interface. (default "localhost:6060")
+ --skip_headers If true, avoid header prefixes in the log messages
+ --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
+ --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
+ -v, --v Level number for the log level verbosity
+ --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
+```
diff --git a/content/v1.12-docs/cli/cmctl.md b/content/v1.12-docs/cli/cmctl.md
new file mode 100644
index 0000000000..dff83b3bc2
--- /dev/null
+++ b/content/v1.12-docs/cli/cmctl.md
@@ -0,0 +1,30 @@
+---
+title: cmctl CLI reference
+description: "cert-manager cmctl CLI documentation"
+---
+```
+
+cmctl is a CLI tool manage and configure cert-manager resources for Kubernetes
+
+Usage: cmctl [command]
+
+Available Commands:
+ approve Approve a CertificateRequest
+ check Check cert-manager components
+ convert Convert cert-manager config files between different API versions
+ create Create cert-manager resources
+ deny Deny a CertificateRequest
+ experimental Interact with experimental features
+ help Help about any command
+ inspect Get details on certificate related resources
+ renew Mark a Certificate for manual renewal
+ status Get details on current status of cert-manager resources
+ upgrade Tools that assist in upgrading cert-manager
+ version Print the cert-manager CLI version and the deployed cert-manager version
+
+Flags:
+ -h, --help help for cmctl
+ --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+
+Use "cmctl [command] --help" for more information about a command.
+```
diff --git a/content/v1.12-docs/cli/controller.md b/content/v1.12-docs/cli/controller.md
new file mode 100644
index 0000000000..768ffb05cc
--- /dev/null
+++ b/content/v1.12-docs/cli/controller.md
@@ -0,0 +1,78 @@
+---
+title: controller CLI reference
+description: "cert-manager controller CLI documentation"
+---
+```
+
+cert-manager is a Kubernetes addon to automate the management and issuance of
+TLS certificates from various issuing sources.
+
+It will ensure certificates are valid and up to date periodically, and attempt
+to renew certificates at an appropriate time before expiry.
+
+Usage:
+ cert-manager-controller [flags]
+
+Flags:
+ --acme-http01-solver-image string The docker image to use to solve ACME HTTP01 challenges. You most likely will not need to change this parameter unless you are testing a new feature or developing cert-manager. (default "quay.io/jetstack/cert-manager-acmesolver:canary")
+ --acme-http01-solver-nameservers strings A list of comma separated dns server endpoints used for ACME HTTP01 check requests. This should be a list containing host and port, for example 8.8.8.8:53,8.8.4.4:53
+ --acme-http01-solver-resource-limits-cpu string Defines the resource limits CPU size when spawning new ACME HTTP01 challenge solver pods. (default "100m")
+ --acme-http01-solver-resource-limits-memory string Defines the resource limits Memory size when spawning new ACME HTTP01 challenge solver pods. (default "64Mi")
+ --acme-http01-solver-resource-request-cpu string Defines the resource request CPU size when spawning new ACME HTTP01 challenge solver pods. (default "10m")
+ --acme-http01-solver-resource-request-memory string Defines the resource request Memory size when spawning new ACME HTTP01 challenge solver pods. (default "64Mi")
+ --acme-http01-solver-run-as-non-root Defines the ability to run the http01 solver as root for troubleshooting issues (default true)
+ --add_dir_header If true, adds the file directory to the header of the log messages
+ --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
+ --auto-certificate-annotations strings The annotation consumed by the ingress-shim controller to indicate a ingress is requesting a certificate (default [kubernetes.io/tls-acme])
+ --cluster-issuer-ambient-credentials Whether a cluster-issuer may make use of ambient credentials for issuers. 'Ambient Credentials' are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the ClusterIssuer API object. When this flag is enabled, the following sources for credentials are also used: AWS - All sources the Go SDK defaults to, notably including any EC2 IAM roles available via instance metadata. (default true)
+ --cluster-resource-namespace string Namespace to store resources owned by cluster scoped resources such as ClusterIssuer in. This must be specified if ClusterIssuers are enabled. (default "kube-system")
+ --controllers strings A list of controllers to enable. '--controllers=*' enables all on-by-default controllers, '--controllers=foo' enables just the controller named 'foo', '--controllers=*,-foo' disables the controller named 'foo'.
+ All controllers: issuers, clusterissuers, certificates-metrics, ingress-shim, gateway-shim, orders, challenges, certificaterequests-issuer-acme, certificaterequests-approver, certificaterequests-issuer-ca, certificaterequests-issuer-selfsigned, certificaterequests-issuer-vault, certificaterequests-issuer-venafi, certificates-trigger, certificates-issuing, certificates-key-manager, certificates-request-manager, certificates-readiness, certificates-revision-manager (default [*])
+ --copied-annotation-prefixes strings Specify which annotations should/shouldn't be copiedfrom Certificate to CertificateRequest and Order, as well as from CertificateSigningRequest to Order, by passing a list of annotation key prefixes.A prefix starting with a dash(-) specifies an annotation that shouldn't be copied. Example: '*,-kubectl.kuberenetes.io/'- all annotationswill be copied apart from the ones where the key is prefixed with 'kubectl.kubernetes.io/'. (default [*,-kubectl.kubernetes.io/,-fluxcd.io/,-argocd.argoproj.io/])
+ --default-issuer-group string Group of the Issuer to use when the tls is requested but issuer group is not specified on the ingress resource. (default "cert-manager.io")
+ --default-issuer-kind string Kind of the Issuer to use when the tls is requested but issuer kind is not specified on the ingress resource. (default "Issuer")
+ --default-issuer-name string Name of the Issuer to use when the tls is requested but issuer name is not specified on the ingress resource.
+ --dns01-check-retry-period duration The duration the controller should wait between a propagation check. Despite the name, this flag is used to configure the wait period for both DNS01 and HTTP01 challenge propagation checks. For DNS01 challenges the propagation check verifies that a TXT record with the challenge token has been created. For HTTP01 challenges the propagation check verifies that the challenge token is served at the challenge URL.This should be a valid duration string, for example 180s or 1h (default 10s)
+ --dns01-recursive-nameservers strings A list of comma separated dns server endpoints used for DNS01 check requests. This should be a list containing host and port, for example 8.8.8.8:53,8.8.4.4:53
+ --dns01-recursive-nameservers-only When true, cert-manager will only ever query the configured DNS resolvers to perform the ACME DNS01 self check. This is useful in DNS constrained environments, where access to authoritative nameservers is restricted. Enabling this option could cause the DNS01 self check to take longer due to caching performed by the recursive nameservers.
+ --enable-certificate-owner-ref Whether to set the certificate resource as an owner of secret where the tls certificate is stored. When this flag is enabled, the secret will be automatically removed when the certificate resource is deleted.
+ --enable-profiling Enable profiling for controller.
+ --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
+ AdditionalCertificateOutputFormats=true|false (ALPHA - default=false)
+ AllAlpha=true|false (ALPHA - default=false)
+ AllBeta=true|false (BETA - default=false)
+ ExperimentalCertificateSigningRequestControllers=true|false (ALPHA - default=false)
+ ExperimentalGatewayAPISupport=true|false (ALPHA - default=false)
+ LiteralCertificateSubject=true|false (ALPHA - default=false)
+ ServerSideApply=true|false (ALPHA - default=false)
+ StableCertificateRequestName=true|false (ALPHA - default=false)
+ UseCertificateRequestBasicConstraints=true|false (ALPHA - default=false)
+ ValidateCAA=true|false (ALPHA - default=false)
+ -h, --help help for cert-manager-controller
+ --issuer-ambient-credentials Whether an issuer may make use of ambient credentials. 'Ambient Credentials' are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the Issuer API object. When this flag is enabled, the following sources for credentials are also used: AWS - All sources the Go SDK defaults to, notably including any EC2 IAM roles available via instance metadata.
+ --kube-api-burst int the maximum burst queries-per-second of requests sent to the Kubernetes apiserver (default 50)
+ --kube-api-qps float32 indicates the maximum queries-per-second requests to the Kubernetes apiserver (default 20)
+ --kubeconfig string Paths to a kubeconfig. Only required if out-of-cluster.
+ --leader-elect If true, cert-manager will perform leader election between instances to ensure no more than one instance of cert-manager operates at a time (default true)
+ --leader-election-lease-duration duration The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. This is only applicable if leader election is enabled. (default 1m0s)
+ --leader-election-namespace string Namespace used to perform leader election. Only used if leader election is enabled (default "kube-system")
+ --leader-election-renew-deadline duration The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. This is only applicable if leader election is enabled. (default 40s)
+ --leader-election-retry-period duration The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled. (default 15s)
+ --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+ --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
+ --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
+ --log_file string If non-empty, use this log file (no effect when -logtostderr=true)
+ --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
+ --logtostderr log to standard error instead of files (default true)
+ --master string Optional apiserver host address to connect to. If not specified, autoconfiguration will be attempted.
+ --max-concurrent-challenges int The maximum number of challenges that can be scheduled as 'processing' at once. (default 60)
+ --metrics-listen-address string The host and port that the metrics endpoint should listen on. (default "0.0.0.0:9402")
+ --namespace string If set, this limits the scope of cert-manager to a single namespace and ClusterIssuers are disabled. If not specified, all namespaces will be watched
+ --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
+ --profiler-address string The host and port that Go profiler should listen on, i.e localhost:6060. Ensure that profiler is not exposed on a public address. Profiler will be served at /debug/pprof. (default "localhost:6060")
+ --skip_headers If true, avoid header prefixes in the log messages
+ --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
+ --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
+ -v, --v Level number for the log level verbosity
+ --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
+```
diff --git a/content/v1.12-docs/cli/webhook.md b/content/v1.12-docs/cli/webhook.md
new file mode 100644
index 0000000000..f4d6ef30c3
--- /dev/null
+++ b/content/v1.12-docs/cli/webhook.md
@@ -0,0 +1,51 @@
+---
+title: webhook CLI reference
+description: "cert-manager webhook CLI documentation"
+---
+```
+Webhook component providing API validation, mutation and conversion functionality for cert-manager (canary) ()
+
+Usage:
+ webhook [flags]
+
+Flags:
+ --add-dir-header If true, adds the file directory to the header of the log messages
+ --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
+ --api-server-host string Optional apiserver host address to connect to. If not specified, autoconfiguration will be attempted.
+ --config string Path to a file containing a WebhookConfiguration object used to configure the webhook
+ --dynamic-serving-ca-secret-name string name of the secret used to store the CA that signs serving certificates certificates
+ --dynamic-serving-ca-secret-namespace string namespace of the secret used to store the CA that signs serving certificates
+ --dynamic-serving-dns-names strings DNS names that should be present on certificates generated by the dynamic serving CA
+ --enable-profiling Enable profiling for webhook.
+ --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
+ AdditionalCertificateOutputFormats=true|false (ALPHA - default=false)
+ AllAlpha=true|false (ALPHA - default=false)
+ AllBeta=true|false (BETA - default=false)
+ ExperimentalCertificateSigningRequestControllers=true|false (ALPHA - default=false)
+ ExperimentalGatewayAPISupport=true|false (ALPHA - default=false)
+ LiteralCertificateSubject=true|false (ALPHA - default=false)
+ ServerSideApply=true|false (ALPHA - default=false)
+ StableCertificateRequestName=true|false (ALPHA - default=false)
+ UseCertificateRequestBasicConstraints=true|false (ALPHA - default=false)
+ ValidateCAA=true|false (ALPHA - default=false)
+ --healthz-port int port number to listen on for insecure healthz connections (default 6080)
+ -h, --help help for webhook
+ --kubeconfig string optional path to the kubeconfig used to connect to the apiserver. If not specified, in-cluster-config will be used
+ --log-backtrace-at traceLocation when logging hits line file:N, emit a stack trace (default :0)
+ --log-dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
+ --log-file string If non-empty, use this log file (no effect when -logtostderr=true)
+ --log-file-max-size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
+ --logtostderr log to standard error instead of files (default true)
+ --one-output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
+ --profiler-address string Address of the Go profiler (pprof). This should never be exposed on a public interface. If this flag is not set, the profiler is not run. (default "localhost:6060")
+ --secure-port int port number to listen on for secure TLS connections (default 6443)
+ --skip-headers If true, avoid header prefixes in the log messages
+ --skip-log-headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
+ --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
+ --tls-cert-file string path to the file containing the TLS certificate to serve with
+ --tls-cipher-suites strings Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be use. Possible values: TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_RC4_128_SHA
+ --tls-min-version string Minimum TLS version supported. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13
+ --tls-private-key-file string path to the file containing the TLS private key to serve with
+ -v, --v Level number for the log level verbosity
+ --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
+```
diff --git a/content/v1.12-docs/concepts/README.md b/content/v1.12-docs/concepts/README.md
new file mode 100644
index 0000000000..48ed7e2377
--- /dev/null
+++ b/content/v1.12-docs/concepts/README.md
@@ -0,0 +1,11 @@
+---
+title: Concepts
+description: cert-manager core concepts
+---
+
+There are several components and ideas that make up cert-manager. This section
+describes them on a conceptual level, to aid with understanding how cert-manager
+does its job.
+
+You probably don't want this section if you're just getting started; check out
+a [tutorial](../tutorials/README.md) instead.
\ No newline at end of file
diff --git a/content/v1.12-docs/concepts/acme-orders-challenges.md b/content/v1.12-docs/concepts/acme-orders-challenges.md
new file mode 100644
index 0000000000..80c31606e4
--- /dev/null
+++ b/content/v1.12-docs/concepts/acme-orders-challenges.md
@@ -0,0 +1,100 @@
+---
+title: ACME Orders and Challenges
+description: 'cert-manager core concepts: ACME Orders and Challenges'
+---
+
+cert-manager supports requesting certificates from ACME servers, including from
+[Let's Encrypt](https://letsencrypt.org/), with use of the [ACME
+Issuer](../configuration/acme/README.md). These certificates are typically trusted on
+the public Internet by most computers. To successfully request a certificate,
+cert-manager must solve ACME Challenges which are completed in order to prove
+that the client owns the DNS addresses that are being requested.
+
+In order to complete these challenges, cert-manager introduces two
+`CustomResource` types; `Orders` and `Challenges`.
+
+## Orders
+
+`Order` resources are used by the ACME issuer to manage the lifecycle of an ACME
+'order' for a signed TLS certificate. More details on ACME orders and domain
+validation can be found on the Let's Encrypt website
+[here](https://letsencrypt.org/how-it-works/). An order represents a single
+certificate request which will be created automatically once a new
+[`CertificateRequest`](./certificaterequest.md) resource referencing an ACME
+issuer has been created. `CertificateRequest` resources are created
+automatically by cert-manager once a [`Certificate`](./certificate.md) resource
+is created, has its specification changed, or needs renewal.
+
+As an end-user, you will never need to manually create an `Order` resource.
+Once created, an `Order` cannot be changed. Instead, a new `Order` resource must
+be created.
+
+The `Order` resource encapsulates multiple ACME 'challenges' for that 'order',
+and as such, will manage one or more `Challenge` resources.
+
+## Challenges
+
+`Challenge` resources are used by the ACME issuer to manage the lifecycle of an
+ACME 'challenge' that must be completed in order to complete an 'authorization'
+for a single DNS name/identifier.
+
+When an `Order` resource is created, the order controller will create
+`Challenge` resources for each DNS name that is being authorized with the ACME
+server.
+
+As an end-user, you will never need to manually create a `Challenge` resource.
+Once created, a `Challenge` cannot be changed. Instead, a new `Challenge`
+resource must be created.
+
+### Challenge Lifecycle
+
+After a `Challenge` resource has been created, it will be initially queued for
+processing. Processing will not begin until the challenge has been 'scheduled'
+to start. This scheduling process prevents too many challenges being attempted
+at once, or multiple challenges for the same DNS name being attempted at once.
+For more information on how challenges are scheduled, read the [challenge
+scheduling](#challenge-scheduling).
+
+Once a challenge has been scheduled, it will first be 'synced' with the ACME
+server in order to determine its current state. If the challenge is already
+valid, its 'state' will be updated to 'valid', and will also set
+`status.processing = false` to 'unschedule' itself.
+
+If the challenge is still 'pending', the challenge controller will 'present' the
+challenge using the configured solver, one of HTTP01 or DNS01. Once the
+challenge has been 'presented', it will set `status.presented = true`.
+
+Once 'presented', the challenge controller will perform a 'self check' to
+ensure that the challenge has 'propagated' (i.e. the authoritative DNS servers
+have been updated to respond correctly, or the changes to the ingress resources
+have been observed and in-use by the ingress controller).
+
+If the self check fails, cert-manager will retry the self check with a fixed 10
+second retry interval. Challenges that do not ever complete the self check will
+continue retrying until the user intervenes by either retrying the `Order` (by
+deleting the `Order` resource) or amending the associated `Certificate` resource
+to resolve any configuration errors.
+
+Once the self check is passing, the ACME 'authorization' associated with this
+challenge will be 'accepted'.
+
+The final state of the authorization after accepting it will be copied across to
+the Challenge's `status.state` field, as well as the 'error reason' if an error
+occurred whilst the ACME server attempted to validate the challenge.
+
+Once a Challenge has entered the `valid`, `invalid`, `expired` or `revoked`
+state, it will set `status.processing = false` to prevent any further processing
+of the ACME challenge, and to allow another challenge to be scheduled if there
+is a backlog of challenges to complete.
+
+### Challenge Scheduling
+
+Instead of attempting to process all challenges at once, challenges are
+'scheduled' by cert-manager.
+
+This scheduler applies a cap on the maximum number of simultaneous challenges
+as well as disallows two challenges for the same DNS name and solver type
+(`HTTP01` or `DNS01`) to be completed at once.
+
+The maximum number of challenges that can be processed at a time is 60 as of
+[`ddff78`](https://github.com/cert-manager/cert-manager/blob/ddff78f011558e64186d61f7c693edced1496afa/pkg/controller/acmechallenges/scheduler/scheduler.go#L31-L33).
\ No newline at end of file
diff --git a/content/v1.12-docs/concepts/ca-injector.md b/content/v1.12-docs/concepts/ca-injector.md
new file mode 100644
index 0000000000..2c7c8dd638
--- /dev/null
+++ b/content/v1.12-docs/concepts/ca-injector.md
@@ -0,0 +1,234 @@
+---
+title: CA Injector
+description: 'cert-manager core concepts: CA Injector'
+---
+
+`cainjector` helps to configure the CA certificates for:
+[Mutating Webhooks],
+[Validating Webhooks]
+[Conversion Webhooks] and [API Services]
+
+In particular, `cainjector` populates the `caBundle` field of four API types:
+`ValidatingWebhookConfiguration`,
+`MutatingWebhookConfiguration`
+`CustomResourceDefinition` and `APIService`.
+The first three resource types are used to configure how the Kubernetes API server connects to webhooks.
+This `caBundle` data is loaded by the Kubernetes API server and used to verify the serving certificates of webhook API servers.
+`APIService` is used to represent an [Extension API Server]. `caBundle` of `APIService` can be populated with CA cert that can be used to validate the API server's serving certificate.
+
+We will refer to these four API types as *injectable* resources.
+
+
+An *injectable* resource MUST have one of these annotations:
+`cert-manager.io/inject-ca-from`,
+`cert-manager.io/inject-ca-from-secret`, or
+`cert-manager.io/inject-apiserver-ca`, depending on the injection *source*.
+This is explained in more detail below.
+
+`cainjector` copies CA data from one of three *sources*:
+a Kubernetes `Secret`,
+a cert-manager `Certificate`, or from
+the Kubernetes API server CA certificate (which `cainjector` itself uses to verify its TLS connection to the Kubernetes API server).
+
+If the *source* is a Kubernetes `Secret`, that resource MUST also have an `cert-manager.io/allow-direct-injection: "true"` annotation.
+The three *source* types are explained in more detail below.
+
+
+## Examples
+
+Here are examples demonstrating how to use the three `cainjector` *sources*.
+In each case we use `ValidatingWebhookConfiguration` as the *injectable*,
+but you can substitute `MutatingWebhookConfiguration` or `CustomResourceDefinition` definition instead.
+
+### Injecting CA data from a Certificate resource
+
+Here is an example of a `ValidatingWebhookConfiguration`
+configured with the annotation `cert-manager.io/inject-ca-from`,
+which will make `cainjector` populate the `caBundle` field using CA data from a cert-manager `Certificate`.
+
+NOTE: This example does not deploy a webhook server,
+it only deploys a partial webhook configuration,
+but it should be sufficient to help you understand what `cainjector` does:
+
+```yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: example1
+
+---
+
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: webhook1
+ annotations:
+ cert-manager.io/inject-ca-from: example1/webhook1-certificate
+webhooks:
+- name: webhook1.example.com
+ admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook1
+ namespace: example1
+ path: /validate
+ port: 443
+ sideEffects: None
+
+---
+
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: webhook1-certificate
+ namespace: example1
+spec:
+ secretName: webhook1-certificate
+ dnsNames:
+ - webhook1.example1
+ issuerRef:
+ name: selfsigned
+
+---
+
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: selfsigned
+ namespace: example1
+spec:
+ selfSigned: {}
+```
+
+You should find that the `caBundle` value is now identical to the CA value in the `Secret` for the `Certificate`:
+
+```
+kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io webhook1 -o yaml | grep caBundle
+kubectl -n example1 get secret webhook1-certificate -o yaml | grep ca.crt
+```
+
+And after a short time, the Kubernetes API server will read that new `caBundle` value and use it to verify a TLS connection to the webhook server.
+
+### Injecting CA data from a Secret resource
+
+Here is another example of a `ValidatingWebhookConfiguration`
+this time configured with the annotation `cert-manager.io/inject-ca-from-secret`,
+which will make `cainjector` populate the `caBundle` field using CA data from a Kubernetes `Secret`.
+
+NOTE: This example does not deploy a webhook server,
+it only deploys a partial webhook configuration,
+but it should be sufficient to help you understand what `cainjector` does:
+
+```yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: example2
+
+---
+
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: webhook2
+ annotations:
+ cert-manager.io/inject-ca-from-secret: example2/example-ca
+webhooks:
+- name: webhook2.example.com
+ admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook2
+ namespace: example2
+ path: /validate
+ port: 443
+ sideEffects: None
+
+---
+
+apiVersion: v1
+kind: Secret
+metadata:
+ name: example-ca
+ namespace: example2
+ annotations:
+ cert-manager.io/allow-direct-injection: "true"
+type: kubernetes.io/tls
+data:
+ ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5akNDQWQ2Z0F3SUJBZ0lRTkdJZ24yM3BQYVpNbk9MUjJnVmZHakFOQmdrcWhraUc5dzBCQVFzRkFEQVYKTVJNd0VRWURWUVFERXdwRmVHRnRjR3hsSUVOQk1CNFhEVEl3TURreU5ERTFOREEwTVZvWERUSXdNVEl5TXpFMQpOREEwTVZvd0ZURVRNQkVHQTFVRUF4TUtSWGhoYlhCc1pTQkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBS2F3RzVoMzlreHdyNEl0WCtHaDNYVWQrdTVJc2ZlSFdoTTc4TTRQTmZFeXhQMXoKRmNLN1d0MHJFMkwwNUppYmQ4ZjNpb3k5OXNnQ3I4OEw2SWxYZTB0RnkzNysxenJ4TFluR2hDQnZzZjltd0hLbgpIVTEvNERwQjROZkhPbFllNE9tbHVoNE9HdmZINU1EbDh5OWZGMjhXRXVBQ2dwdmpCUWxvRDNlVjJ5UmJvQ2kyCmtSTDJWYTFZL0FQZEpWK21VYkFvZmg0bllmUmNLRTJsSUg0RG5ZdXFPU3JaaituZUQ2M2RTSktxcHQ5K2luN2YKNHljZ2pQYU93MmdyKzhLK291QTlSQTV1VDI3SVNJcUJDcEV6elRqbVBUUWNvUTYxZGF0aDZkc1lsTEU4aWZWUwp4RWZuVEdQKy94M0FXQXR4eU5lanVuZGFXbVNFL3h5OHh0K0FxblVDQXdFQUFhTkNNRUF3RGdZRFZSMFBBUUgvCkJBUURBZ0trTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkowNkc5eEc2V1VBTHB6T3JYaHAKV2dsTm5qMkFNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUI3ZG9CZnBLR3o4VlRQSnc0YXhpdisybzJpMHE1SQpSRzU2UE81WnhKQktZQlRROElHQmFOSm1yeGtmNTJCV0ttUGp4cXlNSGRwWjVBU00zOUJkZVUzRGtEWHp4RkgwCjM5RU12UnhIUERyMGQ4cTFFbndQT0xZY1hzNjJhYjdidE11cTJUMFNNZzRYMkY5VmNKTW5YdjlrNnA0VGZNR3MKVThCQnJhVGhUZm53ejBsWXMyblFjdzNmZjZ1bG1wWlk4K3BTak1aVDNJZHZOMFA4Y2hOdUlmUFRHWDJmSlo2NQpxcUUrelRoU3hIeXFTOTVoczhsd1lRRUhGQlVsalRnMCtQZThXL0hOSXZBOU9TYWw1U3UvdlhydmcxN04xdHVyCk5XcWRyZU5OVm1ubXMvTFJodmthWTBGblRvbFNBRkNXWS9GSDY5ZzRPcThiMHVyK3JVMHZOZFFXCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+ tls.key: ""
+ tls.crt: ""
+```
+
+You should find that the `caBundle` value is now identical to the `ca.crt` value in the `Secret`:
+
+```
+kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io webhook2 -o yaml | grep caBundle
+```
+
+And after a short time, the Kubernetes API server will read that new `caBundle` value and use it to verify a TLS connection to the webhook server.
+
+This `Secret` based injection mechanism can operate independently of the `Certificate` based mechanism described earlier.
+It will work without the cert-manager CRDs installed
+and it will work if the cert-manager CRDs and associated webhook servers are not yet configured.
+
+NOTE: For this reason, cert-manager uses the `Secret` based injection mechanism to bootstrap its own webhook server.
+The cert-manager webhook server generates its own private key and self-signed certificate and places them in a `Secret` when it starts up.
+
+### Injecting the Kubernetes API Server CA
+
+Here is another example of a `ValidatingWebhookConfiguration`
+this time configured with the annotation `cert-manager.io/inject-apiserver-ca: "true"`,
+which will make `cainjector` populate the `caBundle` field using the same CA certificate used by the Kubernetes API server.
+
+NOTE: This example does not deploy a webhook server,
+it only deploys a partial webhook configuration,
+but it should be sufficient to help you understand what `cainjector` does:
+
+```yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: example3
+
+---
+
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: webhook3
+ annotations:
+ cert-manager.io/inject-apiserver-ca: "true"
+webhooks:
+- name: webhook3.example.com
+ admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook3
+ namespace: example3
+ path: /validate
+ port: 443
+ sideEffects: None
+
+```
+
+You should find that the `caBundle` value is now identical to the CA used in your `KubeConfig` file:
+
+```
+kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io webhook3 -o yaml | grep caBundle
+kubectl config view --minify --raw | grep certificate-authority-data
+```
+
+And after a short time, the Kubernetes API server will read that new `caBundle` value and use it to verify a TLS connection to the webhook server.
+
+NOTE: In this case you will have to ensure that your webhook is configured to serve a TLS certificate that has been signed by the Kubernetes cluster CA.
+The disadvantages of this mechanism are that: you will require access to the private key of the Kubernetes cluster CA and you will need to manually rotate the webhook certificate.
+
+[Validating Webhooks]: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook
+[Mutating Webhooks]: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook
+[Conversion Webhooks]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#webhook-conversion
+[API Services]: https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/
+[Extension API Server]: https://kubernetes.io/docs/tasks/extend-kubernetes/setup-extension-api-server/
\ No newline at end of file
diff --git a/content/docs/concepts/certificate.md b/content/v1.12-docs/concepts/certificate.md
similarity index 100%
rename from content/docs/concepts/certificate.md
rename to content/v1.12-docs/concepts/certificate.md
diff --git a/content/docs/concepts/certificaterequest.md b/content/v1.12-docs/concepts/certificaterequest.md
similarity index 83%
rename from content/docs/concepts/certificaterequest.md
rename to content/v1.12-docs/concepts/certificaterequest.md
index e8f102d4ef..5dbc1ca546 100644
--- a/content/docs/concepts/certificaterequest.md
+++ b/content/v1.12-docs/concepts/certificaterequest.md
@@ -60,7 +60,6 @@ manage the logic and life cycle of `CertificateRequests`.
used and relied upon by controllers or services to make decisions on what
actions to take next on the resource.
-
### Ready
Each ready condition consists of the pair `Ready` - a boolean value, and
`Reason` - a string. The set of values and meanings are as follows:
@@ -68,8 +67,30 @@ Each ready condition consists of the pair `Ready` - a boolean value, and
| Ready | Reason | Condition Meaning |
| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| False | Pending | The `CertificateRequest` is currently pending, waiting for some other operation to take place. This could be that the `Issuer` does not exist yet or the `Issuer` is in the process of issuing a certificate. |
-| False | Failed | The certificate has failed to be issued - either the returned certificate failed to be decoded or an instance of the referenced issuer used for signing failed. No further action will be taken on the `CertificateRequest` by it's controller. |
-| True | Issued | A signed certificate has been successfully issued by the referenced `Issuer`. |
+| False | Failed | The certificate has failed to be issued - either the returned certificate failed to be decoded or an instance of the referenced issuer used for signing failed. No further action will be taken on the `CertificateRequest` by its controller and it can be considered terminally failed. |
+| True | Issued | A signed certificate has been successfully issued by the referenced `Issuer`. |
+
+This condition should be set by the issuer.
+
+### Denied
+| Denied | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| True | \ | The `CertificateRequest` was Denied by an approver. This `CertificateRequest` can be considered terminally failed.
+
+This condition should only be set by an approver.
+
+### Approved
+| Approved | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| True | \ | The `CertificateRequest` was approved by the approver. This `CertificateRequest` is approved and can be issued by the issuer.
+
+This condition should only be set by an approver.
+
+### InvalidRequest
+| InvalidRequest | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| True | \ | The `CertificateRequest` is invalid. This `CertificateRequest` can be considered terminally failed.
+
## UserInfo
diff --git a/content/v1.12-docs/concepts/issuer.md b/content/v1.12-docs/concepts/issuer.md
new file mode 100644
index 0000000000..6293369992
--- /dev/null
+++ b/content/v1.12-docs/concepts/issuer.md
@@ -0,0 +1,44 @@
+---
+title: Issuer
+description: 'cert-manager core concepts: Issuers and ClusterIssuers'
+---
+
+`Issuers`, and `ClusterIssuers`, are Kubernetes resources that represent
+certificate authorities (CAs) that are able to generate signed certificates by honoring
+certificate signing requests. All cert-manager certificates require a referenced
+issuer that is in a ready condition to attempt to honor the request.
+
+An example of an `Issuer` type is `CA`. A simple `CA` `Issuer` is as follows:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: ca-issuer
+ namespace: mesh-system
+spec:
+ ca:
+ secretName: ca-key-pair
+```
+
+This is a simple `Issuer` that will sign certificates based on a private key.
+The certificate stored in the secret `ca-key-pair` can then be used to trust
+newly signed certificates by this `Issuer` in a Public Key Infrastructure (PKI)
+system.
+
+## Namespaces
+
+An `Issuer` is a namespaced resource, and it is not possible to issue
+certificates from an `Issuer` in a different namespace. This means you will need
+to create an `Issuer` in each namespace you wish to obtain `Certificates` in.
+
+If you want to create a single `Issuer` that can be consumed in multiple
+namespaces, you should consider creating a `ClusterIssuer` resource. This is
+almost identical to the `Issuer` resource, however is non-namespaced so it
+can be used to issue `Certificates` across all namespaces.
+
+## Supported Issuers
+
+cert-manager supports a number of 'in-tree', as well as 'out-of-tree' `Issuer`
+types. An exhaustive list of these `Issuer` types can be found in the
+cert-manager [configuration documentation](../configuration/README.md).
diff --git a/content/v1.12-docs/concepts/webhook.md b/content/v1.12-docs/concepts/webhook.md
new file mode 100644
index 0000000000..1bcbbee769
--- /dev/null
+++ b/content/v1.12-docs/concepts/webhook.md
@@ -0,0 +1,80 @@
+---
+title: All About the cert-manager Webhook
+description: |
+ Learn about the webhook component of cert-manager, which validates, converts and sets default values for the cert-manager custom resources
+---
+
+cert-manager extends the Kubernetes API using Custom Resource Definitions.
+It installs a webhook which has three main functions:
+
+- [Validation](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook):
+ Ensures that when cert-manager resources are created or updated, they conform
+ to the rules of the API. This validation is more in depth than for example
+ ensuring resources conform to the OpenAPI schema, but instead contains logic such as
+ not allowing to specify more than one `Issuer` type per `Issuer` resource. The
+ validating admission is always called and will respond with a success or
+ failed response.
+- [Mutation / Defaulting](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook):
+ Changes the contents of resources during create and update operations, for
+ example to set default values.
+- [Conversion](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#webhook-conversion):
+ The webhook is also responsible for implementing a conversion over versions
+ in the cert-manager `CustomResources` (`cert-manager.io`). This means that
+ multiple API versions can be supported simultaneously; from `v1alpha2` through to `v1`.
+ This makes it possible to rely on a particular version of our
+ configuration schema.
+
+> ℹ️ This is known as Dynamic Admission Control.
+> Read more about [Dynamic Admission Control](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) in the Kubernetes documentation.
+
+## Overview
+
+The webhook component is deployed as another pod that runs alongside the main
+cert-manager controller and CA injector components.
+
+In order for the API server to communicate with the webhook component, the
+webhook requires a TLS certificate that the apiserver is configured to trust.
+
+The [`cainjector`](./ca-injector.md) creates `secret/cert-manager-webhook-ca`, a self-signed root CA certificate which is used to sign certificates for the webhook pod.
+
+Then the webhook can be configured with either
+
+1. paths to a TLS certificate and key signed by the webhook CA, or
+2. a reference to the CA Secret for dynamic generation of the certificate and key on webhook startup
+
+## Known Problems and Solutions
+
+### Webhook connection problems on GKE private cluster
+
+If errors occur around the webhook but the webhook is running then the webhook
+is most likely not reachable from the API server. In this case, ensure that the
+API server can communicate with the webhook by following the [GKE private
+cluster explanation](../installation/compatibility.md#gke).
+
+### Webhook connection problems on AWS EKS
+
+When using a custom CNI (such as Weave or Calico) on EKS, the webhook cannot be reached by cert-manager.
+This happens because the control plane cannot be configured to run on a custom CNI on EKS,
+so the CNIs differ between control plane and worker nodes.
+The solution is to [run the webhook in the host network](../installation/compatibility.md#aws-eks) so it can be reached by cert-manager.
+
+### Webhook connection problems shortly after cert-manager installation
+
+When you first install cert-manager, it will take a few seconds before the cert-manager API is usable.
+This is because the cert-manager API requires the cert-manager webhook server, which takes some time to start up.
+Here's why:
+
+* The webhook server performs a leader election at startup which may take a few seconds.
+* The webhook server may take a few seconds to start up and to generate its self-signed CA and serving certificate and to publish those to a Secret.
+* `cainjector` performs a leader election at start up which can take a few seconds.
+* `cainjector`, once started, will take a few seconds to update the `caBundle` in all the webhook configurations.
+
+For these reasons, after installing cert-manager and when performing post-installation cert-manager API operations,
+you will need to check for temporary API configuration errors and retry.
+
+You could also add a post-installation check which performs `kubectl --dry-run` operations on the cert-manager API.
+Or you could add a post-installation check which automatically retries the [Installation Verification](../installation/verify.md) steps until they succeed.
+
+### Other Webhook Problems
+
+If you encounter any other problems with the webhook, please refer to the [webhook troubleshooting guide](../troubleshooting/webhook.md).
diff --git a/content/v1.12-docs/configuration/README.md b/content/v1.12-docs/configuration/README.md
new file mode 100644
index 0000000000..85c5d1334f
--- /dev/null
+++ b/content/v1.12-docs/configuration/README.md
@@ -0,0 +1,30 @@
+---
+title: Issuer Configuration
+description: Learn about configuring cert-manager using Issuer and ClusterIssuer resources.
+---
+
+The first thing you'll need to configure after you've installed cert-manager is an `Issuer` or a `ClusterIssuer`.
+These are resources that represent certificate authorities (CAs)
+able to sign certificates in response to certificate signing requests.
+
+This section documents how the different issuer types can be configured. You might want to
+[read more about `Issuer` and `ClusterIssuer` resources](../concepts/issuer.md).
+
+cert-manager comes with a number of built-in certificate issuers which are denoted by being in
+the `cert-manager.io` group. You can also install external issuers in addition to the built-in types.
+Built-in and external issuers are treated the same and are configured similarly.
+
+## Cluster Resource Namespace
+
+When using `ClusterIssuer` resource types, ensure you understand the purpose of the
+Cluster Resource Namespace; this can be a common source
+of issues for people getting started with cert-manager.
+
+The `ClusterIssuer` resource is cluster scoped. This means that when referencing
+a secret via the `secretName` field, secrets will be looked for in the `Cluster
+Resource Namespace`. By default, this namespace is `cert-manager` however it can be
+changed via a flag on the cert-manager-controller component:
+
+```bash
+--cluster-resource-namespace=my-namespace
+```
diff --git a/content/v1.12-docs/configuration/acme/README.md b/content/v1.12-docs/configuration/acme/README.md
new file mode 100644
index 0000000000..3c658510e0
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/README.md
@@ -0,0 +1,392 @@
+---
+title: ACME
+description: 'cert-manager configuration: ACME Issuers'
+---
+
+The ACME Issuer type represents a single account registered with the Automated
+Certificate Management Environment (ACME) Certificate Authority server. When you
+create a new ACME `Issuer`, cert-manager will generate a private key which is
+used to identify you with the ACME server.
+
+Certificates issued by public ACME servers are typically trusted by client's
+computers by default. This means that, for example, visiting a website that is
+backed by an ACME certificate issued for that URL, will be trusted by default by
+most client's web browsers. ACME certificates are typically free.
+
+## Solving Challenges
+
+In order for the ACME CA server to verify that a client owns the domain, or
+domains, a certificate is being requested for, the client must complete
+"challenges". This is to ensure clients are unable to request certificates for
+domains they do not own and as a result, fraudulently impersonate another's
+site. As detailed in the [RFC8555](https://tools.ietf.org/html/rfc8555),
+cert-manager offers two challenge validations - HTTP01 and DNS01 challenges.
+
+[HTTP01](./http01/README.md) challenges are completed by presenting a computed
+key, that should be present at a HTTP URL endpoint and is routable over the
+internet. This URL will use the domain name requested for the certificate. Once
+the ACME server is able to get this key from this URL over the internet, the
+ACME server can validate you are the owner of this domain. When a HTTP01
+challenge is created, cert-manager will automatically configure your cluster
+ingress to route traffic for this URL to a small web server that presents this
+key.
+
+[DNS01](./dns01/README.md) challenges are completed by providing a computed key
+that is present at a DNS TXT record. Once this TXT record has been propagated
+across the internet, the ACME server can successfully retrieve this key via a
+DNS lookup and can validate that the client owns the domain for the requested
+certificate. With the correct permissions, cert-manager will automatically
+present this TXT record for your given DNS provider.
+
+## Configuration
+
+### Creating a Basic ACME Issuer
+
+All ACME `Issuers` follow a similar configuration structure - a clients `email`,
+a `server` URL, a `privateKeySecretRef`, and one or more `solvers`. Below is an
+example of a simple ACME issuer:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ # You must replace this email address with your own.
+ # Let's Encrypt will use this to contact you about expiring
+ # certificates, and issues related to your account.
+ email: user@example.com
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ privateKeySecretRef:
+ # Secret resource that will be used to store the account's private key.
+ name: example-issuer-account-key
+ # Add a single challenge solver, HTTP01 using nginx
+ solvers:
+ - http01:
+ ingress:
+ class: nginx
+```
+
+Solvers come in the form of [`dns01`](./dns01/README.md) and
+[`http01`](./http01/README.md) stanzas. For more information on how to configure
+these solver types, visit their respective documentation -
+[DNS01](./dns01/README.md), [HTTP01](./http01/README.md).
+
+### External Account Bindings
+
+cert-manager supports using External Account Bindings with your ACME account.
+External Account Bindings are used to associate your ACME account with an
+external account such as a CA custom database. This is typically not needed for
+most cert-manager users unless you know it is explicitly needed.
+
+External Account Bindings require two fields on an ACME `Issuer` which
+represents your ACME account. These fields are:
+
+- `keyID` - the key ID or account ID of which your external account binding is indexed by the
+external account manager
+- `keySecretRef` - the name and key of a secret containing a base 64 encoded
+URL string of your external account symmetric MAC key
+
+> Note: In _most_ cases, the MAC key must be encoded in `base64URL`. The
+> following command will base64-encode a key and convert it to `base64URL`:
+>
+> ```console
+> $ echo 'my-secret-key' | base64 -w0 | sed -e 's/+/-/g' -e 's/\//_/g' -e 's/=//g'
+> ```
+>
+> You can then create the Secret resource with:
+>
+> ```console
+> $ kubectl create secret generic eab-secret --from-literal \
+> secret={base64 encoded secret key}
+> ```
+
+An example of an ACME issuer with an External Account Binding is as follows.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: my-acme-server-with-eab
+spec:
+ acme:
+ email: user@example.com
+ server: https://my-acme-server-with-eab.com/directory
+ externalAccountBinding:
+ keyID: my-keyID-1
+ keySecretRef:
+ name: eab-secret
+ key: secret
+ privateKeySecretRef:
+ name: example-issuer-account-key
+ solvers:
+ - http01:
+ ingress:
+ class: nginx
+```
+> Note: cert-manager versions pre-`v1.3.0` also required users to specify the
+> MAC algorithm for EAB by setting
+> `Issuer.spec.acme.externalAccountBinding.keyAlgorithm` field. This field is
+> now deprecated because the upstream Go `x/crypto` library hardcodes the algorithm
+> to `HS256`. (See related discussion upstream
+> [`CL#41430`](https://github.com/golang/go/issues/41430)).
+### Reusing an ACME Account
+
+You may want to reuse a single ACME account across multiple clusters. This
+might especially be useful when using EAB. If the `disableAccountKeyGeneration`
+field is set, cert-manager will not create a new ACME account and use the
+existing key specified in `privateKeySecretRef`. Note that the
+`Issuer`/`ClusterIssuer` will not be ready and will continue to retry until the
+`Secret` is provided.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: my-acme-server-with-existing-acme-account
+spec:
+ acme:
+ email: user@example.com
+ disableAccountKeyGeneration: true
+ privateKeySecretRef:
+ name: example-issuer-account-key
+```
+
+
+### Adding Multiple Solver Types
+
+You may want to use different types of challenge solver configurations for
+different ingress controllers, for example if you want to issue wildcard
+certificates using `DNS01` alongside other certificates that are validated using
+`HTTP01`.
+
+The `solvers` stanza has an optional `selector` field, that can be used to
+specify which `Certificates`, and further, what DNS names *on those*
+`Certificates` should be used to solve challenges.
+
+There are three selector types that can be used to form the requirements that a
+`Certificate` must meet in order to be selected for a solver - `matchLabels`,
+`dnsNames` and `dnsZones`. You can have any number of these three selectors on a
+single solver.
+
+
+#### Match Labels
+
+The `matchLabel` selector requires that all `Certificates` match all of
+the labels that are defined in the string map list of that stanza. For example,
+the following `Issuer` will only match on `Certificates` that have the labels
+`"user-cloudflare-solver": "true"` and `"email": "user@example.com"`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ matchLabels:
+ "use-cloudflare-solver": "true"
+ "email": "user@example.com"
+```
+
+#### DNS Names
+
+The `dnsNames` selector is a list of exact DNS names that should be mapped to a
+solver. This means that `Certificates` containing any of these DNS names will
+be selected. If a match is found, a `dnsNames` selector will take precedence
+over a [`dnsZones`](#dns-zones) selector. If multiple solvers match with the
+same `dnsNames` value, the solver with the most matching labels in
+[`matchLabels`](#match-labels) will be selected. If neither has more matches,
+the solver defined earlier in the list will be selected.
+
+The following example will solve challenges of `Certificates` with DNS names
+`example.com` and `*.example.com` for these domains.
+
+> Note: `dnsNames` take an exact match and do not resolve wildcards, meaning the
+> following `Issuer` *will not* solve for DNS names such as `foo.example.com`.
+> Use the [`dnsZones`](#dns-zones) selector type to match all subdomains within
+> a zone.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ dnsNames:
+ - 'example.com'
+ - '*.example.com'
+```
+
+#### DNS Zones
+
+The `dnsZones` stanza defines a list of DNS zones that can be solved by this
+solver. If a DNS name is an exact match, or a subdomain of any of the specified
+`dnsZones`, this solver will be used, unless a more specific
+[`dnsNames`](#dns-names) match is configured. This means that `sys.example.com`
+will be selected over one specifying `example.com` for the domain
+`www.sys.example.com`. If multiple solvers match with the same `dnsZones` value,
+the solver with the most matching labels in [`matchLabels`](#match-labels) will
+be selected. If neither has more matches, the solver defined earlier in the list
+will be selected.
+
+In the following example, this solver will resolve challenges for the domain
+`example.com`, as well as all of its subdomains `*.example.com`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ dnsZones:
+ - 'example.com'
+```
+
+#### All Together
+
+Each solver is able to have any number of the three selector types defined. In
+the following example, the `DNS01` solver for CloudFlare will be used to solve
+challenges for domains for `Certificates` that contain the DNS names
+`a.example.com` and `b.example.com`. The `DNS01` solver for Google CloudDNS will
+be used to solve challenges for `Certificates` whose DNS names match
+zone `test.example.com` and all of its subdomains (e.g. `foo.test.example.com`).
+
+For all other challenges, the `HTTP01` solver will be used *only* if the
+`Certificate` also contains the label `"use-http01-solver": "true"`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ ...
+ solvers:
+ - http01:
+ ingress:
+ class: nginx
+ selector:
+ matchLabels:
+ "use-http01-solver": "true"
+ - dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ dnsNames:
+ - 'a.example.com'
+ - 'b.example.com'
+ - dns01:
+ cloudDNS:
+ project: my-project-id
+ hostedZoneName: 'test-example.com'
+ serviceAccountSecretRef:
+ key: sa
+ name: gcp-sa-secret
+ selector:
+ dnsZones:
+ - 'test.example.com' # This should be the DNS name of the zone
+```
+
+Each individual selector block can contain more than one selector type for
+example:
+
+```yaml
+solvers:
+- dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ matchLabels:
+ 'email': 'user@example.com'
+ 'solver': 'cloudflare'
+ dnsZones:
+ - 'test.example.com'
+ - 'example.dev'
+```
+
+In this case the `DNS01` solver for Cloudflare will only be used to solve a
+challenge for a DNS name if the `Certificate` has a label from
+`matchLabels` _and_ the DNS name matches a zone from `dnsZones`.
+
+## Private ACME Servers
+
+cert-manager should also work with private or self-hosted ACME servers, as long as they follow the ACME spec.
+
+If your ACME server doesn't use a publicly trusted certificate, you can pass a trusted CA to use when creating your
+issuer, from cert-manager 1.11 onwards:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: my-acme-server-issuer
+spec:
+ acme:
+ server: https://my-acme-server.example.com
+ caBundle:
+ ...
+```
+
+
+## Alternative Certificate Chains
+
+{/* The empty link below preserves old links to #alternative-certificate-chain", which matched the old title of this section */}
+
+
+
+It's possible to choose alternative certificate chains when fetching a certificate from an ACME server. This allows issuers to gracefully roll people over to a new root certificate during a transition period; the most famous example was the Let's Encrypt ["ISRG Root" changeover](https://community.letsencrypt.org/t/transition-to-isrgs-root-delayed-until-jan-11-2021/125516).
+
+This functionality is not exclusive to Let's Encrypt; if your ACME server supports signing by multiple CAs you can use `preferredChain` with the value of the Common Name of the chain you want in the Issuer part of the certificate. If the common name matches a difference chain, the server can choose to use and return that new chain.
+
+If the `preferredChain` does not match a certificate the server will return whatever it considers to be its default certificate.
+
+By way of an example, below is how a user would have requested an alternative chain before the (now completed) "ISRG Root" changeover, but note that since this change has already happened there's no need for this with Let's Encrypt any more:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt
+spec:
+ acme:
+ server: https://acme-v02.api.letsencrypt.org/directory
+ preferredChain: "ISRG Root X1"
+```
diff --git a/content/v1.12-docs/configuration/acme/dns01/README.md b/content/v1.12-docs/configuration/acme/dns01/README.md
new file mode 100644
index 0000000000..b9240f8045
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/README.md
@@ -0,0 +1,186 @@
+---
+title: DNS01
+description: 'cert-manager configuration: ACME DNS-01 challenges overview'
+---
+
+## Configuring DNS01 Challenge Provider
+
+This page contains details on the different options available on the `Issuer`
+resource's DNS01 challenge solver configuration.
+
+For more information on configuring ACME `Issuers` and their API format, read the
+[ACME Issuers](../README.md) documentation.
+
+DNS01 provider configuration must be specified on the `Issuer` resource, similar
+to the examples in the setting up documentation.
+
+You can read about how the DNS01 challenge type works on the [Let's Encrypt
+challenge types
+page](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge).
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ email: user@example.com
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ privateKeySecretRef:
+ name: example-issuer-account-key
+ solvers:
+ - dns01:
+ cloudDNS:
+ project: my-project
+ serviceAccountSecretRef:
+ name: prod-clouddns-svc-acct-secret
+ key: service-account.json
+```
+
+Each issuer can specify multiple different DNS01 challenge providers, and
+it is also possible to have multiple instances of the same DNS provider on a
+single `Issuer` (e.g. two CloudDNS accounts could be set, each with their own
+name).
+
+For more information on utilizing multiple solver types on a single `Issuer`,
+read the multiple-solver-types section.
+
+## Setting Nameservers for DNS01 Self Check
+
+cert-manager will check the correct DNS records exist before attempting a DNS01
+challenge. By default cert-manager will use the recursive nameservers taken
+from `/etc/resolv.conf` to query for the authoritative nameservers, which it will
+then query directly to verify the DNS records exist.
+
+If this is not desired (for example with multiple authoritative nameservers or
+split-horizon DNS), the cert-manager controller exposes two flags that allows
+you alter this behavior:
+
+`--dns01-recursive-nameservers` Comma separated string with host and port of the
+recursive nameservers cert-manager should query.
+
+`--dns01-recursive-nameservers-only` Forces cert-manager to only use the
+recursive nameservers for verification. Enabling this option could cause the DNS01
+self check to take longer due to caching performed by the recursive nameservers.
+
+
+Example usage:
+```bash
+--dns01-recursive-nameservers-only --dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53
+```
+
+If you're using the `cert-manager` helm chart, you can set recursive nameservers
+through `.Values.extraArgs` or at the command at helm install/upgrade time
+with `--set`:
+
+```bash
+--set 'extraArgs={--dns01-recursive-nameservers-only,--dns01-recursive-nameservers=8.8.8.8:53\,1.1.1.1:53}'
+```
+
+## Delegated Domains for DNS01
+
+By default, cert-manager will not follow CNAME records pointing to subdomains.
+
+If granting cert-manager access to the root DNS zone is not desired, then the
+`_acme-challenge.example.com` subdomain can instead be delegated to some other,
+less privileged domain (`less-privileged.example.org`). This could be achieved in the following way. Say, one has two zones:
+
+* `example.com`
+* `less-privileged.example.org`
+
+1. Create a CNAME record pointing to this less privileged domain:
+```
+_acme-challenge.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+```
+
+2. Grant cert-manager rights to update less privileged `less-privileged.example.org` zone
+
+3. Provide configuration/credentials for updating this less privileged zone
+and add an additional field into the relevant `dns01` solver. Note that `selector`
+field is still working for the original `example.com`, while credentials are provided for
+`less-privileged.example.org`
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ ...
+spec:
+ acme:
+ ...
+ solvers:
+ - selector:
+ dnsZones:
+ - 'example.com'
+ dns01:
+ # Valid values are None and Follow
+ cnameStrategy: Follow
+ route53:
+ region: eu-central-1
+ accessKeyID:
+ hostedZoneID:
+ secretAccessKeySecretRef:
+ ...
+```
+
+If you have a multitude of (sub)domains requiring separate certificates,
+it is possible to share an aliased less-privileged domain. To achieve it one should
+create a CNAME record for each (sub)domain like this:
+
+```txt
+_acme-challenge.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+_acme-challenge.www.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+_acme-challenge.foo.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+_acme-challenge.bar.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+```
+
+With this configuration cert-manager will follow CNAME records recursively in order to determine
+which DNS zone to update during DNS01 challenges.
+
+
+## Supported DNS01 providers
+
+A number of different DNS providers are supported for the ACME `Issuer`. Below
+is a listing of available providers, their `.yaml` configurations, along with
+additional Kubernetes and provider specific notes regarding their usage.
+
+- [ACMEDNS](./acme-dns.md)
+- [Akamai](./akamai.md)
+- [AzureDNS](./azuredns.md)
+- [CloudFlare](./cloudflare.md)
+- [Google](./google.md)
+- [Route53](./route53.md)
+- [DigitalOcean](./digitalocean.md)
+- [RFC2136](./rfc2136.md)
+
+## Webhook
+
+cert-manager also supports out of tree DNS providers using an external webhook.
+Links to these supported providers along with their documentation are below:
+
+- [`AliDNS-Webhook`](https://github.com/pragkent/alidns-webhook)
+- [`cert-manager-alidns-webhook`](https://github.com/DEVmachine-fr/cert-manager-alidns-webhook)
+- [`cert-manager-webhook-civo`](https://github.com/okteto/cert-manager-webhook-civo)
+- [`cert-manager-webhook-dnspod`](https://github.com/qqshfox/cert-manager-webhook-dnspod)
+- [`cert-manager-webhook-dnsimple`](https://github.com/neoskop/cert-manager-webhook-dnsimple)
+- [`cert-manager-webhook-gandi`](https://github.com/bwolf/cert-manager-webhook-gandi)
+- [`cert-manager-webhook-infomaniak`](https://github.com/Infomaniak/cert-manager-webhook-infomaniak)
+- [`cert-manager-webhook-inwx`](https://gitlab.com/smueller18/cert-manager-webhook-inwx)
+- [`cert-manager-webhook-linode`](https://github.com/slicen/cert-manager-webhook-linode)
+- [`cert-manager-webhook-oci`](https://gitlab.com/dn13/cert-manager-webhook-oci) (Oracle Cloud Infrastructure)
+- [`cert-manager-webhook-scaleway`](https://github.com/scaleway/cert-manager-webhook-scaleway)
+- [`cert-manager-webhook-selectel`](https://github.com/selectel/cert-manager-webhook-selectel)
+- [`cert-manager-webhook-softlayer`](https://github.com/cgroschupp/cert-manager-webhook-softlayer)
+- [`cert-manager-webhook-ibmcis`](https://github.com/jb-dk/cert-manager-webhook-ibmcis)
+- [`cert-manager-webhook-loopia`](https://github.com/Identitry/cert-manager-webhook-loopia)
+- [`cert-manager-webhook-arvan`](https://github.com/kiandigital/cert-manager-webhook-arvan)
+- [`bizflycloud-certmanager-dns-webhook`](https://github.com/bizflycloud/bizflycloud-certmanager-dns-webhook)
+- [`cert-manager-webhook-hetzner`](https://github.com/vadimkim/cert-manager-webhook-hetzner)
+- [`cert-manager-webhook-yandex-cloud`](https://github.com/malinink/cert-manager-webhook-yandex-cloud)
+- [`cert-manager-webhook-netcup`](https://github.com/aellwein/cert-manager-webhook-netcup)
+- [`cert-manager-webhook-pdns`](https://github.com/zachomedia/cert-manager-webhook-pdns)
+
+You can find more information on how to configure webhook providers [here](./webhook.md).
+
+To create a new unsupported DNS provider, follow the development documentation [here](../../../contributing/dns-providers.md).
diff --git a/content/v1.12-docs/configuration/acme/dns01/acme-dns.md b/content/v1.12-docs/configuration/acme/dns01/acme-dns.md
new file mode 100644
index 0000000000..968531bf5f
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/acme-dns.md
@@ -0,0 +1,220 @@
+---
+title: ACMEDNS
+description: 'cert-manager configuration: ACME DNS-01 challenges using ACMEDNS'
+---
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ solvers:
+ - dns01:
+ acmeDNS:
+ host: https://acme.example.com
+ accountSecretRef:
+ name: acme-dns
+ key: acmedns.json
+```
+
+In general, clients to ACMEDNS perform registration on the users behalf and
+inform them of the CNAME entries they must create. This is not possible in
+cert-manager, it is a non-interactive system. Registration must be carried out
+beforehand and the resulting credentials JSON uploaded to the cluster as a
+`Secret`. In this example, we use `curl` and the API endpoints directly.
+Information about setting up and configuring ACMEDNS is available on the
+[ACMEDNS project page](https://github.com/joohoi/acme-dns).
+
+1. First, register with the ACMEDNS server, in this example, there is one
+ running at `auth.example.com`. The command:
+
+ ```sh
+ curl -X POST http://auth.example.com/register
+ ```
+
+ will return a JSON with credentials for your registration:
+
+ ```json
+ {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": []
+ }
+ ```
+
+ It is strongly recommended to restrict the update endpoint to the IP
+ range of your pods. This is done at registration time as follows:
+
+ ```sh
+ curl -X POST http://auth.example.com/register \
+ -H "Content-Type: application/json" \
+ --data '{"allowfrom": ["10.244.0.0/16"]}'
+ ```
+
+ Make sure to update the `allowfrom` field to match your cluster
+ configuration. The JSON will now look like:
+
+ ```json
+ {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ }
+ ```
+
+2. Save this JSON to a file with the key as your domain. You can specify
+ multiple domains with the same credentials if you like. In our example,
+ the returned credentials can be used to verify ownership of
+ `example.com` and and `example.org`.
+
+ ```json
+ {
+ "example.com": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ },
+ "example.org": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ }
+ }
+ ```
+
+3. Next, update your primary DNS server with the CNAME record that will tell the
+ verifier how to locate the challenge TXT record. This is obtained from the
+ `fulldomain` field in the registration:
+
+ ```
+ _acme-challenge.example.com CNAME d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com
+ _acme-challenge.example.org CNAME d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com
+ ```
+
+ The "name" of the record always has the _acme-challenge subdomain, and
+ the "value" of the record matches exactly the fulldomain field from
+ registration.
+
+ At verification time, the domain name `d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com` will be a TXT
+ record that is set to your validation token. When the verifier queries `_acme-challenge.example.com`, it will
+ be directed to the correct location by this CNAME record. This proves that you control `example.com`
+
+4. Create a secret from the credentials JSON that was saved in step 2, this
+ secret is referenced in the `accountSecretRef` field of your DNS01
+ issuer settings. When creating an `Issuer` both this `Issuer` and
+ `Secret` must be in the same namespace. However for a `ClusterIssuer`
+ (which does not have a namespace) the `Secret` must be placed in the
+ same namespace as where the cert-manager pod is running in (in the
+ default setup `cert-manager`).
+
+ ```sh
+ kubectl create secret generic acme-dns --from-file acmedns.json
+ ```
+
+## Limitation of the `acme-dns` server
+
+The [`acme-dns`](https://github.com/joohoi/acme-dns) server has a [known
+limitation](https://github.com/cert-manager/cert-manager/issues/3610#issuecomment-849792721):
+when a set of credentials is used with more than 2 domains, cert-manager
+will fail solving the DNS01 challenges.
+
+Imagining that you have configured the ACMEDNS issuer with a single set of
+credentials, and that the "subdomain" of this set of credentials is
+`d420c923-bbd7-4056-ab64-c3ca54c9b3cf`:
+
+```yaml
+kind: Secret
+metadata:
+ name: auth-example-com
+stringData:
+ acmedns.json: |
+ {
+ "example.com": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ },
+ }
+---
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: my-acme-dns
+spec:
+ acme:
+ solvers:
+ - dns01:
+ acmeDNS:
+ accountSecretRef:
+ name: auth-example-com
+ key: acmedns.json
+ host: auth.example.com
+```
+
+and imagine that you want to create a Certificate with three subdomains:
+
+```yaml
+kind: Certificate
+spec:
+ issuerRef:
+ name: issuer-1
+ dnsNames:
+ - "example.com"
+ - "*.example.com"
+ - "foo.example.com"
+```
+
+cert-manager will only be able to solve 2 challenges out of 3 in a non
+deterministic way. This limitation comes from a "feature" mentioned [this
+acme-dns issue](https://github.com/joohoi/acme-dns/issues/76).
+
+One workaround is to issue one set of acme-dns credentials for each
+domain that we want to be challenged, keeping in mind that each acme-dns
+"subdomain" can only accept at most 2 challenged domains. For example, the
+above secret would become:
+
+```yaml
+kind: Secret
+metadata:
+ name: auth-example-com
+stringData:
+ acmedns.json: |
+ {
+ "example.com": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ },
+ "foo.example.com": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ }
+```
+
+With this setup, we have:
+
+- `example.com` and `*.example.com` are registered in the acme-dns
+ "subdomain" `d420c923-bbd7-4056-ab64-c3ca54c9b3cf`.
+- `foo.example.com` is registered in the acme-dns "subdomain"
+ `d420c923-bbd7-4056-ab64-c3ca54c9b3cf`.
+
+Another workaround is to use `--max-concurrent-challenges 2` when running
+the `cert-manager-controller`. With this setting, acme-dns will only have 2
+TXT records in its database at any time, which mitigates the issue.
\ No newline at end of file
diff --git a/content/v1.12-docs/configuration/acme/dns01/akamai.md b/content/v1.12-docs/configuration/acme/dns01/akamai.md
new file mode 100644
index 0000000000..271f7fd620
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/akamai.md
@@ -0,0 +1,86 @@
+---
+title: Akamai
+description: 'cert-manager configuration: ACME DNS-01 challenges using Akamai DNS'
+---
+
+## Edge DNS
+
+Use Edge DNS to solve DNS01 ACME challenges by creating a `Secret` using [Akamai API credentials](https://developer.akamai.com/getting-started/edgegrid) and an `Issuer` that references the `Secret` and sets the solver type.
+
+### Create a Secret
+
+The `Secret` should look like the following for the `Issuer` to reference. Replace `use_akamai_client_secret`, `use_akamai_access_token` and `use_akamai_client_token` with the respective Akamai API credential values.
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: akamai-secret
+type: Opaque
+stringData:
+ clientSecret: use_akamai_client_secret
+ accessToken: use_akamai_access_token
+ clientToken: use_akamai_client_token
+```
+
+### Create an Issuer
+
+To set Edge DNS for challenge tokens, `cert-manager` uses an `Issuer` that references the above `Secret` and other attributes such as the solver type. The `Issuer` should look like the following. Replace `use_akamai_host` with the Akamai API credential `host` value.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-akamai-dns
+spec:
+ acme:
+ server: https://acme-v02.api.letsencrypt.org/directory
+ email: contact@me.com
+ privateKeySecretRef:
+ name: letsencrypt-akamai-issuer-account-key
+ solvers:
+ - dns01:
+ akamai:
+ serviceConsumerDomain: use_akamai_host
+ clientTokenSecretRef:
+ name: akamai-secret
+ key: clientToken
+ clientSecretSecretRef:
+ name: akamai-secret
+ key: clientSecret
+ accessTokenSecretRef:
+ name: akamai-secret
+ key: accessToken
+```
+
+### Create a Certificate
+
+The `Certificate` should look like the following and reference the Akamai Edge DNS `Issuer` above.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-zone
+spec:
+ secretName: akamai-crt-secret
+ dnsNames:
+ - '*.example.zone'
+ issuerRef:
+ name: letsencrypt-akamai-dns
+ kind: Issuer
+```
+
+> Note: `cert-manager` will wait for challenge tokens to propagate across the Edge DNS network. Follow the `certificate` status with a command such as the following.
+
+```bash
+kubectl describe certificate example-zone
+```
+
+### Troubleshooting
+
+Follow the `cert-manager` events to identify any issues with a command such as the following.
+
+```bash
+cmctl status certificate example-zone
+```
\ No newline at end of file
diff --git a/content/v1.12-docs/configuration/acme/dns01/azuredns.md b/content/v1.12-docs/configuration/acme/dns01/azuredns.md
new file mode 100644
index 0000000000..bc5de32fec
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/azuredns.md
@@ -0,0 +1,505 @@
+---
+title: AzureDNS
+description: 'cert-manager configuration: ACME DNS-01 challenges using AzureDNS'
+---
+
+cert-manager can create and then delete DNS-01 records in Azure DNS but it needs to authenticate to Azure first.
+There are four authentication methods available:
+
+- [Managed Identity Using AAD Workload Identity](#managed-identity-using-aad-pod-identity) (recommended)
+- [Managed Identity Using AAD Pod Identities](#managed-identity-using-aad-pod-identities) (deprecated)
+- [Managed Identity Using AKS Kubelet Identity](#managed-identity-using-aks-kubelet-identity)
+- [Service Principal](#service-principal)
+
+## Managed Identity Using AAD Workload Identity
+
+> ℹ️ This feature is available in cert-manager `>= v1.11.0`.
+>
+> 📖 Read the [AKS + LoadBalancer + Let's Encrypt tutorial](../../../tutorials/getting-started-aks-letsencrypt/README.md) for an end-to-end example of this authentication method.
+
+Azure AD workload identity (preview) on Azure Kubernetes Service (AKS) allows cert-manager to authenticate to Azure using a Kubernetes ServiceAccount Token and then to manage DNS-01 records in Azure DNS.
+This is the recommended authentication method because it is more secure and easier to maintain than the other methods.
+
+### Reconfigure the cluster
+
+Enable the workload identity federation features on your cluster.
+If you have an Azure AKS cluster you can use the following command:
+
+```bash
+az aks update \
+ --name ${CLUSTER} \
+ --enable-oidc-issuer \
+ --enable-workload-identity # ℹ️ This option is currently only available when using the aks-preview extension.
+```
+
+> ℹ️ You can [install the Azure workload identity extension on other managed and self-managed clusters](https://azure.github.io/azure-workload-identity/docs/installation.html) if you are not using Azure AKS.
+>
+> 📖 Read [Deploy and configure workload identity on an Azure Kubernetes Service (AKS) cluster](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster) for more information about the `--enable-workload-identity` feature.
+>
+### Reconfigure cert-manager
+
+Label the cert-manager controller Pod and ServiceAccount for the attention of the Azure Workload Identity webhook,
+which will result in the cert-manager controller Pod having an extra volume containing a Kubernetes ServiceAccount token which it will use to authenticate with Azure.
+
+If you installed cert-manager using Helm, the labels can be configured using Helm values:
+
+```yaml
+# values.yaml
+podLabels:
+ azure.workload.identity/use: "true"
+serviceAccount:
+ labels:
+ azure.workload.identity/use: "true"
+```
+
+If successful, the cert-manager Pod will have some new environment variables set,
+and the Azure workload-identity ServiceAccount token as a projected volume:
+
+```bash
+kubectl describe pod -n cert-manager -l app.kubernetes.io/component=controller
+```
+
+```terminal
+Containers:
+ ...
+ cert-manager-controller:
+ ...
+ Environment:
+ ...
+ AZURE_CLIENT_ID:
+ AZURE_TENANT_ID: f99bd6a4-665c-41cf-aff1-87a89d5c62d4
+ AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/azure/tokens/azure-identity-token
+ AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/
+ Mounts:
+ /var/run/secrets/azure/tokens from azure-identity-token (ro)
+Volumes:
+ ...
+ azure-identity-token:
+ Type: Projected (a volume that contains injected data from multiple sources)
+ TokenExpirationSeconds: 3600
+```
+
+> 📖 Read about [the role of the Mutating Admission Webhook](https://azure.github.io/azure-workload-identity/docs/installation/mutating-admission-webhook.html) in Azure AD Workload Identity for Kubernetes.
+
+
+### Create a Managed Identity
+
+In order for cert-manager to use the Azure API and manipulate the records in the Azure DNS zone,
+it needs an Azure account and the best type of account to use is called a "Managed Identity".
+This account does not come with a password or an API key and it is designed for use by machines rather than humans.
+
+Choose a managed identity name and create the Managed Identity:
+
+```bash
+export IDENTITY_NAME=cert-manager
+az identity create --name "${IDENTITY_NAME}"
+```
+
+Grant it permission to modify the DNS zone records:
+
+```bash
+export IDENTITY_CLIENT_ID=$(az identity show --name "${IDENTITY_NAME}" --query 'clientId' -o tsv)
+az role assignment create \
+ --role "DNS Zone Contributor" \
+ --assignee IDENTITY_CLIENT_ID \
+ --scope $(az network dns zone show --name $DOMAIN_NAME -o tsv --query id)
+```
+
+> 📖 Read [What are managed identities for Azure resources?](https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview)
+> for an overview of managed identities and their uses.
+>
+> 📖 Read [Azure built-in roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles) to learn about the "DNS Zone Contributor" role.
+>
+> 📖 Read more about [the `az identity` command](https://learn.microsoft.com/en-us/cli/azure/identity).
+
+### Add a Federated Identity
+
+Now associate a federated identity with the managed identity that you created earlier.
+cert-manager will authenticate to Azure using a short lived Kubernetes ServiceAccount token,
+and it will be able to impersonate the managed identity that you created in the previous step.
+
+```bash
+export SERVICE_ACCOUNT_NAME=cert-manager # ℹ️ This is the default Kubernetes ServiceAccount used by the cert-manager controller.
+export SERVICE_ACCOUNT_NAMESPACE=cert-manager # ℹ️ This is the default namespace for cert-manager.
+export SERVICE_ACCOUNT_ISSUER=$(az aks show --resource-group $AZURE_DEFAULTS_GROUP --name $CLUSTER --query "oidcIssuerProfile.issuerUrl" -o tsv)
+az identity federated-credential create \
+ --name "cert-manager" \
+ --identity-name "${IDENTITY_NAME}" \
+ --issuer "${SERVICE_ACCOUNT_ISSUER}" \
+ --subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}"
+```
+
+- `--subject`: is the distinguishing name of the Kubernetes ServiceAccount.
+- `--issuer`: is a URL from which the Azure will download the JWT signing certificate and other metadata
+
+> 📖 Read about [Workload identity federation](https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation) in the Microsoft identity platform documentation.
+>
+> 📖 Read more about [the `az identity federated-credential` command](https://learn.microsoft.com/en-us/cli/azure/identity/federated-credential).
+
+### Configure a ClusterIssuer
+
+For example:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ email: $EMAIL_ADDRESS
+ privateKeySecretRef:
+ name: letsencrypt-staging
+ solvers:
+ - dns01:
+ azureDNS:
+ hostedZoneName: $AZURE_ZONE_NAME
+ resourceGroupName: $AZURE_RESOURCE_GROUP
+ subscriptionID: $AZURE_SUBSCRIPTION_ID
+ environment: AzurePublicCloud
+ managedIdentity:
+ clientID: $IDENTITY_CLIENT_ID
+```
+
+The following variables need to be filled in.
+
+```bash
+# An email address to which Let's Encrypt will send renewal reminders.
+export EMAIL_ADDRESS=
+# The Azure DNS zone in which the DNS-01 records will be created and deleted.
+export AZURE_ZONE_NAME=
+# The Azure resource group containing the DNS zone.
+export AZURE_RESOURCE_GROUP=
+# The Azure billing account name and ID for the DNS zone.
+export AZURE_SUBSCRIPTION=
+export AZURE_SUBSCRIPTION_ID=$(az account show --name $AZURE_SUBSCRIPTION --query 'id' -o tsv)
+```
+
+#### ⚠️ Using 'Ambient Credentials' with ClusterIssuer and Issuer resources
+
+This authentication method is an example of what cert-manager calls 'ambient credentials'.
+Ambient credentials are enabled by default for ClusterIssuer resources, but disabled by default for Issuer resources.
+This is to prevent unprivileged users, who have permission to create Issuer resources, from issuing certificates using credentials that cert-manager incidentally has access to.
+ClusterIssuer resources are cluster scoped (not namespaced) and only platform administrators should be granted permission to create them.
+
+If you are using this authentication mechanism and ambient credentials are not enabled, you will see this error:
+
+```bash
+error instantiating azuredns challenge solver: ClientID is not set but neither --cluster-issuer-ambient-credentials nor --issuer-ambient-credentials are set.
+```
+
+> ⚠️ It is possible (but not recommended) to enable this authentication mechanism for `Issuer` resources, by setting the `--issuer-ambient-credentials` flag on the cert-manager controller to true.
+
+## Managed Identity Using AAD Pod Identities
+
+> ⚠️ The [open source Azure AD pod-managed identity (preview) in Azure Kubernetes Service has been deprecated as of 10/24/2022](https://github.com/Azure/aad-pod-identity#-announcement).
+> Use Workload Identity instead.
+
+[AAD Pod Identities](https://azure.github.io/aad-pod-identity) allows assigning a [Managed Identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) to a pod. This removes the need for adding explicit credentials into the cluster to create the required DNS records.
+
+> Note: When using Pod identity, even though assigning multiple identities to a single pod is allowed, currently cert-manager does not support this as it is not able to identify which identity to use.
+
+Firstly an identity should be created that has access to contribute to the DNS Zone.
+
+- Example creation using `azure-cli` and `jq`:
+
+```bash
+# Choose a unique Identity name and existing resource group to create identity in.
+IDENTITY=$(az identity create --name $IDENTITY_NAME --resource-group $IDENTITY_GROUP --output json)
+
+# Gets principalId to use for role assignment
+PRINCIPAL_ID=$(echo $IDENTITY | jq -r '.principalId')
+
+# Used for identity binding
+CLIENT_ID=$(echo $IDENTITY | jq -r '.clientId')
+RESOURCE_ID=$(echo $IDENTITY | jq -r '.id')
+
+# Get existing DNS Zone Id
+ZONE_ID=$(az network dns zone show --name $ZONE_NAME --resource-group $ZONE_GROUP --query "id" -o tsv)
+
+# Create role assignment
+az role assignment create --role "DNS Zone Contributor" --assignee $PRINCIPAL_ID --scope $ZONE_ID
+```
+
+- Example creation using Terraform
+
+```terraform
+variable resource_group_name {}
+variable location {}
+variable dns_zone_id {}
+
+# Creates Identity
+resource "azurerm_user_assigned_identity" "dns_identity" {
+ name = "cert-manager-dns01"
+ resource_group_name = var.resource_group_name
+ location = var.location
+}
+
+# Creates Role Assignment
+resource "azurerm_role_assignment" "dns_contributor" {
+ scope = var.dns_zone_id
+ role_definition_name = "DNS Zone Contributor"
+ principal_id = azurerm_user_assigned_identity.dns_identity.principal_id
+}
+
+# Client Id Used for identity binding
+output "identity_client_id" {
+ value = azurerm_user_assigned_identity.dns_identity.client_id
+}
+
+# Resource Id Used for identity binding
+output "identity_resource_id" {
+ value = azurerm_user_assigned_identity.dns_identity.id
+}
+```
+
+Next we need to ensure we have installed [AAD Pod Identity](https://azure.github.io/aad-pod-identity) using their walk-through. This will install the CRDs and deployment required to assign the identity.
+
+Now we can create the identity resource and binding using the below manifest as an example:
+
+```yaml
+apiVersion: "aadpodidentity.k8s.io/v1"
+kind: AzureIdentity
+metadata:
+ annotations:
+ # recommended to use namespaced identites https://azure.github.io/aad-pod-identity/docs/configure/match_pods_in_namespace/
+ aadpodidentity.k8s.io/Behavior: namespaced
+ name: certman-identity
+ namespace: cert-manager # change to your preferred namespace
+spec:
+ type: 0 # MSI
+ resourceID: # Resource Id From Previous step
+ clientID: # Client Id from previous step
+---
+apiVersion: "aadpodidentity.k8s.io/v1"
+kind: AzureIdentityBinding
+metadata:
+ name: certman-id-binding
+ namespace: cert-manager # change to your preferred namespace
+spec:
+ azureIdentity: certman-identity
+ selector: certman-label # This is the label that needs to be set on cert-manager pods
+```
+
+Next we need to ensure the cert-manager pod has a relevant label to use the pod identity binding. This can be done by editing the deployment and adding the below into the `.spec.template.metadata.labels` field
+
+```yaml
+spec:
+ template:
+ metadata:
+ labels:
+ aadpodidbinding: certman-label # must match selector in AzureIdentityBinding
+```
+
+Or by using the helm values `podLabels`
+
+```yaml
+podLabels:
+ aadpodidbinding: certman-label
+```
+
+Lastly when we create the certificate issuer we only need to specify the `hostedZoneName`, `resourceGroupName` and `subscriptionID` fields for the DNS zone. Example below:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ azureDNS:
+ subscriptionID: AZURE_SUBSCRIPTION_ID
+ resourceGroupName: AZURE_DNS_ZONE_RESOURCE_GROUP
+ hostedZoneName: AZURE_DNS_ZONE
+ # Azure Cloud Environment, default to AzurePublicCloud
+ environment: AzurePublicCloud
+```
+
+This authentication mechanism is what cert-manager considers 'ambient credentials'. Use of ambient credentials is disabled by default for cert-manager `Issuer`s. This to ensure unprivileged users who have permission to create issuers cannot issue certificates using any credentials cert-manager incidentally has access to. To enable this authentication mechanism for `Issuer`s, you will need to set `--issuer-ambient-credentials` flag on cert-manager controller to true. (There is a corresponding `--cluster-issuer-ambient-credentials` flag which is set to `true` by default).
+
+If you are using this authentication mechanism and ambient credentials are not enabled, you will see this error:
+```bash
+error instantiating azuredns challenge solver: ClientID is not set but neither --cluster-issuer-ambient-credentials nor --issuer-ambient-credentials are set.
+```
+
+These are necessary to enable Azure Managed Identities.
+
+## Managed Identity Using AKS Kubelet Identity
+
+When creating an AKS cluster in Azure there is the option to use a managed identity that is assigned to the kubelet. This identity is assigned to the underlying node pool in the AKS cluster and can then be used by the cert-manager pods to authenticate to Azure Active Directory.
+
+There are some caveats with this approach, these mainly being:
+
+- Any permissions granted to this identity will also be accessible to all containers running inside the Kubernetes cluster.
+- Using AKS extensions like `Kube Dashboard`, `Virtual Node`, or `HTTP Application Routing` (see full list [here](https://docs.microsoft.com/en-us/azure/aks/use-managed-identity#summary-of-managed-identities)) will create additional identities that are assigned to your node pools. If your node pools have more than one identity assigned, you will need to specify either `clientID` or `resourceID` to select the correct one.
+
+To set this up, firstly you will need to retrieve the identity that the kubelet is using by querying the AKS cluster. This can then be used to create the appropriate permissions in the DNS zone.
+
+- Example commands using `azure-cli`:
+
+```bash
+# Get AKS Kubelet Identity
+PRINCIPAL_ID=$(az aks show -n $CLUSTERNAME -g $CLUSTER_GROUP --query "identityProfile.kubeletidentity.objectId" -o tsv)
+
+# Get existing DNS Zone Id
+ZONE_ID=$(az network dns zone show --name $ZONE_NAME --resource-group $ZONE_GROUP --query "id" -o tsv)
+
+# Create role assignment
+az role assignment create --role "DNS Zone Contributor" --assignee $PRINCIPAL_ID --scope $ZONE_ID
+```
+
+- Example terraform:
+
+```terraform
+variable dns_zone_id {}
+
+# Creating the AKS cluster, abbreviated.
+resource "azurerm_kubernetes_cluster" "cluster" {
+ ...
+ # Creates Identity associated to kubelet
+ identity {
+ type = "SystemAssigned"
+ }
+ ...
+}
+
+resource "azurerm_role_assignment" "dns_contributor" {
+ scope = var.dns_zone_id
+ role_definition_name = "DNS Zone Contributor"
+ principal_id = azurerm_kubernetes_cluster.cluster.kubelet_identity[0].object_id
+ skip_service_principal_aad_check = true # Allows skipping propagation of identity to ensure assignment succeeds.
+}
+```
+
+Then when creating the cert-manager issuer we need to specify the `hostedZoneName`, `resourceGroupName` and `subscriptionID` fields for the DNS Zone.
+
+We also need to specify `managedIdentity.clientID` or `managedIdentity.resourceID` if multiple managed identities are assigned to the node pools.
+
+The value for `managedIdentity.clientID` can be fetched by running this command:
+
+```bash
+az aks show -n $CLUSTERNAME -g $CLUSTER_GROUP --query "identityProfile.kubeletidentity.clientId" -o tsv
+```
+
+Example below:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ azureDNS:
+ subscriptionID: AZURE_SUBSCRIPTION_ID
+ resourceGroupName: AZURE_DNS_ZONE_RESOURCE_GROUP
+ hostedZoneName: AZURE_DNS_ZONE
+ # Azure Cloud Environment, default to AzurePublicCloud
+ environment: AzurePublicCloud
+ # optional, only required if node pools have more than 1 managed identity assigned
+ managedIdentity:
+ # client id of the node pool managed identity (can not be set at the same time as resourceID)
+ clientID: YOUR_MANAGED_IDENTITY_CLIENT_ID
+ # resource id of the managed identity (can not be set at the same time as clientID)
+ # resourceID: YOUR_MANAGED_IDENTITY_RESOURCE_ID
+```
+
+## Service Principal
+
+Configuring the AzureDNS DNS01 Challenge for a Kubernetes cluster requires
+creating a service principal in Azure.
+
+To create the service principal you can use the following script (requires
+`azure-cli` and `jq`):
+
+```bash
+# Choose a name for the service principal that contacts azure DNS to present
+# the challenge.
+$ AZURE_CERT_MANAGER_NEW_SP_NAME=NEW_SERVICE_PRINCIPAL_NAME
+# This is the name of the resource group that you have your dns zone in.
+$ AZURE_DNS_ZONE_RESOURCE_GROUP=AZURE_DNS_ZONE_RESOURCE_GROUP
+# The DNS zone name. It should be something like domain.com or sub.domain.com.
+$ AZURE_DNS_ZONE=AZURE_DNS_ZONE
+
+$ DNS_SP=$(az ad sp create-for-rbac --name $AZURE_CERT_MANAGER_NEW_SP_NAME --output json)
+$ AZURE_CERT_MANAGER_SP_APP_ID=$(echo $DNS_SP | jq -r '.appId')
+$ AZURE_CERT_MANAGER_SP_PASSWORD=$(echo $DNS_SP | jq -r '.password')
+$ AZURE_TENANT_ID=$(echo $DNS_SP | jq -r '.tenant')
+$ AZURE_SUBSCRIPTION_ID=$(az account show --output json | jq -r '.id')
+```
+
+For security purposes, it is appropriate to utilize RBAC to ensure that you
+properly maintain access control to your resources in Azure. The service
+principal that is generated by this tutorial has fine-grained access to ONLY the
+DNS Zone in the specific resource group specified. It requires this permission
+so that it can read/write the \_acme\_challenge TXT records to the zone.
+
+Lower the Permissions of the service principal.
+
+```bash
+$ az role assignment delete --assignee $AZURE_CERT_MANAGER_SP_APP_ID --role Contributor
+```
+
+Give Access to DNS Zone.
+
+```bash
+$ DNS_ID=$(az network dns zone show --name $AZURE_DNS_ZONE --resource-group $AZURE_DNS_ZONE_RESOURCE_GROUP --query "id" --output tsv)
+$ az role assignment create --assignee $AZURE_CERT_MANAGER_SP_APP_ID --role "DNS Zone Contributor" --scope $DNS_ID
+```
+
+Check Permissions. As the result of the following command, we would like to see just one object in the permissions array with "DNS Zone Contributor" role.
+
+```bash
+$ az role assignment list --all --assignee $AZURE_CERT_MANAGER_SP_APP_ID
+```
+
+A secret containing service principal password should be created on Kubernetes to facilitate presenting the challenge to Azure DNS. You can create the secret with the following command:
+
+```bash
+$ kubectl create secret generic azuredns-config --from-literal=client-secret=$AZURE_CERT_MANAGER_SP_PASSWORD
+```
+
+Get the variables for configuring the issuer.
+
+```bash
+$ echo "AZURE_CERT_MANAGER_SP_APP_ID: $AZURE_CERT_MANAGER_SP_APP_ID"
+$ echo "AZURE_CERT_MANAGER_SP_PASSWORD: $AZURE_CERT_MANAGER_SP_PASSWORD"
+$ echo "AZURE_SUBSCRIPTION_ID: $AZURE_SUBSCRIPTION_ID"
+$ echo "AZURE_TENANT_ID: $AZURE_TENANT_ID"
+$ echo "AZURE_DNS_ZONE: $AZURE_DNS_ZONE"
+$ echo "AZURE_DNS_ZONE_RESOURCE_GROUP: $AZURE_DNS_ZONE_RESOURCE_GROUP"
+```
+
+To configure the issuer, substitute the capital cased variables with the values
+from the previous script. You can get the subscription id from the Azure portal.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ azureDNS:
+ clientID: AZURE_CERT_MANAGER_SP_APP_ID
+ clientSecretSecretRef:
+ # The following is the secret we created in Kubernetes. Issuer will use this to present challenge to Azure DNS.
+ name: azuredns-config
+ key: client-secret
+ subscriptionID: AZURE_SUBSCRIPTION_ID
+ tenantID: AZURE_TENANT_ID
+ resourceGroupName: AZURE_DNS_ZONE_RESOURCE_GROUP
+ hostedZoneName: AZURE_DNS_ZONE
+ # Azure Cloud Environment, default to AzurePublicCloud
+ environment: AzurePublicCloud
+```
diff --git a/content/v1.12-docs/configuration/acme/dns01/cloudflare.md b/content/v1.12-docs/configuration/acme/dns01/cloudflare.md
new file mode 100644
index 0000000000..b3f4ded449
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/cloudflare.md
@@ -0,0 +1,108 @@
+---
+title: Cloudflare
+description: 'cert-manager configuration: ACME DNS-01 challenges using Cloudflare DNS'
+---
+
+To use Cloudflare, you may use one of two types of tokens. **API Tokens** allow application-scoped keys bound to specific zones and permissions, while **API Keys** are globally-scoped keys that carry the same permissions as your account.
+
+**API Tokens** are recommended for higher security, since they have more restrictive permissions and are more easily revocable.
+
+## API Tokens
+
+Tokens can be created at **User Profile > API Tokens > API Tokens**. The following settings are recommended:
+
+- Permissions:
+ - `Zone - DNS - Edit`
+ - `Zone - Zone - Read`
+- Zone Resources:
+ - `Include - All Zones`
+
+To create a new `Issuer`, first make a Kubernetes secret containing your new API token:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: cloudflare-api-token-secret
+type: Opaque
+stringData:
+ api-token:
+```
+
+Then in your `Issuer` manifest:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ apiTokenSecretRef:
+ name: cloudflare-api-token-secret
+ key: api-token
+```
+
+## API Keys
+
+API keys can be retrieved at **User Profile > API Tokens > API Keys > Global API Key > View**.
+
+To create a new `Issuer`, first make a Kubernetes secret containing your API key:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: cloudflare-api-key-secret
+type: Opaque
+stringData:
+ api-key:
+```
+
+Then in your `Issuer` manifest:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ email: my-cloudflare-acc@example.com
+ apiKeySecretRef:
+ name: cloudflare-api-key-secret
+ key: api-key
+```
+
+## Troubleshooting
+
+### Actor `com.cloudflare.api.token.xxxx` requires permission `com.cloudflare.api.account.zone.list` to list zones
+If you get the error that your token does not have the correct permission to list zones there can be 2 causes.
+1. The token lacks the `Zone - Zone - Read` permission
+2. cert-manager identified the wrong zone name for the domain due to DNS issues.
+
+In the case of the 2nd issue you will see an error like below:
+```
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Started 6s cert-manager Challenge scheduled for processing
+ Warning PresentError 3s (x2 over 3s) cert-manager Error presenting challenge: Cloudflare API Error for GET "/zones?name="
+ Error: 0: Actor 'com.cloudflare.api.token.xxxx' requires permission 'com.cloudflare.api.account.zone.list' to list zones
+```
+
+In this case we recommend [changing your DNS01 self-check nameservers](./README.md#setting-nameservers-for-dns01-self-check).
+
+## `Cloudflare API error for POST "/zones//dns_records` generic error
+
+You might be hitting this as Cloudflare blocks the use of the API to update DNS records for the following TLDs: `.cf`, `.ga`, `.gq`, `.ml` and `.tk`.
+This is discussed in the [Cloudflare Community](https://community.cloudflare.com/t/unable-to-update-ddns-using-api-for-some-tlds/167228).
+We recommend using an alternative DNS provider when using these TLDs.
\ No newline at end of file
diff --git a/content/v1.12-docs/configuration/acme/dns01/digitalocean.md b/content/v1.12-docs/configuration/acme/dns01/digitalocean.md
new file mode 100644
index 0000000000..4d6c155863
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/digitalocean.md
@@ -0,0 +1,46 @@
+---
+title: DigitalOcean
+description: 'cert-manager configuration: ACME DNS-01 challenges using DigitalOcean DNS'
+---
+
+This provider uses a Kubernetes `Secret` resource to work. In the following
+example, the `Secret` will have to be named `digitalocean-dns` and have a
+sub-key `access-token` with the token in it. For example:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: digitalocean-dns
+data:
+ # insert your DO access token here
+ access-token: "base64 encoded access-token here"
+ ```
+
+The access token must have write access.
+
+To create a Personal Access Token, see [DigitalOcean documentation](https://docs.digitalocean.com/reference/api/create-personal-access-token/).
+
+Handy direct link: https://cloud.digitalocean.com/account/api/tokens/new
+
+To encode your access token into base64, you can use the following
+
+```bash
+echo -n 'your-access-token' | base64
+```
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ digitalocean:
+ tokenSecretRef:
+ name: digitalocean-dns
+ key: access-token
+```
\ No newline at end of file
diff --git a/content/v1.12-docs/configuration/acme/dns01/google.md b/content/v1.12-docs/configuration/acme/dns01/google.md
new file mode 100644
index 0000000000..460239de80
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/google.md
@@ -0,0 +1,242 @@
+---
+title: Google CloudDNS
+description: 'cert-manager configuration: ACME DNS-01 challenges using Google CloudDNS'
+---
+
+This guide explains how to set up an `Issuer`, or `ClusterIssuer`, to use Google
+CloudDNS to solve DNS01 ACME challenges. It's advised you read the [DNS01
+Challenge Provider](./README.md) page first for a more general understanding of
+how cert-manager handles DNS01 challenges.
+
+This guide assumes that your cluster is hosted on Google Cloud Platform (GCP)
+and that you already have a domain set up with CloudDNS.
+
+You'll need to be using a **Public DNS Zone**, so that the ACME challenge checker
+is able to access the DNS records that cert-manager will create.
+
+## Set up a Service Account
+
+cert-manager needs to be able to add records to CloudDNS in order to solve the
+DNS01 challenge. To enable this, a GCP service account must be created with the
+`dns.admin` role.
+
+> Note: For this guide the `gcloud` command will be used to set up the service
+> account. Ensure that `gcloud` is using the correct project and zone before
+> entering the commands. These steps could also be completed using the Cloud
+> Console.
+
+```bash
+PROJECT_ID=myproject-id
+gcloud iam service-accounts create dns01-solver --display-name "dns01-solver"
+```
+
+In the command above, replace `myproject-id` with the ID of your project.
+
+```bash
+gcloud projects add-iam-policy-binding $PROJECT_ID \
+ --member serviceAccount:dns01-solver@$PROJECT_ID.iam.gserviceaccount.com \
+ --role roles/dns.admin
+```
+
+> **Note**: The use of the `dns.admin` role in this example role is for convenience.
+> If you want to ensure cert-manager runs under a least privilege service account,
+> you will need to create a custom role with the following permissions:
+>
+> * `dns.resourceRecordSets.*`
+> * `dns.changes.*`
+> * `dns.managedZones.list`
+
+## Use Static Credentials
+
+Follow the instructions in the following sections to deploy cert-manager using
+static credentials for the service account you created. You should rotate these
+credentials periodically.
+
+### Create a Service Account Secret
+
+To access this service account, cert-manager uses a key stored in a Kubernetes
+`Secret`. First, create a key for the service account and download it as a JSON
+file, then create a `Secret` from this file.
+
+Keep the key file safe and do not share it, as it could be used to gain access
+access to your cloud resources. The key file can be deleted once it has been
+used to generate the `Secret`.
+
+If you did not create the service account `dns01-solver` before, you need to
+create it first.
+
+```bash
+gcloud iam service-accounts create dns01-solver
+```
+
+Replace instances of `$PROJECT_ID` with the ID of your project.
+```bash
+gcloud iam service-accounts keys create key.json \
+ --iam-account dns01-solver@$PROJECT_ID.iam.gserviceaccount.com
+kubectl create secret generic clouddns-dns01-solver-svc-acct \
+ --from-file=key.json
+```
+
+> Note: If you have already added the `Secret` but get an error: `...due to
+> error processing: error getting clouddns service account: secret "XXX" not
+> found`, the `Secret` may be in the wrong namespace. If you're configuring a
+> `ClusterIssuer`, move the `Secret` to the `Cluster Resource Namespace` which
+> is `cert-manager` by default. If you're configuring an `Issuer`, the `Secret`
+> should be stored in the same namespace as the `Issuer` resource.
+
+### Create an Issuer That Uses CloudDNS
+
+Next, create an `Issuer` (or `ClusterIssuer`) with a `cloudDNS` provider. An
+example `Issuer` manifest can be seen below with annotations.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudDNS:
+ # The ID of the GCP project
+ project: $PROJECT_ID
+ # This is the secret used to access the service account
+ serviceAccountSecretRef:
+ name: clouddns-dns01-solver-svc-acct
+ key: key.json
+```
+
+For more information about `Issuers` and `ClusterIssuers`, see
+[Configuration](../../README.md).
+
+Once an `Issuer` (or `ClusterIssuer`) has been created successfully, a
+`Certificate` can then be added to verify that everything works.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com
+ namespace: default
+spec:
+ secretName: example-com-tls
+ issuerRef:
+ # The issuer created previously
+ name: example-issuer
+ dnsNames:
+ - example.com
+ - www.example.com
+```
+
+For more details about `Certificates`, see [Usage](../../../usage/README.md).
+
+## GKE Workload Identity
+
+If you are deploying cert-manager into a [Google Container Engine (GKE)
+cluster](https://cloud.google.com/kubernetes-engine/) with workload identity
+enabled, you can leverage workload identity to avoid creating and managing
+static service account credentials. The [workload identity
+how-to](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
+provides more detail on how workload identity functions, but briefly workload
+identity allows you to link a Google service accounts (GSA) to Kubernetes
+service accounts (KSA). This GSA/KSA linking is two-way, i.e., you must
+establish the link in GCP _and_ Kubernetes. Once configured, workload identity
+allows Kubernetes pods running under a KSA to access the GCP APIs with the
+permissions of the linked GSA. The workload identity how-to also provides
+detailed instructions on how to enable workload identity in your GKE cluster.
+The instructions in the following sections assume you are deploying cert-manager
+to a GKE cluster with workload identity already enabled.
+
+### Enable Ambient Credential Usage
+
+'Ambient Credentials' are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the ClusterIssuer API object. When this flag is enabled Cert-Manager will access the GKE Metadata server for credentials. By default this is enabled for ClusterIssuer resources but is disabled for Issuer resources. To enable it for Issuer resources set the `--issuer-ambient-credentials` flag.
+
+### Link KSA to GSA in GCP
+
+The cert-manager component that needs to modify DNS records is the pod created
+as part of the cert-manager deployment. The [standard methods for deploying
+cert-manager to Kubernetes](../../../installation/README.md) create the
+cert-manager deployment in the cert-manager namespace and its pod spec specifies
+it runs under the cert-manager service account. To link the GSA you created
+above to the cert-manager KSA in the cert-manager namespace in your GKE cluster,
+run the following command.
+
+```bash
+gcloud iam service-accounts add-iam-policy-binding \
+ --role roles/iam.workloadIdentityUser \
+ --member "serviceAccount:$PROJECT_ID.svc.id.goog[cert-manager/cert-manager]" \
+ dns01-solver@$PROJECT_ID.iam.gserviceaccount.com
+```
+
+If your cert-manager pods are running under a different service account, replace
+`goog[cert-manager/cert-manager]` with `goog[NAMESPACE/SERVICE_ACCOUNT]`, where
+`NAMESPACE` is the namespace of the service account and `SERVICE_ACCOUNT` is the
+name of the service account.
+
+### Link KSA to GSA in Kubernetes
+
+After deploying cert-manager, add the proper workload identity annotation to the
+cert-manager service account.
+
+```bash
+kubectl annotate serviceaccount --namespace=cert-manager cert-manager \
+ "iam.gke.io/gcp-service-account=dns01-solver@$PROJECT_ID.iam.gserviceaccount.com"
+```
+
+Again, if your cert-manager pods are running under a different service account,
+replace `--namespace=cert-manager cert-manager` with `--namespace=NAMESPACE
+SERVICE_ACCOUNT`, where `NAMESPACE` is the namespace of the service account and
+`SERVICE_ACCOUNT` is the name of the service account.
+
+If you are deploying cert-manager using its helm chart, you can use the
+`serviceAccount.annotations` configuration parameter to add the above workload
+identity annotation to the cert-manager KSA.
+
+### Create an Issuer That Uses CloudDNS
+
+Next, create an `Issuer` (or `ClusterIssuer`) with a `clouddns` provider. An
+example `Issuer` manifest can be seen below with annotations. Note that the
+issuer does not include a `serviceAccountSecretRef` property. Excluding this
+instructs cert-manager to use the default credentials provided by GKE workload
+identity.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudDNS:
+ # The ID of the GCP project
+ project: $PROJECT_ID
+```
+
+For more information about `Issuers` and `ClusterIssuers`, see
+[Configuration](../../README.md).
+
+Once an `Issuer` (or `ClusterIssuer`) has been created successfully, a
+`Certificate` can then be added to verify that everything works.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com
+ namespace: default
+spec:
+ secretName: example-com-tls
+ issuerRef:
+ # The issuer created previously
+ name: example-issuer
+ dnsNames:
+ - example.com
+ - www.example.com
+```
+
+For more details about `Certificates`, see [Usage](../../../usage/README.md).
diff --git a/content/v1.12-docs/configuration/acme/dns01/rfc2136.md b/content/v1.12-docs/configuration/acme/dns01/rfc2136.md
new file mode 100644
index 0000000000..86e9dd32df
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/rfc2136.md
@@ -0,0 +1,207 @@
+---
+title: RFC-2136
+description: 'cert-manager configuration: ACME DNS-01 challenges using RFC2136-compliant DNS providers'
+---
+
+The goal of this document is to provide a configuration overview of the various
+facilities required to deploy cert-manager against a RFC2136 compliant DNS
+server such as BIND `named`. This capability is also commonly known as “dynamic
+DNS”.
+
+Unlike the peer of other cert-manager DNS integrations, `named` is a bit of a
+“Swiss Army Knife” of domain name servers. Over the years, it has been highly
+optimized to provide maximal vertical scalability for a single node, as well as
+horizontal scalability with service provider interfaces. This flexibility makes
+it impossible to go into every possible `named` deployment that a user may run
+in to though. Instead, this document will try to make sure your server is ready
+to accept requests from cert-manager using command line tools, then get on to
+the making the two work together.
+
+## Transaction Signatures ⇒ TSIG
+
+Dynamic DNS updates are essentially server queries which otherwise might return
+resource records (RRs). Since DNS servers are commonly exposed to the public
+internet, being able to push an unauthenticated update to any server that
+responds to queries would be immediately untenable.
+
+In the eyes of the `named` architects, the generic solution to this problem
+space was twofold. The first is to require manual enablement of updates at a
+zone level, such as `example.com`. In a naive network, there is no requirement
+that zone updates have any security to them, and clients can be configured such
+that they can provide updates without any authentication. An example of where
+this is useful is for machines booting using DHCP, in this case the machines
+know about themselves and the DNS server can be configured to accept updates
+when they come from the address being configured.
+
+This clearly has limitations in situations such as cert-manager and the DNS01
+challenge. In this environment, a TXT RR must be created after coordination with
+the ACME server. After negotiating with the ACME server, a the TXT RR that is
+published on the domain validates that the domain is legitimately engaged with
+the process of creating a certificate for it. In the bigger picture of DNS, this
+means that an arbitrary actor (cert-manager, in this case) must be able to add
+one of these KV mappings to the domain and delete it after the certificate has
+been issued. `cert-manager` does not have a convenient physical characteristic
+such as a DHCP allocation to validate it's requests.
+
+For cases like this, we need to be able to sign a request that is being sent to
+the DNS server. We do that through TSIGs, or Transaction SIGnatures.
+
+### Configuration Step 1 - Set up your DNS server for secure dynamic updates
+
+There are many excellent tutorials on the net that walk through
+preparing a basic `named` server for dynamic updates:
+
+- https://www.cyberciti.biz/faq/unix-linux-bind-named-configuring-tsig/
+- https://tomthorp.me/blog/using-tsig-enable-secure-zone-transfers-between-bind-9x-servers
+
+More complex `name` deployments will not use text files, but rather may use LDAP
+or SQL for a database for resource records. An additional wrinkle is metadata
+configuration, such as for zone metadata like enabling dynamic updates or access
+control lists (ACLs) for a zone. There are too many configurations to go into
+here, but you should be able to find the documentation to do so.
+
+Whatever your deployment is, the goal at this stage has nothing to do with
+cert-manager and everything to do with a tool called `nsupdate` generating
+updates signed with TSIG. Once this is out of the way, you can attack the
+cert-manager configuration with far greater confidence.
+
+#### Using `nsupdate`
+
+Most paths to configuring BIND `named` will go through using `dnssec-keygen`.
+This command-line tool generates a named private key that is used for signing
+TSIG requests. When a request is signed, both the signature and the name of the
+private key are attached to the request in an unencrypted form. In this manner,
+when the request is received, the name of the private key can be used to by the
+recipient to find the private key itself, build a new signature with it, and
+compare the two for acceptance.
+
+Since there are dozens of ways to have your `named` server misconfigured, we’ll
+use `nsupdate` to test that the server behaves as expected before we get there.
+`https://debian-administration.org/article/591/Using_the_dynamic_DNS_editor_nsupdate`
+is a solid breakdown of how to use the tool.
+
+To get started, we’ll simply run `nsupdate -k ` where `keyID` is the value
+returned from `dnssec-keygen`. This will read the key from disk and provide a
+command prompt to issue commands. In general, we want to write a simple TXT RR
+and make sure we can delete it.
+
+```bash
+$ nsupdate -k
+update add www1.example.com 60 txt testing
+send
+… test here with `nslookup`
+update delete www1.example.com txt
+send
+… test here with `nslookup`
+```
+
+Any failures to write, read or delete the record will mean that cert-manager
+will not be able to do so either, no matter how well it is configured.
+
+### Configuration Step 2 - Set up cert-manager
+
+Now we get to the fun stuff, seeing everything work. Remember that we need to
+set up the ACME DNS01 issuer and challenge mechanism as well as the `rfc2136`
+provider. Since the documentation covers the other parts sufficiently, let’s
+focus on the provider here.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ rfc2136:
+ nameserver:
+ tsigKeyName:
+ tsigAlgorithm: HMACSHA512 // should be matched to the algo you chose in `dnssec-keygen`
+ tsigSecretSecretRef:
+ name:
+ key:
+```
+
+For example:
+
+```yaml
+ rfc2136:
+ nameserver: 1.2.3.4:53
+ tsigKeyName: example-com-secret
+ tsigAlgorithm: HMACSHA512
+ tsigSecretSecretRef:
+ name: tsig-secret
+ key: tsig-secret-key
+```
+
+For this example configuration, we’ll need the following two commands. The
+first, on your `named` server generates the key. Note how `example-com-secret`
+is both in the `tsigKeyName` above and the `dnssec-keygen` command that follows.
+
+```bash
+$ dnssec-keygen -r /dev/urandom -a HMAC-SHA512 -b 512 -n HOST example-com-secret
+```
+
+Also note how the `tsigAlgorithm` is provided in both the configuration and the
+`keygen` command. They are listed at
+`https://github.com/miekg/dns/blob/v1.0.12/tsig.go#L18-L23`.
+
+The second bit of configuration you need on the Kubernetes side is to create a
+secret. Pulling the secret key string from the `.private` file generated
+above, use the secret in the placeholder below:
+
+```bash
+$ kubectl -n cert-manager create secret generic tsig-secret --from-literal=tsig-secret-key=
+```
+
+Note how the `tsig-secret` and `tsig-secret-key` match the configuration in the
+`tsigSecretSecretRef` above.
+
+## Rate Limits
+
+The `rfc2136` provider waits until *all* nameservers to in your domain's SOA RR
+respond with the same result before it contacts Let's Encrypt to complete the
+challenge process. This is because the challenge server contacts a
+non-authoritative DNS server that does a recursive query (a query for records it
+does not maintain locally). If the servers in the SOA do not contain the correct
+values, it's likely that the non-authoritative server will have bad information
+as well, causing the request to go against rate limits and eventually locking
+the process out.
+
+This process is in place to protect users from server misconfiguration creating
+a more subtle lockout that persists after the server configuration has been
+repaired.
+
+As documented elsewhere, it is prudent to fully debug configurations using the
+ACME staging servers before using the production servers. The staging servers
+have less aggressive rate limits, but the certificates they issue are not signed
+with a root certificate trusted by browsers.
+
+## What’s next?
+
+This configuration so far will actually do nothing. You still have to request a
+certificate as described [here](../../../usage/README.md). Once a certificate is
+requested, the provider will begin processing the request.
+
+## Troubleshooting
+
+- Be sure that you have fully tested the DNS server updates using `nsupdate`
+ first. Ideally, this is done from a pod in the same namespace as the `rfc2136`
+ provider to ensure there are no firewall issues.
+- The logs for the `cert-manager` pod are your friend. Additional logs can be
+ generated by adding the `--v=5` argument to the container launch.
+- The TSIG key is encoded with `base64`, but the Kubernetes API server also
+ expects that key literals will be decoded before they are stored. In some
+ cases, a key must be double-encoded. (If you've tested using `nsupdate`, it's
+ pretty easy to spot when you are running into this.)
+- Pay attention to the refresh time of the zone you are working with. For zones
+ with low traffic, it will not make a significant difference to reduce the
+ refresh time down to about five minutes while getting initial certificates.
+ Once the process is working, the beauty of `cert-manager` is it doesn't matter
+ if a renewal takes hours due to refresh times, it's all automated!
+- Compared to the other providers that often use REST APIs to modify DNS RRs,
+ this provider can take a little longer. You can `watch kubectl certificate
+ yourcert` to get a display of what's going on. It's not uncommon for the process
+ to take five minutes in total.
\ No newline at end of file
diff --git a/content/v1.12-docs/configuration/acme/dns01/route53.md b/content/v1.12-docs/configuration/acme/dns01/route53.md
new file mode 100644
index 0000000000..f18bbf128c
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/route53.md
@@ -0,0 +1,253 @@
+---
+title: Route53
+description: 'cert-manager configuration: ACME DNS-01 challenges using Amazon AWS Route53 DNS'
+---
+
+This guide explains how to set up an `Issuer`, or `ClusterIssuer`, to use Amazon
+Route53 to solve DNS01 ACME challenges. It's advised you read the [DNS01
+Challenge Provider](./README.md) page first for a more general understanding of
+how cert-manager handles DNS01 challenges.
+
+> Note: This guide assumes that your cluster is hosted on Amazon Web Services
+> (AWS) and that you already have a hosted zone in Route53.
+
+## Set up an IAM Role
+
+cert-manager needs to be able to add records to Route53 in order to solve the
+DNS01 challenge. To enable this, create a IAM policy with the following
+permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "route53:GetChange",
+ "Resource": "arn:aws:route53:::change/*"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "route53:ChangeResourceRecordSets",
+ "route53:ListResourceRecordSets"
+ ],
+ "Resource": "arn:aws:route53:::hostedzone/*"
+ },
+ {
+ "Effect": "Allow",
+ "Action": "route53:ListHostedZonesByName",
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+> Note: The `route53:ListHostedZonesByName` statement can be removed if you
+> specify the (optional) `hostedZoneID`. You can further tighten the policy by
+> limiting the hosted zone that cert-manager has access to (e.g.
+> `arn:aws:route53:::hostedzone/DIKER8JEXAMPLE`).
+
+## Credentials
+
+You have two options for the set up - either create a user or a role and attach
+that policy from above. Using a role is considered best practice because you do
+not have to store permanent credentials in a secret.
+
+cert-manager supports two ways of specifying credentials:
+
+- explicit by providing a `accessKeyID` and `secretAccessKey`
+- or implicit (using [metadata
+ service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)
+ or [environment variables or credentials
+ file](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials).
+
+cert-manager also supports specifying a `role` to enable cross-account access
+and/or limit the access of cert-manager. Integration with
+[`kiam`](https://github.com/uswitch/kiam) and
+[`kube2iam`](https://github.com/jtblin/kube2iam) should work out of the box.
+
+
+## Cross Account Access
+
+Example: Account Y manages Route53 DNS Zones. Now you want cert-manager running in Account X (or many other accounts) to be able to manage records in Route53 zones hosted in Account Y.
+
+First, create a role with the permissions policy above (let's call the role `dns-manager`)
+in Account Y, and attach a trust relationship like the one below.
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::XXXXXXXXXXX:role/cert-manager"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+
+Bear in mind, that you won't be able to define this policy until `cert-manager` role on account Y is created. If you are setting this up using a configuration language, you may want to define principal as:
+
+```json
+"Principal": {
+ "AWS": "XXXXXXXXXXX"
+ }
+```
+And restrict it, in a future step, after all the roles are created.
+
+This allows the role `cert-manager` in Account X to assume the `dns-manager` role in Account Y to manage the Route53 DNS zones in Account Y. For more information visit the [official
+documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html).
+
+Second, create the cert-manager role in Account X; this will be used as a credentials source for the cert-manager pods running in Account X. Attach to the role the following **permissions** policy:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Resource": "arn:aws:iam::YYYYYYYYYYYY:role/dns-manager",
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+
+And the following trust relationship (Add AWS `Service`s as needed):
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "ec2.amazonaws.com"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+
+## Creating an Issuer (or `ClusterIssuer`)
+
+Here is an example configuration for a `ClusterIssuer`:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-prod
+spec:
+ acme:
+ ...
+ solvers:
+
+ # example: cross-account zone management for example.com
+ # this solver uses ambient credentials (i.e. inferred from the environment or EC2 Metadata Service)
+ # to assume a role in a different account
+ - selector:
+ dnsZones:
+ - "example.com"
+ dns01:
+ route53:
+ region: us-east-1
+ hostedZoneID: DIKER8JEXAMPLE # optional, see policy above
+ role: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager
+
+ # this solver handles example.org challenges
+ # and uses explicit credentials
+ - selector:
+ dnsZones:
+ - "example.org"
+ dns01:
+ route53:
+ region: eu-central-1
+ accessKeyID: AKIAIOSFODNN7EXAMPLE
+ secretAccessKeySecretRef:
+ name: prod-route53-credentials-secret
+ key: secret-access-key
+ # you can also assume a role with these credentials
+ role: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager
+```
+
+Note that, as mentioned above, the pod is using `arn:aws:iam::XXXXXXXXXXX:role/cert-manager` as a credentials source in Account X, but the `ClusterIssuer` ultimately assumes the `arn:aws:iam::YYYYYYYYYYYY:role/dns-manager` role to actually make changes in Route53 zones located in Account Y.
+
+## EKS IAM Role for Service Accounts (IRSA)
+
+While [`kiam`](https://github.com/uswitch/kiam) / [`kube2iam`](https://github.com/jtblin/kube2iam) work directly with cert-manager, some special attention is needed for using the [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) feature available on EKS.
+
+### OIDC provider
+
+First follow the AWS documentation [Enabling IAM roles for service accounts on your cluster](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html) to ensure that the OIDC provider for the EKS cluster is enabled. The OIDC information is needed to create the trust relationship for the cert-manager role below.
+
+### IAM role trust policy
+
+The cert-manager role needs the following trust relationship attached to the role in order to use the IRSA method. Replace the following:
+
+- `` with the AWS account ID of the EKS cluster.
+- `` with the region where the EKS cluster is located.
+- `` with the hash in the EKS API URL; this will be a random 32 character hex string (example: `45DABD88EEE3A227AF0FA468BE4EF0B5`)
+- `` with the namespace where cert-manager is running.
+- `` with the name of the `ServiceAccount` object created by cert-manager.
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRoleWithWebIdentity",
+ "Principal": {
+ "Federated": "arn:aws:iam:::oidc-provider/oidc.eks..amazonaws.com/id/"
+ },
+ "Condition": {
+ "StringEquals": {
+ "oidc.eks..amazonaws.com/id/:sub": "system:serviceaccount::"
+ }
+ }
+ }
+ ]
+}
+```
+
+**Note:** If you're following the Cross Account example above, this trust policy is attached to the cert-manager role in Account X with ARN `arn:aws:iam::XXXXXXXXXXX:role/cert-manager`. The permissions policy is the same as above.
+
+### Service annotation
+
+Annotate the `ServiceAccount` created by cert-manager:
+
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ annotations:
+ eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager
+```
+
+You will also need to modify the cert-manager `Deployment` with the correct file system permissions, so the `ServiceAccount` token can be read.
+
+```yaml
+spec:
+ template:
+ spec:
+ securityContext:
+ fsGroup: 1001
+```
+
+The cert-manager Helm chart provides a variable for injecting annotations into cert-manager's `ServiceAccount` and `Deployment` object like so:
+
+```yaml
+serviceAccount:
+ annotations:
+ eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager
+securityContext:
+ fsGroup: 1001
+```
+
+**Note:** If you're following the Cross Account example above, modify the `ClusterIssuer` in the same way as above with the role from Account Y.
diff --git a/content/v1.12-docs/configuration/acme/dns01/webhook.md b/content/v1.12-docs/configuration/acme/dns01/webhook.md
new file mode 100644
index 0000000000..d9a4339e39
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/dns01/webhook.md
@@ -0,0 +1,32 @@
+---
+title: Webhook
+description: 'cert-manager configuration: ACME DNS-01 challenges using External Webhook Solvers'
+---
+
+The webhook `Issuer` is a generic ACME solver. The actual work is done by an
+external service. Look at the respective documentation of
+[`dns-providers`](../../../contributing/dns-providers.md).
+
+View more webhook solvers at https://github.com/topics/cert-manager-webhook.
+
+Here is an example of how webhook providers are to be configured. All `DNS01`
+providers will contain their own specific configuration however all require a
+`groupName` and `solverName` field.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ webhook:
+ groupName: $WEBHOOK_GROUP_NAME
+ solverName: $WEBHOOK_SOLVER_NAME
+ config:
+ ...
+
+```
diff --git a/content/v1.12-docs/configuration/acme/http01/README.md b/content/v1.12-docs/configuration/acme/http01/README.md
new file mode 100644
index 0000000000..ee46fdbe40
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/http01/README.md
@@ -0,0 +1,366 @@
+---
+title: HTTP01
+description: 'cert-manager configuration: ACME HTTP-01 challenges'
+---
+
+
+
+📌 This page focuses on solving ACME HTTP-01 challenges. If you are looking for
+how to automatically create Certificate resources by annotating Ingress or
+Gateway resources, see [Securing Ingress Resources](../../../usage/ingress.md) and
+[Securing Gateway Resources](../../../usage/gateway.md).
+
+
+
+cert-manager uses your existing Ingress or Gateway configuration in order to
+solve HTTP01 challenges.
+
+
+## Configuring the HTTP01 Ingress solver
+
+This page contains details on the different options available on the `Issuer`
+resource's HTTP01 challenge solver configuration. For more information on
+configuring ACME issuers and their API format, read the [ACME Issuers](../README.md)
+documentation.
+
+You can read about how the HTTP01 challenge type works on the [Let's Encrypt
+challenge types
+page](https://letsencrypt.org/docs/challenge-types/#http-01-challenge).
+
+Here is an example of a simple `HTTP01` ACME issuer with more options for
+configuration below:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ privateKeySecretRef:
+ name: example-issuer-account-key
+ solvers:
+ - http01:
+ ingress:
+ class: nginx
+```
+
+## Options
+
+The HTTP01 Issuer supports a number of additional options. For full details on
+the range of options available, read the [reference
+documentation](../../../reference/api-docs.md#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01).
+
+### `class`
+
+If the `class` field is specified, cert-manager will create new `Ingress`
+resources in order to route traffic to the `acmesolver` pods, which are
+responsible for responding to ACME challenge validation requests.
+
+If this field is not specified, and `name` is also not specified,
+cert-manager will default to create *new* `Ingress` resources but will **not**
+set the ingress class on these resources, meaning *all* ingress controllers
+installed in your cluster will serve traffic for the challenge solver,
+potentially incurring additional cost.
+
+
+### `name`
+
+If the `name` field is specified, cert-manager will edit the named
+ingress resource in order to solve HTTP01 challenges.
+
+This is useful for compatibility with ingress controllers such as `ingress-gce`,
+which utilize a unique IP address for each `Ingress` resource created.
+
+This mode should be avoided when using ingress controllers that expose a single
+IP for all ingress resources, as it can create compatibility problems with
+certain ingress-controller specific annotations.
+
+
`serviceType`
+
+In rare cases it might be not possible/desired to use `NodePort` as type for the
+HTTP01 challenge response service, e.g. because of Kubernetes limit
+restrictions. To define which Kubernetes service type to use during challenge
+response specify the following HTTP01 configuration:
+
+```yaml
+ http01:
+ ingress:
+ # Valid values are ClusterIP and NodePort
+ serviceType: ClusterIP
+```
+
+By default, type `NodePort` will be used when you don't set HTTP01 or when you set
+`serviceType` to an empty string. Normally there's no need to change this.
+
+
+### `podTemplate`
+
+You may wish to change or add to the labels and annotations of solver pods.
+These can be configured under the `metadata` field under `podTemplate`.
+
+Similarly, you can set the `nodeSelector`, tolerations and affinity of solver
+pods by configuring under the `spec` field of the `podTemplate`. No other
+spec fields can be edited.
+
+An example of how you could configure the template is as so:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: ...
+spec:
+ acme:
+ server: ...
+ privateKeySecretRef:
+ name: ...
+ solvers:
+ - http01:
+ ingress:
+ podTemplate:
+ metadata:
+ labels:
+ foo: "bar"
+ env: "prod"
+ spec:
+ nodeSelector:
+ bar: baz
+```
+
+The added labels and annotations will merge on top of the cert-manager defaults,
+overriding entries with the same key.
+
+No other fields of the `podTemplate` exist.
+
+### `ingressTemplate`
+
+It is possible to add labels and annotations to the solver ingress resources.
+It can be really useful when you are managing several Ingress Controllers across your cluster and you want to make sure that the right one will pick up and expose the solver (for the upcoming challenge to resolve).
+These can be configured under the `metadata` field under `ingressTemplate`:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: ...
+spec:
+ acme:
+ server: ...
+ privateKeySecretRef:
+ name: ...
+ solvers:
+ - http01:
+ ingress:
+ ingressTemplate:
+ metadata:
+ labels:
+ foo: "bar"
+ annotations:
+ "nginx.ingress.kubernetes.io/whitelist-source-range": "0.0.0.0/0,::/0"
+ "nginx.org/mergeable-ingress-type": "minion"
+ "traefik.ingress.kubernetes.io/frontend-entry-points": "http"
+```
+
+The added labels and annotations will merge on top of the cert-manager defaults,
+overriding entries with the same key.
+
+No other fields of the ingress can be edited.
+
+## Configuring the HTTP-01 Gateway API solver
+
+**FEATURE STATE**: cert-manager 1.5 [alpha]
+
+The Gateway and HTTPRoute resources are part of the [Gateway API][gwapi], a set
+of CRDs that you install on your Kubernetes cluster that provide various
+improvements over the Ingress API.
+
+[gwapi]: https://gateway-api.sigs.k8s.io
+
+
+
+📌 This feature requires the installation of the [Gateway API bundle](https://gateway-api.sigs.k8s.io/guides/#installing-a-gateway-controller) and passing a
+feature flag to the cert-manager controller.
+
+To install v1.5.1 Gateway API bundle (Gateway CRDs and webhook), run the following command:
+
+```sh
+kubectl apply -f "https://github.com/kubernetes-sigs/gateway-api/releases/download/v0.5.1/standard-install.yaml"
+```
+
+To enable the feature in cert-manager, turn on the `GatewayAPI` feature gate:
+
+- If you are using Helm:
+
+ ```sh
+ helm upgrade --install cert-manager jetstack/cert-manager --namespace cert-manager \
+ --set "extraArgs={--feature-gates=ExperimentalGatewayAPISupport=true}"
+ ```
+
+- If you are using the raw cert-manager manifests, add the following flag to the
+ cert-manager controller Deployment:
+
+ ```yaml
+ args:
+ - --feature-gates=ExperimentalGatewayAPISupport=true
+ ```
+
+The Gateway API CRDs should either be installed before cert-manager starts or
+the cert-manager Deployment should be restarted after installing the Gateway API
+CRDs. This is important because some of the cert-manager components only perform
+the Gateway API check on startup. You can restart cert-manager with the
+following command:
+
+```sh
+kubectl rollout restart deployment cert-manager -n cert-manager
+```
+
+
+
+
+
+
+🚧 cert-manager 1.8+ is tested with v1alpha2 Kubernetes Gateway API. It should also work
+with v1beta1 because of resource conversion, but has not been tested with it.
+
+
+The Gateway API HTTPRoute HTTP-01 solver creates a temporary HTTPRoute using the
+given labels. These labels must match a Gateway that contains a listener on port
+80.
+
+Here is an example of a HTTP-01 ACME Issuer using the Gateway API:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt
+ namespace: default
+spec:
+ acme:
+ solvers:
+ - http01:
+ gatewayHTTPRoute:
+ parentRefs:
+ - name: traefik
+ namespace: traefik
+ kind: Gateway
+```
+
+The Issuer relies on an existing Gateway present on the cluster. cert-manager
+does not edit Gateway resources.
+
+For example, the following Gateway will allow the Issuer to solve the challenge:
+
+```yaml
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: Gateway
+metadata:
+ name: traefik
+ namespace: traefik
+spec:
+ gatewayClassName: traefik
+ listeners:
+ - name: http
+ protocol: HTTP
+ port: 80
+ allowedRoutes:
+ namespaces:
+ from: All
+```
+
+In the above example, the Gateway has been specifically created for the purpose
+of solving HTTP-01 challenges, but you can also choose to re-use your existing
+Gateway, as long as it has a listener on port 80.
+
+The `labels` on your Issuer may reference a Gateway that is on a separate
+namespace, as long as the Gateway's port 80 listener is configured with `from:
+All`. Note that the Certificate will still be created on the same namespace as
+the Issuer, which means that you won't be able to reference this Secret in the
+above-mentioned Gateway.
+
+When the above Issuer is presented with a Certificate, cert-manager creates the
+temporary HTTPRoute. For example, with the following Certificate:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-tls
+ namespace: default
+spec:
+ issuerRef:
+ name: letsencrypt
+ dnsNames:
+ - example.net
+```
+
+You will see an HTTPRoute appear:
+
+```yaml
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: HTTPRoute
+metadata:
+ name: cm-acme-http-solver-gdhvg
+ namespace: default
+spec:
+ parentRefs:
+ - name: traefik
+ namespace: traefik
+ kind: Gateway
+ hostnames:
+ - example.net
+ rules:
+ - forwardTo:
+ - port: 8089
+ serviceName: cm-acme-http-solver-gdhvg
+ weight: 1
+ matches:
+ - path:
+ type: Exact
+ value: /.well-known/acme-challenge/YadC4gaAzqEPU1Yea0D2MrzvNRWiBCtUizCtpiRQZqI
+```
+
+After the Certificate is issued, the HTTPRoute is deleted.
+
+
`labels`
+
+These labels are copied into the temporary HTTPRoute created by cert-manager for
+solving the HTTP-01 challenge. These labels must match one of the Gateway
+resources on your cluster. The matched Gateway have a listener on port 80.
+
+Note that when the labels do not match any Gateway on your cluster, cert-manager
+will create the temporary HTTPRoute challenge and nothing will happen.
+
+
`serviceType`
+
+This field has the same meaning as the
+[`http01.ingress.serviceType`](#ingress-service-type).
+
+
+## Setting Nameservers for HTTP-01 solver propagation checks
+
+cert-manager will perform reachability tests before attempting a HTT01
+challenge. By default cert-manager will use the recursive nameservers taken
+from `/etc/resolv.conf` to query the challenge URL.
+
+If this is not desired (for example with split-horizon DNS), the cert-manager
+controller exposes a flag that allows you alter this behavior:
+
+`--acme-http01-solver-nameservers` Comma separated string with host and port of the
+recursive nameservers cert-manager should query.
+
+
+Example usage:
+```bash
+--acme-http01-solver-nameservers="8.8.8.8:53,1.1.1.1:53"
+```
+
+If you're using the `cert-manager` helm chart, you can set recursive nameservers
+through `.Values.extraArgs` or at the command at helm install/upgrade time
+with `--set`:
+
+```bash
+--set 'extraArgs={--acme-http01-solver-nameservers=8.8.8.8:53\,1.1.1.1:53}'
+```
diff --git a/content/v1.12-docs/configuration/acme/http01/externalloadbalancer.md b/content/v1.12-docs/configuration/acme/http01/externalloadbalancer.md
new file mode 100644
index 0000000000..a85966bd29
--- /dev/null
+++ b/content/v1.12-docs/configuration/acme/http01/externalloadbalancer.md
@@ -0,0 +1,34 @@
+---
+title: External Load Balancer
+description: 'cert-manager configuration: ACME HTTP-01 challenges using External Load Balancers'
+---
+
+When you are using an external load balancer provided by any host, you can face several configuration issues to get it work with cert-manager.
+
+This documentation is intended to help configure the HTTP-01 challenge type for instances behind external load balancer.
+
+## NAT Loopback / Hairpin
+
+The first configuration point is NAT loopback. You can face check issues due to Load Balancer preventing instances behind it to access its external interface.
+
+Some Network Load Balancer have this kind of limitation for several reasons. It can be configured through `iptables` rerouting configuration known as `NAT loopback`.
+
+To check if you are facing this problem :
+
+1. Check that the endpoint of the challenge is accessible to the public : `curl `
+2. Check that the challenge endpoint is NOT accessible from inside behind the Load Balancer: use SSH to open a session on a node places behind the LB; then launch the same command than before : `curl `
+
+The `HTTP-01` challenge's endpoint can be found in the logs when the `pre-check` fails. If it does not appear in the logs, you can check the challenge URL by `kubectl`command.
+
+`` is the URL used to test the HTTP-01 from the certificate `Issuer`. For Let's Encrypt for example, the URL is formed like `/.well-known/acme-challenge/`
+
+
+## Load Balancer HTTP endpoints
+
+If you are using a Load Balancer (outside a managed Kubernetes service), you should be able to configure the Load Balancer protocol as HTTP, HTTPS, TCP, UDP. Several Load Balancer now offer free TLS certificates with Let's Encrypt.
+
+When using HTTP(s) protocols for your Load Balancer, it can intercept the challenge URL to replace the response's verification hash with their hash.
+
+In this case, cert-manager will fail `did not get expected response when querying endpoint, expected 'xxxx' but got: yyyy (truncated)`.
+
+This kind of error can be thrown for multiple reasons. This case shows a correctly formatted response, but not the expected one. The solution is to configure the Load Balancer with TCP protocol so that the HTTP request will not be intercepted by the host.
\ No newline at end of file
diff --git a/content/v1.12-docs/configuration/ca.md b/content/v1.12-docs/configuration/ca.md
new file mode 100644
index 0000000000..fffb6f2401
--- /dev/null
+++ b/content/v1.12-docs/configuration/ca.md
@@ -0,0 +1,94 @@
+---
+title: CA
+description: 'cert-manager configuration: CA Issuers'
+---
+
+⚠️ CA issuers are generally either for trying cert-manager out or else for advanced users with
+a good idea of how to run a PKI. To be used safely in production, CA issuers introduce 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 CA issuer represents a Certificate Authority whose certificate and
+private key are stored inside the cluster as a Kubernetes `Secret`.
+
+Certificates issued by a CA issuer will not be publicly trusted and so are unlikely to be trusted
+by your applications without further configuration.
+
+Consider [trust-manager](../projects/trust-manager/README.md) for distributing your CA certificate safely
+across your cluster!
+
+## Deployment
+
+CA Issuers must be configured with a certificate and private key stored in a Kubernetes
+secret. You can create this externally if you wish, or you could bootstrap a root certificate
+using a [`SelfSigned` issuer](./selfsigned.md#bootstrapping-ca-issuers).
+
+Your certificate's secret should reside in the same namespace as the `Issuer`, or otherwise
+in the `Cluster Resource Namespace` in the case of a `ClusterIssuer`.
+
+The `Cluster Resource Namespace` is defaulted as being the `cert-manager` namespace, but
+can be configured using the `--cluster-resource-namespace` flag on the cert-manager controller.
+
+Below is an example of a secret resource that will be used for signing. Take
+note of the index keys used for each field as these are required in order for
+cert-manager to find the certificate and key. Also note that, like all secrets,
+data must be base64 encoded. The command `$ cat crt.pem | base64 -w0` should help you
+on GNU-based systems (Debian, Ubuntu, etc.) and `$ cat crt.pem | base64 -b0` on BSD-based
+systems (most notably macOS).
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: ca-key-pair
+ namespace: sandbox
+data:
+ tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMrVENDQWVHZ0F3SUJBZ0lKQUtQR3dLRGwvNUhuTUEwR0NTcUdTSWIzRFFFQkN3VUFNQk14RVRBUEJnTlYKQkFNTUNHcHZjMmgyWVc1c01CNFhEVEU1TURneU1qRTJNRFUxT0ZvWERUSTVNRGd4T1RFMk1EVTFPRm93RXpFUgpNQThHQTFVRUF3d0lhbTl6YUhaaGJtd3dnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCCkFRQ3doU0IvcVc2L2tMYjJ6cHUrRUp2RDl3SEZhcStRQS8wSkgvTGxseW83ekFGeCtISHErQ09BYmsrQzhCNHQKL0hVRXNuczVSTDA5Q1orWDRqNnBiSkZkS2R1UHhYdTVaVllua3hZcFVEVTd5ZzdPU0tTWnpUbklaNzIzc01zMApSNmpZbi9Ecmo0eFhNSkVmSFVEcVllU1dsWnIzcWkxRUZhMGM3ZlZEeEgrNHh0WnROTkZPakg3YzZEL3ZXa0lnCldRVXhpd3Vzc2U2S01PV2pEbnYvNFZyamVsMlFnVVlVYkhDeWVaSG1jdGkrSzBMV0Nmby9SZzZQdWx3cmJEa2gKam1PZ1l0MzBwZGhYME9aa0F1a2xmVURIZnA4YmpiQ29JMnRhWUFCQTZBS2pLc08zNUxBRVU3OUNMMW1MVkh1WgpBQ0k1VWppamEzVlBXVkhTd21KUEp5dXhBZ01CQUFHalVEQk9NQjBHQTFVZERnUVdCQlFtbDVkVEFaaXhGS2hqCjkzd3VjUldoYW8vdFFqQWZCZ05WSFNNRUdEQVdnQlFtbDVkVEFaaXhGS2hqOTN3dWNSV2hhby90UWpBTUJnTlYKSFJNRUJUQURBUUgvTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFCK2tsa1JOSlVLQkxYOHlZa3l1VTJSSGNCdgpHaG1tRGpKSXNPSkhac29ZWGRMbEcxcFpORmpqUGFPTDh2aDQ0Vmw5OFJoRVpCSHNMVDFLTWJwMXN1NkNxajByClVHMWtwUkJlZitJT01UNE1VN3ZSSUNpN1VPbFJMcDFXcDBGOGxhM2hQT2NSYjJ5T2ZGcVhYeVpXWGY0dDBCNDUKdEhpK1pDTkhCOUZ4alNSeWNiR1lWaytUS3B2aEphU1lOTUdKM2R4REthUDcrRHgzWGNLNnNBbklBa2h5SThhagpOVSttdzgvdG1Sa1A0SW4va1hBUitSaTBxVW1Iai92d3ZuazRLbTdaVXkxRllIOERNZVM1TmtzbisvdUhsUnhSClY3RG5uMDM5VFJtZ0tiQXFONzJnS05MbzVjWit5L1lxREFZSFlybjk4U1FUOUpEZ3RJL0svQVRwVzhkWAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
+ tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBc0lVZ2Y2bHV2NUMyOXM2YnZoQ2J3L2NCeFdxdmtBUDlDUi95NVpjcU84d0JjZmh4CjZ2Z2pnRzVQZ3ZBZUxmeDFCTEo3T1VTOVBRbWZsK0krcVd5UlhTbmJqOFY3dVdWV0o1TVdLVkExTzhvT3praWsKbWMwNXlHZTl0N0RMTkVlbzJKL3c2NCtNVnpDUkh4MUE2bUhrbHBXYTk2b3RSQld0SE8zMVE4Ui91TWJXYlRUUgpUb3grM09nLzcxcENJRmtGTVlzTHJMSHVpakRsb3c1Ny8rRmE0M3Bka0lGR0ZHeHdzbm1SNW5MWXZpdEMxZ242ClAwWU9qN3BjSzJ3NUlZNWpvR0xkOUtYWVY5RG1aQUxwSlgxQXgzNmZHNDJ3cUNOcldtQUFRT2dDb3lyRHQrU3cKQkZPL1FpOVppMVI3bVFBaU9WSTRvMnQxVDFsUjBzSmlUeWNyc1FJREFRQUJBb0lCQUNFTkhET3JGdGg1a1RpUApJT3dxa2UvVVhSbUl5MHlNNHFFRndXWXBzcmUxa0FPMkFDWjl4YS96ZDZITnNlanNYMEM4NW9PbmtrTk9mUHBrClcxVS94Y3dLM1ZpRElwSnBIZ09VNzg1V2ZWRXZtU3dZdi9Fb1V3eHFHRVMvcnB5Z1drWU5WSC9XeGZGQlg3clMKc0dmeVltbXJvM09DQXEyLzNVVVFiUjcrT09md3kzSHdUdTBRdW5FSnBFbWU2RXdzdWIwZzhTTGp2cEpjSHZTbQpPQlNKSXJyL1RjcFRITjVPc1h1Vm5FTlVqV3BBUmRQT1NrRFZHbWtCbnkyaVZURElST3NGbmV1RUZ1NitXOWpqCmhlb1hNN2czbkE0NmlLenUzR0YwRWhLOFkzWjRmeE42NERkbWNBWnphaU1vMFJVaktWTFVqbVlQSEUxWWZVK3AKMkNYb3dNRUNnWUVBMTgyaU52UEkwVVlWaUh5blhKclNzd1YrcTlTRStvVi90U2ZSUUNGU2xsV0d3KzYyblRiVwpvNXpoL1RDQW9VTVNSbUFPZ0xKWU1LZUZ1SWdvTEoxN1pvWjN0U1czTlVtMmRpT0lPSHorcTQxQzM5MDRrUzM5CjkrYkFtVmtaSFA5VktLOEMraS9tek5mSkdHZEJadGIweWtTM2t3OUIxTHdnT3o3MDhFeXFSQ2tDZ1lFQTBXWlAKbzF2MThnV2tMK2FnUDFvOE13eDRPZlpTN3dKY3E0Z0xnUWhjYS9pSkttY0x0RFN4cUJHckJ4UVo0WTIyazlzdQpzTFVrNEJobGlVM29iUUJNaUdtMGtITHVBSEFRNmJvdWZBMUJwZjN2VFdHSkhSRjRMeFJsNzc2akw4UXI4VnpxClpURVBtY0R0T0hpYjdwb2I1Z2IzSDhiVGhYeUhmdGZxRW55alhFa0NnWUVBdk9DdDZZclZhTlQrWThjMmRFYk4Kd3dJOExBaUZtdjdkRjZFUjlCODJPWDRCeGR0WTJhRDFtNTNqN2NaVnpzNzFYOE1TN25FcDN1dkFqaElkbDI3KwpZbTJ1dUUyYVhIbDN5VTZ3RzBETFpUcnVIU0Z5TVI4ZithbHRTTXBDd0s1NXluSGpHVFp6dXpYaVBBbWpwRzdmCk1XbVRncE1IK3puc3UrNE9VNFBHUW9FQ2dZQWNqdUdKbS84YzlOd0JsR2lDZTJIK2JGTHhSTURteStHcm16QkcKZHNkMENqOWF3eGI3aXJ3MytjRGpoRUJMWExKcjA5YTRUdHdxbStrdElxenlRTG92V0l0QnNBcjVrRThlTVVBcAp0djBmRUZUVXJ0cXVWaldYNWlaSTNpMFBWS2ZSa1NSK2pJUmVLY3V3aWZKcVJpWkw1dU5KT0NxYzUvRHF3Yk93CnRjTHAwUUtCZ0VwdEw1SU10Sk5EQnBXbllmN0F5QVBhc0RWRE9aTEhNUGRpL2dvNitjSmdpUmtMYWt3eUpjV3IKU25QSG1TbFE0aEluNGMrNW1lbHBDWFdJaklLRCtjcTlxT2xmQmRtaWtYb2RVQ2pqWUJjNnVGQ1QrNWRkMWM4RwpiUkJQOUNtWk9GL0hOcHN0MEgxenhNd1crUHk5Q2VnR3hhZ0ZCekxzVW84N0xWR2h0VFFZCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
+```
+
+> Note: If your issuer represents an intermediate, ensure that `tls.crt` contains
+> the issuer's full chain in the correct order: `issuer -> intermediate(s) -> root`.
+> The root (self-signed) CA certificate is optional, but adding it will ensure that
+> the correct CA certificate is stored in the secrets for issued `Certificate`s under
+> the `ca.crt` key. If you fail to provide a complete chain, it might not be possible
+> for consumers of issued `Certificate`s to verify whether they're trusted.
+
+Next is to deploy the CA issuer which references this `Secret`. This is done by
+referencing the secret name under the `ca` stanza in the `Issuer` spec.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: ca-issuer
+ namespace: sandbox
+spec:
+ ca:
+ secretName: ca-key-pair
+```
+
+Optionally, you can specify [CRL](https://en.wikipedia.org/wiki/Certificate_revocation_list) Distribution Points; an array of strings each of which identifies the location of the CRL from which the revocation of this certificate can be checked.
+
+```yaml
+...
+spec:
+ ca:
+ secretName: ca-key-pair
+ crlDistributionPoints:
+ - "http://example.com"
+```
+
+Once deployed, you can then check that the issuer has been successfully
+configured by checking the ready status of the certificate. Replace `issuers`
+here with `clusterissuers` if that is what has been deployed.
+
+```bash
+$ kubectl get issuers ca-issuer -n sandbox -o wide
+NAME READY STATUS AGE
+ca-issuer True Signing CA verified 2m
+```
+
+Certificates are now ready to be requested by using the CA `Issuer` named
+`ca-issuer` within the `sandbox` namespace.
diff --git a/content/docs/configuration/external.md b/content/v1.12-docs/configuration/external.md
similarity index 100%
rename from content/docs/configuration/external.md
rename to content/v1.12-docs/configuration/external.md
diff --git a/content/v1.12-docs/configuration/selfsigned.md b/content/v1.12-docs/configuration/selfsigned.md
new file mode 100644
index 0000000000..bfc2b39b2b
--- /dev/null
+++ b/content/v1.12-docs/configuration/selfsigned.md
@@ -0,0 +1,171 @@
+---
+title: SelfSigned
+description: 'cert-manager configuration: SelfSigned Issuers'
+---
+
+⚠️ `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](#caveats) - including security issues - to
+consider with `SelfSigned` issuers; in general you'd likely want to use a
+[`CA`](./ca.md) issuer rather than a `SelfSigned` issuer. That said,
+`SelfSigned` issuers are really useful for initially [bootstrapping](#bootstrapping-ca-issuers)
+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:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: selfsigned-issuer
+ namespace: sandbox
+spec:
+ selfSigned: {}
+```
+
+```yaml
+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:
+
+```bash
+$ 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`](./ca.md)
+issuer.
+
+The YAML below will create a `SelfSigned` issuer, issue a root certificate and
+use that root as a `CA` issuer:
+
+```yaml
+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
+```
+
+### CRL Distribution Points
+
+You may also optionally specify [CRL](https://en.wikipedia.org/wiki/Certificate_revocation_list)
+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:
+
+```yaml
+...
+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](../projects/trust-manager/README.md) 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](https://tools.ietf.org/html/rfc5280#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](https://github.com/cert-manager/cert-manager/blob/45befd86966c563663d18848943a1066d9681bf8/pkg/controller/certificaterequests/selfsigned/selfsigned.go#L140)
+of type `BadConfig` if it detects that a certificate is being created
+by a `SelfSigned` issuer which has an empty Issuer DN.
diff --git a/content/v1.12-docs/configuration/vault.md b/content/v1.12-docs/configuration/vault.md
new file mode 100644
index 0000000000..c2dd25aee5
--- /dev/null
+++ b/content/v1.12-docs/configuration/vault.md
@@ -0,0 +1,270 @@
+---
+title: Vault
+description: 'cert-manager configuration: Vault Issuers'
+---
+
+The `Vault` `Issuer` represents the certificate authority
+[Vault](https://www.vaultproject.io/) - a multi-purpose secret store that can be
+used to sign certificates for your Public Key Infrastructure (PKI). Vault is an
+external project to cert-manager and as such, this guide will assume it has been
+configured and deployed correctly, ready for signing. You can read more on how
+to configure Vault as a certificate authority
+[here](https://www.vaultproject.io/docs/secrets/pki/).
+
+This `Issuer` type is typically used when Vault is already being used within
+your infrastructure, or you would like to make use of its feature set where the
+CA issuer alone cannot provide.
+
+## Deployment
+
+All Vault issuers share common configuration for requesting certificates,
+namely the server, path, and CA bundle:
+
+- Server is the URL whereby Vault is reachable.
+- Path is the Vault path that will be used for signing. Note that the path
+ *must* use the `sign` endpoint.
+- CA bundle denotes an optional field containing a base64 encoded string of the
+ Certificate Authority to trust the Vault connection. This is typically
+ _always_ required when using an `https` URL.
+
+Below is an example of a configuration to connect a Vault server.
+
+> **Warning**: This configuration is incomplete as no authentication methods have
+> been added.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vault-issuer
+ namespace: sandbox
+spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ ...
+```
+
+## Authenticating
+
+In order to request signing of certificates by Vault, the issuer must be able to
+properly authenticate against it. cert-manager provides multiple approaches to
+authenticating to Vault which are detailed below.
+
+### Authenticating via an AppRole
+
+An [AppRole](https://www.vaultproject.io/docs/auth/approle.html) is a method of
+authenticating to Vault through use of its internal role policy system. This
+authentication method requires that the issuer has possession of the `SecretID`
+secret key, the `RoleID` of the role to assume, and the app role path. Firstly,
+the secret ID key must be stored within a Kubernetes `Secret` that resides in the
+same namespace as the `Issuer`, or otherwise inside the `Cluster Resource
+Namespace` in the case of a `ClusterIssuer`.
+
+```yaml
+apiVersion: v1
+kind: Secret
+type: Opaque
+metadata:
+ name: cert-manager-vault-approle
+ namespace: sandbox
+data:
+ secretId: "MDI..."
+```
+
+Once the `Secret` has been created, the `Issuer` is ready to be deployed which
+references this `Secret`, as well as the data key of the field that stores the
+secret ID.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vault-issuer
+ namespace: sandbox
+spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ appRole:
+ path: approle
+ roleId: "291b9d21-8ff5-..."
+ secretRef:
+ name: cert-manager-vault-approle
+ key: secretId
+```
+
+### Authenticating with a Token
+
+This method of authentication uses a token string that has been generated from
+one of the many authentication backends that Vault supports. These tokens have
+an expiry and so need to be periodically refreshed. You can read more on Vault
+tokens [here](https://www.vaultproject.io/docs/concepts/tokens.html).
+
+> **Note**: cert-manager does not refresh these token automatically and so another
+> process must be put in place to do this.
+
+Firstly, the token is be stored inside a Kubernetes `Secret` inside the same
+namespace as the `Issuer` or otherwise in the `Cluster Resource Namespace` in
+the case of using a `ClusterIssuer`.
+
+```yaml
+apiVersion: v1
+kind: Secret
+type: Opaque
+metadata:
+ name: cert-manager-vault-token
+ namespace: sandbox
+data:
+ token: "MjI..."
+```
+
+Once submitted, the Vault issuer is able to be created using token
+authentication by referencing this `Secret` along with the key of the field the
+token data is stored at.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vault-issuer
+ namespace: sandbox
+spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ tokenSecretRef:
+ name: cert-manager-vault-token
+ key: token
+```
+
+### Authenticating with Kubernetes Service Accounts
+
+Vault can be configured so that applications can authenticate using Kubernetes
+[`Service Account
+Tokens`](https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin).
+You find documentation on how to configure Vault to authenticate using Service
+Account Tokens [here](https://www.vaultproject.io/docs/auth/kubernetes.html).
+
+For the Vault issuer to use this authentication, cert-manager must get access to
+the token that is stored in a Kubernetes `Secret`. Kubernetes Service Account
+Tokens are already stored in `Secret` resources however, you must ensure that
+it is present in the same namespace as the `Issuer`, or otherwise in the
+`Cluster Resource Namespace` in the case of using a `ClusterIssuer`.
+
+> **Note**: In Kubernetes 1.24 onwards, the token secret is no longer created
+> by default for the Service Account. In this case you need to manually create
+> the secret resource. See [this guide](https://kubernetes.io/docs/concepts/configuration/secret/#service-account-token-secrets)
+> for more details.
+
+This authentication method also expects a `role` field which is the Vault role
+that the Service Account is to assume, as well as an optional `mountPath` field which
+is the authentication mount path, defaulting to `kubernetes`.
+
+#### Kubernetes version less than 1.24
+
+The following example will be making use of the Service Account
+`my-service-account`. The secret data field key will be `token` if the `Secret`
+has been created by Kubernetes. The Vault role used is `my-app-1`, using the
+default mount path of `/v1/auth/kubernetes`
+
+1) Create the Service Account:
+
+ ```shell
+ kubectl create serviceaccount -n sandbox vault-issuer
+ ```
+
+1) Get the auto-generated Secret name:
+
+ ```shell
+ kubectl get secret -o json | jq -r '.items[] | select(.metadata.annotations["kubernetes.io/service-account.name"] == "vault-issuer") | .metadata.name'
+ ```
+
+1) Create the Issuer using that Secret name retrieved from the previous step:
+
+ ```yaml
+ apiVersion: cert-manager.io/v1
+ kind: Issuer
+ metadata:
+ name: vault-issuer
+ namespace: sandbox
+ spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ kubernetes:
+ role: my-app-1
+ mountPath: /v1/auth/kubernetes
+ secretRef:
+ name:
+ key: token
+ ```
+
+#### Kubernetes version 1.24 and greater
+
+This example is almost the same as above but adjusted for the change in
+Kubernetes 1.24 and above.
+
+1) Create the Service Account:
+
+ ```shell
+ kubectl create serviceaccount -n sandbox vault-issuer
+ ```
+
+1) Create the Secret resource for Kubernetes to populate the `token` value:
+
+ ```yaml
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ name: vault-issuer-token
+ annotations:
+ kubernetes.io/service-account.name: "vault-issuer"
+ type: kubernetes.io/service-account-token
+ data: {}
+ ```
+
+1) Create the Issuer resource referencing the Secret resource:
+
+ ```yaml
+ apiVersion: cert-manager.io/v1
+ kind: Issuer
+ metadata:
+ name: vault-issuer
+ namespace: sandbox
+ spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ kubernetes:
+ role: my-app-1
+ mountPath: /v1/auth/kubernetes
+ secretRef:
+ name: vault-issuer-token
+ key: token
+ ```
+
+## Verifying the issuer Deployment
+
+Once the Vault issuer has been deployed, it will be marked as ready if the
+configuration is valid. Replace `issuers` here with `clusterissuers` if that is what has
+been deployed.
+
+```bash
+$ kubectl get issuers vault-issuer -n sandbox -o wide
+NAME READY STATUS AGE
+vault-issuer True Vault verified 2m
+```
+
+Certificates are now ready to be requested by using the Vault issuer named
+`vault-issuer` within the `sandbox` namespace.
\ No newline at end of file
diff --git a/content/v1.12-docs/configuration/venafi.md b/content/v1.12-docs/configuration/venafi.md
new file mode 100644
index 0000000000..93498b0ace
--- /dev/null
+++ b/content/v1.12-docs/configuration/venafi.md
@@ -0,0 +1,282 @@
+---
+title: Venafi
+description: 'cert-manager configuration: Venafi Issuers'
+---
+
+## Introduction
+
+The Venafi `Issuer` types allows you to obtain certificates from [Venafi
+as a Service (VaaS)](https://vaas.venafi.com/jetstack) and [Venafi Trust Protection
+Platform (TPP)](https://www.venafi.com/platform/tls-protect) instances.
+
+You can have multiple different Venafi `Issuer` types installed within the same
+cluster, including mixtures of Venafi as a Service and TPP issuer types. This allows
+you to be flexible with the types of Venafi account you use.
+
+Automated certificate renewal and management are provided for `Certificates`
+using the Venafi `Issuer`.
+
+A single Venafi `Issuer` represents a single Venafi 'zone' so you must create one
+`Issuer` resource for each zone you want to use. A zone is a single entity that
+combines the policy that governs certificate issuance with information about how
+certificates are organized in Venafi to identify the business application and
+establish ownership.
+
+You can configure your `Issuer` resource to either issue certificates only
+within a single namespace, or cluster-wide (using a `ClusterIssuer` resource).
+For more information on the distinction between `Issuer` and `ClusterIssuer`
+resources, read the [Namespaces](../concepts/issuer.md#namespaces) section.
+
+## Creating a Venafi as a Service Issuer
+
+If you haven't already done so, create your Venafi as a Service account on this
+[page](https://vaas.venafi.com/jetstack) and copy the API key from your user
+preferences. Then you may want to create a custom CA Account and Issuing Template
+or choose instead to use defaults that are automatically created for testing
+("Built-in CA" and "Default", respectively). Lastly you'll need to create an
+Application for establishing ownership of all the certificates requested by your
+cert-manager Issuer, and assign to it the Issuing Template.
+
+> Make a note of the Application name and API alias of the Issuing Template because
+> together they comprise the 'zone' you will need for your `Issuer` configuration.
+
+In order to set up a Venafi as a Service `Issuer`, you must first create a Kubernetes
+`Secret` resource containing your Venafi as a Service API credentials:
+
+```bash
+$ kubectl create secret generic \
+ vaas-secret \
+ --namespace='NAMESPACE OF YOUR ISSUER RESOURCE' \
+ --from-literal=apikey='YOUR_VAAS_API_KEY_HERE'
+```
+
+> **Note**: If you are configuring your issuer as a `ClusterIssuer` resource in
+> order to serve `Certificates` across your whole cluster, you must set the
+> `--namespace` parameter to `cert-manager`, which is the default `Cluster
+> Resource Namespace`. The `Cluster Resource Namespace` can be configured
+> through the `--cluster-resource-namespace` flag on the cert-manager controller
+> component.
+
+This API key will be used by cert-manager to interact with Venafi as a Service
+on your behalf.
+
+Once the API key `Secret` has been created, you can create your `Issuer` or
+`ClusterIssuer` resource. If you are creating a `ClusterIssuer` resource, you
+must change the `kind` field to `ClusterIssuer` and remove the
+`metadata.namespace` field.
+
+Save the below content after making your amendments to a file named
+`vaas-issuer.yaml`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vaas-issuer
+ namespace:
+spec:
+ venafi:
+ zone: "My Application\My CIT" # Set this to \
+ cloud:
+ apiTokenSecretRef:
+ name: vaas-secret
+ key: apikey
+```
+
+You can then create the Issuer using `kubectl create`.
+
+```bash
+$ kubectl create -f vaas-issuer.yaml
+```
+
+Verify the `Issuer` has been initialized correctly using `kubectl describe`.
+
+```bash
+$ kubectl get issuer vaas-issuer --namespace='NAMESPACE OF YOUR ISSUER RESOURCE' -o wide
+NAME READY STATUS AGE
+vaas-issuer True Venafi issuer started 2m
+```
+
+You are now ready to issue certificates using the newly provisioned Venafi
+`Issuer` and Venafi as a Service.
+
+Read the [Issuing Certificates](../usage/certificate.md) document for
+more information on how to create Certificate resources.
+
+
+## Creating a Venafi Trust Protection Platform Issuer
+
+The Venafi Trust Protection Platform integration allows you to obtain certificates
+from a properly configured Venafi TPP instance.
+
+The setup is similar to the Venafi as a Service configuration above, however some
+of the connection parameters are slightly different.
+
+> **Note**: You *must* allow "User Provided CSRs" as part of your TPP policy, as
+> this is the only type supported by cert-manager at this time.
+>
+> More specifically, the valid configurations of the "CSR handling" are:
+>
+> - "User Provided CSRs" selected and unlocked,
+> - "User Provided CSRs" selected and locked,
+> - "Service Generated CSRs" selected and unlocked.
+>
+> When using "Service Generated CSRs" selected and unlocked, the default CSR
+> configuration present in your policy folder will override the configuration of
+> your Certificate resource. The subject DN, key algorithm, and key size will be
+> overridden by the values set in the policy folder.
+>
+> With "Service Generated CSRs" selected and locked, the certificate issuance
+> will systematically fail with the following message:
+>
+> ```plain
+> 400 PKCS#10 data will not be processed. Policy "\VED\Policy\foo" is locked to a Server Generated CSR.
+> ```
+
+In order to set up a Venafi Trust Protection Platform `Issuer`, you must first
+create a Kubernetes `Secret` resource containing your Venafi TPP API
+credentials.
+
+### Access Token Authentication
+
+1. [Set up token authentication](https://docs.venafi.com/Docs/21.1/TopNav/Content/SDK/AuthSDK/t-SDKa-Setup-OAuth.php).
+
+ NOTE: Do not select "Refresh Token Enabled" and set a *long* "Token Validity (days)".
+
+2. Create a new user with sufficient privileges to manage and revoke certificates in a particular policy folder (zone).
+
+ E.g. `k8s-xyz-automation`
+
+3. [Create a new application integration](https://docs.venafi.com/Docs/21.1/TopNav/Content/API-ApplicationIntegration/t-APIAppIntegrations-creatingNew-Aperture.php)
+
+ Create an application integration with name and ID `cert-manager`.
+ Set the "API Access Settings" to `Certificates: Read,Manage,Revoke`.
+
+ "Edit Access" to the new application integration, and allow it to be used by the user you created earlier.
+
+4. [Generate an access token](https://github.com/Venafi/vcert/blob/master/README-CLI-PLATFORM.md#obtaining-an-authorization-token)
+
+ ```
+ vcert getcred \
+ --username k8s-xyz-automation \
+ --password somepassword \
+ -u https://tpp.example.com/vedsdk \
+ --client-id cert-manager \
+ --scope "certificate:manage,revoke"
+ ```
+
+ This will print an access-token to `stdout`. E.g.
+
+ ```
+ vCert: 2020/10/07 16:34:27 Getting credentials
+ access_token: I69n.............y1VjNJT3o9U0Wko19g==
+ access_token_expires: 2021-01-05T15:34:30Z
+ ```
+
+5. Save the access-token to a Secret in the Kubernetes cluster
+
+```bash
+$ kubectl create secret generic \
+ tpp-secret \
+ --namespace= \
+ --from-literal=access-token='YOUR_TPP_ACCESS_TOKEN'
+```
+
+### Username / Password Authentication
+
+> ⚠️ When you supply a Venafi TPP username and password,
+> cert-manager uses an older authentication method which is called "API Keys",
+> which has been deprecated since Venafi TPP `19.2`.
+>
+> Beginning in Venafi TPP `22.2`, "API Keys" are disabled by default.
+> You will need to contact Venafi customer support for a special license key which will allow you to re-enable the "API Keys" feature,
+> so that you can continue to use username and password authentication with cert-manager.
+>
+> In Venafi TPP `22.3`, the "API Keys" feature will be permanently removed,
+> and you will need to use access-token authentication instead.
+>
+> 📖 Read [Deprecated functionality from Venafi Platform](https://docs.venafi.com/22.3/deprecation-list-current)
+> and [Functionality Scheduled for Deprecation](https://support.venafi.com/hc/en-us/articles/115001662292) for more information.
+
+```bash
+$ kubectl create secret generic \
+ tpp-secret \
+ --namespace= \
+ --from-literal=username='YOUR_TPP_USERNAME_HERE' \
+ --from-literal=password='YOUR_TPP_PASSWORD_HERE'
+```
+
+> Note: If you are configuring your issuer as a `ClusterIssuer` resource in
+> order to issue `Certificates` across your whole cluster, you must set the
+> `--namespace` parameter to `cert-manager`, which is the default `Cluster
+> Resource Namespace`. The `Cluster Resource Namespace` can be configured
+> through the `--cluster-resource-namespace` flag on the cert-manager controller
+> component.
+
+These credentials will be used by cert-manager to interact with your Venafi TPP
+instance. Username attribute must be adhere to the `:` format. For example: `local:admin`.
+
+Once the Secret containing credentials has been created, you can create your
+`Issuer` or `ClusterIssuer` resource. If you are creating a `ClusterIssuer`
+resource, you must change the `kind` field to `ClusterIssuer` and remove the
+`metadata.namespace` field.
+
+Save the below content after making your amendments to a file named
+`tpp-issuer.yaml`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: tpp-issuer
+ namespace:
+spec:
+ venafi:
+ zone: \VED\Policy\devops\cert-manager # Set this to the Venafi policy folder you want to use
+ tpp:
+ url: https://tpp.venafi.example/vedsdk # Change this to the URL of your TPP instance
+ caBundle:
+ credentialsRef:
+ name: tpp-secret
+```
+
+You can then create the `Issuer` using `kubectl create -f`.
+
+```bash
+$ kubectl create -f tpp-issuer.yaml
+```
+
+Verify the `Issuer` has been initialized correctly using `kubectl describe`.
+
+```bash
+$ kubectl describe issuer tpp-issuer --namespace='NAMESPACE OF YOUR ISSUER RESOURCE'
+```
+
+You are now ready to issue certificates using the newly provisioned Venafi
+`Issuer` and Trust Protection Platform.
+
+Read the [Issuing Certificates](../usage/certificate.md) document for
+more information on how to create Certificate resources.
+
+## Issuer specific annotations
+
+### Custom Fields
+
+Starting `v0.14` you can pass custom fields to Venafi (TPP version `v19.2` and higher) using the `venafi.cert-manager.io/custom-fields` annotation on Certificate resources.
+The value is a JSON encoded array of custom field objects having a `name` and `value` key.
+For example:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com-certificate
+ annotations:
+ venafi.cert-manager.io/custom-fields: |-
+ [
+ {"name": "field-name", "value": "field value"},
+ {"name": "field-name-2", "value": "field value 2"}
+ ]
+...
+```
diff --git a/content/v1.12-docs/faq/README.md b/content/v1.12-docs/faq/README.md
new file mode 100644
index 0000000000..9bb31f91b5
--- /dev/null
+++ b/content/v1.12-docs/faq/README.md
@@ -0,0 +1,182 @@
+---
+title: Frequently Asked Questions (FAQ)
+description: Find answers to some frequently asked questions about cert-manager
+---
+
+On this page you will find answers to some frequently asked questions about cert-manager.
+
+## Terminology
+
+### What does `publicly trusted` and `self-signed` mean?
+
+These terms are defined in the [TLS Terminology page](../reference/tls-terminology.md).
+
+### What do the terms `root`, `intermediate` and `leaf` _certificate_ mean?
+
+These terms are defined in the [TLS Terminology page](../reference/tls-terminology.md).
+
+## Certificates
+
+### Can I trigger a renewal from cert-manager at will?
+
+This is a feature in cert-manager starting in `v0.16` using the `cmctl` CLI. More information can be found on [the renew command's page](../reference/cmctl.md#renew)
+
+### When do certs get re-issued?
+
+To determine if a certificate needs to be re-issued, cert-manager looks at the the spec of `Certificate` resource and latest `CertificateRequest`s as well as the data in `Secret` containing the X.509 certificate.
+
+The issuance process will always get triggered if the:
+
+- `Secret` named on `Certificate`'s spec, does not exist, is missing private key or certificate data or contains corrupt data
+- private key stored in the `Secret` does not match the private key spec on `Certificate`
+- public key of the issued certificate does not match the private key stored in the `Secret`
+- cert-manager issuer annotations on the `Secret` do not match the issuer specified on the `Certificate`
+- DNS names, IP addresses, URLS or email addresses on the issued certificate do not match those on the `Certificate` spec
+- certificate needs to be renewed (because it has expired or the renewal time is now or in the past)
+- certificate has been marked for renewal manually [using `cmctl`](../reference/cmctl.md#renew)
+
+Additionally, if the latest `CertificateRequest` for the `Certificate` is found, cert-manager will also re-issue if:
+
+- the common name on the CSR found on the `CertificateRequest` does not match that on the `Certificate` spec
+- the subject fields on the CSR found on the `CertificateRequest` do not match the subject fields of the `Certificate` spec
+- the duration on the `CertificateRequest` does not match the duration on the `Certificate` spec
+- `isCA` field value on the `Certificate` spec does not match that on the `CertificateRequest`
+- the DNS names, IP addresses, URLS or email addresses on the `CertificateRequest` spec do not match those on the `Certificate` spec
+- key usages on the `CertificateRequest` spec do not match those on the `Certificate` spec
+
+Note that for certain fields re-issuance on change gets triggered only if there
+is a `CertificateRequest` that cert-manager can use to determine whether
+`Certificate`'s spec has changed since the previous issuance. This is because
+some issuers may not respect the requested values for these fields, so we cannot
+rely on the values in the issued X.509 certificates. One such field is
+`.spec.duration`- change to this field will only trigger re-issuance if there is
+a `CertificateRequest` to compare with. In case where you need to re-issue, but
+re-issuance does not get triggered automatically due to there being no
+`CertificateRequest` (i.e after backup and restore), you can use [`cmctl
+renew`](../reference/cmctl.md#renew) to trigger it manually.
+
+### Why isn't my root certificate in my issued Secret's `tls.crt`?
+
+Occasionally, people work with systems which have made a flawed choice regarding TLS chains. The [TLS spec](https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.2)
+has the following section for the "Server Certificate" section of the TLS handshake:
+
+> This is a sequence (chain) of certificates. The sender's
+> certificate MUST come first in the list. Each following
+> certificate MUST directly certify the one preceding it. Because
+> certificate validation requires that root keys be distributed
+> independently, the self-signed certificate that specifies the root
+> certificate authority MAY be omitted from the chain, under the
+> assumption that the remote end must already possess it in order to
+> validate it in any case.
+
+In a standard, secure and correctly configured TLS environment, adding a root certificate to the chain is
+almost always unnecessary and wasteful.
+
+There are two ways that a certificate can be trusted:
+
+- explicitly, by including it in a trust store.
+- through a signature, by following the certificate's chain back up to an explicitly trusted certificate.
+
+Crucially, root certificates are by definition self-signed and they cannot be validated through a signature.
+
+As such, if we have a client trying to validate the certificate chain sent by the server, the client must already have the
+root before the connection is started. If the client already has the root, there was no point in it being sent by the server!
+
+The same logic with not sending root certificates applies for servers trying to validate client certificates;
+the [same justification](https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.6) is given in the TLS RFC.
+
+### How can I see all the historic events related to a certificate object?
+
+cert-manager publishes all events to the Kubernetes events mechanism, you can get the events for your specific resources using `kubectl describe `.
+
+Due to the nature of the Kubernetes event mechanism these will be purged after a while. If you're using a dedicated logging system it might be able or is already also storing Kubernetes events.
+
+### What happens if issuance fails? Will it be retried?
+
+{/* This empty link preserves old links to #what-happens-if-a-renewal-doesn't happen?-will-it-be-tried-again-after-some-time?", which matched the old title of this section */}
+
+
+
+cert-manager will retry a failed issuance except for a few rare edge cases where
+manual intervention is needed.
+
+We aim to retry after a short delay in case of ephemeral failures such as
+network connection errors and with a longer exponentially increasing delay after
+'terminal' failures.
+
+You can observe that latest issuance has terminally failed if the `Certificate`
+has `Issuing` condition set to false and has `status.lastFailureTime` set. In
+this case the issuance will be retried after an exponentially increasing delay
+(1 to 32 hours) by creating a new `CertficateRequest`. You can trigger an
+immediate renewal using the [`cmctl renew`
+command](../reference/cmctl.md#renew). Terminal failures occur if the issuer
+sets the `CertificateRequest` to failed (for example if CA rejected the request
+due to a rate limit being reached) or invalid or if the `CertificateRequest`
+gets denied by an approver.
+
+Ephemeral failures result in the same `CertificateRequest` being re-synced after
+a short delay (up to 5 minutes). Typically they can only be observed in
+cert-manager controller logs.
+
+If it appears the issuance has got stuck and `cmctl renew` does not work, you
+can delete the latest `CertificateRequest`. This is mostly a harmless action
+(the worst that could happen is duplicate issuance if there was a potentially
+successful one in progress), but we do aim for this to not be part of user flow-
+do reach out if you think you have found a case where the flow could be
+improved.
+
+### Is ECC (elliptic-curve cryptography) supported?
+
+cert-manager supports ECDSA key pairs! You can set your certificate to use ECDSA in the `privateKey` part of your Certificate resource.
+
+For example:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: ecdsa
+spec:
+ secretName: ecdsa-cert
+ isCA: false
+ privateKey:
+ algorithm: ECDSA
+ size: 256
+ dnsNames:
+ - ecdsa.example.com
+ issuerRef:
+ [...]
+```
+
+### If `renewBefore` or `duration` is not defined, what will be the default value?
+
+Default `duration` is [90 days](https://github.com/cert-manager/cert-manager/blob/v1.2.0/pkg/apis/certmanager/v1/const.go#L26). If `renewBefore` has not been set, `Certificate` will be renewed 2/3 through its _actual_ duration.
+
+## Miscellaneous
+
+### Kubernetes has a builtin `CertificateSigningRequest` API. Why not use that?
+
+Kubernetes has a [Certificate Signing Requests API],
+and a [`kubectl certificates` command] which allows you to approve certificate signing requests
+and have them signed by the certificate authority (CA) of the Kubernetes cluster.
+
+This API and CLI have occasionally been misused to sign certificates for use by non-control-plane Pods but this is a mistake.
+For the security of the Kubernetes cluster, it is important to limit access to the Kubernetes certificate authority,
+and it is important that you do not use that certificate authority to sign certificates which are used outside of the control-plane,
+because such certificates increase the opportunity for attacks on the Kubernetes API server.
+
+In Kubernetes 1.19 the [Certificate Signing Requests API] has reached V1
+and it can be used more generally by following (or automating) the [Request Signing Process].
+
+cert-manager currently has some [limited experimental support] for this resource.
+
+[Certificate Signing Requests API]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#certificatesigningrequest-v1-certificates-k8s-io
+[`kubectl certificates` command]: https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#certificate
+[Request signing process]: https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#request-signing-process
+[limited experimental support]: ../usage/kube-csr.md
+
+### How to write "cert-manager"
+
+cert-manager should always be written in lowercase. Even when it would normally be
+capitalized such as in titles or at the start of sentences. A hyphen should always be
+used between the words, don't replace it with a space and don't remove it.
diff --git a/content/v1.12-docs/getting-started/README.md b/content/v1.12-docs/getting-started/README.md
new file mode 100644
index 0000000000..c358360f49
--- /dev/null
+++ b/content/v1.12-docs/getting-started/README.md
@@ -0,0 +1,36 @@
+---
+title: Getting Started with cert-manager
+description: Quick start guides for cert-manager
+---
+
+
+
+ Learn how to deploy cert-manager and how to configure it to get certificates for the **NGINX Ingress controller** from **Let's Encrypt**.
+
+
+
+
+
+ Learn how to deploy cert-manager on **Google Kubernetes Engine** and how to configure it to get certificates for Ingress, from **Let's Encrypt**.
+
+
+
+
+
+ Learn how to deploy cert-manager on **Azure Kubernetes Service (AKS)** and how to configure it to get certificates for an HTTPS web server, from **Let's Encrypt**.
+
diff --git a/content/v1.12-docs/installation/README.md b/content/v1.12-docs/installation/README.md
new file mode 100644
index 0000000000..4bcccf6ee9
--- /dev/null
+++ b/content/v1.12-docs/installation/README.md
@@ -0,0 +1,41 @@
+---
+title: Installation
+description: Learn about the various ways you can install cert-manager and how to choose between them
+---
+
+Learn about the various ways you can install cert-manager and how to choose between them.
+
+## Default static install
+
+> You don't require any tweaking of the cert-manager install parameters.
+
+The default static configuration can be installed as follows:
+
+```bash
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.6/cert-manager.yaml
+```
+
+📖 Read more about [installing cert-manager using kubectl apply and static manifests](./kubectl.md).
+
+## Getting started
+
+> You quickly want to learn how to use cert-manager and what it can be used for.
+
+📖 **kubectl apply**: For new users we recommend [installing cert-manager using kubectl apply and static manifests](./kubectl.md).
+
+📖 **helm**: You can [use helm to install cert-manager](./helm.md) and this also allows you to customize the installation if necessary.
+
+📖 **OperatorHub**: If you have an OpenShift cluster, consider [installing cert-manager via OperatorHub](./operator-lifecycle-manager.md),
+which you can do from the OpenShift web console.
+
+🚧 **cmctl**: Try the [experimental `cmctl x install` command](../reference/cmctl.md#install) to quickly install cert-manager.
+
+## Continuous deployment
+
+> You know how to configure your cert-manager setup and want to automate this.
+
+📖 **helm**: You can use [the cert-manager Helm chart](./helm.md) directly with systems like Flux, ArgoCD and Anthos.
+
+📖 **helm template**: You can use `helm template` to generate customized cert-manager installation manifests.
+See [Output YAML using helm template](./helm.md#output-yaml) for more details.
+This templated cert-manager manifest can be piped into your preferred deployment tool.
diff --git a/content/docs/installation/api-compatibility.md b/content/v1.12-docs/installation/api-compatibility.md
similarity index 100%
rename from content/docs/installation/api-compatibility.md
rename to content/v1.12-docs/installation/api-compatibility.md
diff --git a/content/v1.12-docs/installation/best-practice.md b/content/v1.12-docs/installation/best-practice.md
new file mode 100644
index 0000000000..23f5ca984a
--- /dev/null
+++ b/content/v1.12-docs/installation/best-practice.md
@@ -0,0 +1,48 @@
+---
+title: Best Practice
+description: Learn how to deploy cert-manager to comply with popular security standards such as those produced by the CIS, NSA, and BSI.
+---
+
+Learn how to deploy cert-manager to comply with popular security standards such as
+the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/),
+the [NSA Kubernetes Hardening Guide](https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF), or
+the [BSI Kubernetes Security Recommendations](https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Grundschutz/International/bsi_it_gs_comp_2022.pdf?__blob=publicationFile&v=2#page=475).
+
+## Overview
+
+The default cert-manager resources in the Helm chart or YAML manifests (Deployment, Pod, ServiceAccount etc) are designed for backwards compatibility rather than for best practice or maximum security.
+You may find that the default resources do not comply with the security policy on your Kubernetes cluster
+and in that case you can modify the installation configuration using Helm chart values to override the defaults.
+
+## Restrict Auto-Mount of Service Account Tokens
+
+This recommendation is described in the [Kyverno Policy Catalogue](https://kyverno.io/policies/other/res/restrict-automount-sa-token/restrict-automount-sa-token/) as follows:
+> Kubernetes automatically mounts ServiceAccount credentials in each Pod. The
+> ServiceAccount may be assigned roles allowing Pods to access API resources.
+> Blocking this ability is an extension of the least privilege best practice and
+> should be followed if Pods do not need to speak to the API server to function.
+> This policy ensures that mounting of these ServiceAccount tokens is blocked
+
+The cert-manager components *do* need to speak to the API server but we still recommend setting `automountServiceAccountToken: false` for the following reasons:
+1. Setting `automountServiceAccountToken: false` will allow cert-manager to be installed on clusters where Kyverno (or some other policy system) is configured to deny Pods that have this field set to `true`. The Kubernetes default value is `true`.
+2. With `automountServiceAccountToken: true`, *all* the containers in the Pod will mount the ServiceAccount token, including side-car and init containers that might have been injected into the cert-manager Pod resources by Kubernetes admission controllers.
+ The principle of least privilege suggests that it is better to explicitly mount the ServiceAccount token into the cert-manager containers.
+
+So it is recommended to set `automountServiceAccountToken: false` and manually add a projected `Volume` to each of the cert-manager Deployment resources, containing the ServiceAccount token, CA certificate and namespace files that would normally be [added automatically by the Kubernetes ServiceAccount controller](https://github.com/kubernetes/kubernetes/blob/3992eda8e61725c470fb6141a7fe4e7f9ee31ea5/plugin/pkg/admission/serviceaccount/admission.go#L421-L460),
+and to explicitly add a read-only `VolumeMount` to each of the cert-manager containers.
+
+An example of this configuration is included in the Helm Chart Values file below.
+
+## Best Practice Helm Chart Values
+
+Download the following Helm chart values file and supply it to `helm install`, `helm upgrade`, or `helm template` using the `--values` flag:
+
+🔗 `values.best-practice.yaml`
+```yaml file=../../../public/docs/installation/best-practice/values.best-practice.yaml
+```
+
+## Other
+
+This list of recommendations is a work-in-progress.
+If you have other best practice recommendations please [contribute to this page](../contributing/contributing-flow.md).
+
diff --git a/content/v1.12-docs/installation/code-signing.md b/content/v1.12-docs/installation/code-signing.md
new file mode 100644
index 0000000000..f85017b877
--- /dev/null
+++ b/content/v1.12-docs/installation/code-signing.md
@@ -0,0 +1,59 @@
+---
+title: cert-manager Signature Verification
+description: 'cert-manager installation: Code signing'
+---
+
+To help prevent [supply chain attacks](https://en.wikipedia.org/wiki/Supply_chain_attack), some cert-manager release
+artifacts are cryptographically signed so you can be sure that the version of cert-manager you're about to install
+is actually built by and provided by the cert-manager maintainers.
+
+This signing is vitally important if for any reason you need to use a mirrored version of cert-manager; it allows you
+to confirm that the mirror hasn't tampered with the code you're about to install.
+
+Signing keys required for verification are all available on this website, but the actual key that you need might depend
+on the artifact you're trying to validate in the future. At the time of writing, all signing is done using the same underlying
+key.
+
+## Container Images / Cosign
+
+For all cert-manager versions from `v1.8.0` and later, cert-manager container images are signed and verifiable using [`cosign`](https://docs.sigstore.dev/cosign/overview).
+
+The simplest way to verify signatures is to download the public key and then pass it to the cosign CLI directly:
+
+```console
+curl -sSOL https://cert-manager.io/public-keys/cert-manager-pubkey-2021-09-20.pem
+IMAGE_TAG=v1.12.6 # change as needed
+cosign verify --signature-digest-algorithm sha512 --key cert-manager-pubkey-2021-09-20.pem quay.io/jetstack/cert-manager-acmesolver:$IMAGE_TAG
+cosign verify --signature-digest-algorithm sha512 --key cert-manager-pubkey-2021-09-20.pem quay.io/jetstack/cert-manager-cainjector:$IMAGE_TAG
+cosign verify --signature-digest-algorithm sha512 --key cert-manager-pubkey-2021-09-20.pem quay.io/jetstack/cert-manager-ctl:$IMAGE_TAG
+cosign verify --signature-digest-algorithm sha512 --key cert-manager-pubkey-2021-09-20.pem quay.io/jetstack/cert-manager-controller:$IMAGE_TAG
+cosign verify --signature-digest-algorithm sha512 --key cert-manager-pubkey-2021-09-20.pem quay.io/jetstack/cert-manager-webhook:$IMAGE_TAG
+```
+
+For a more fully-featured signature verification process in Kubernetes, check out [`connaisseur`](https://sse-secure-systems.github.io/connaisseur/).
+
+- PEM-encoded public key: [`cert-manager-pubkey-2021-09-20.pem`](https://cert-manager.io/public-keys/cert-manager-pubkey-2021-09-20.pem)
+
+## Helm Charts
+
+
+Helm requires the use of PGP for verification; the key format is different.
+
+Trying to use "plain" PEM encoded public keys during verification will fail.
+
+
+For all cert-manager versions from `v1.6.0` and later, Helm charts are signed and verifiable through the Helm CLI.
+
+The easiest way to verify is to grab the GPG keyring directly, which can then be passed into `helm verify` like so:
+
+```console
+curl -sSL https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg > cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg
+helm verify --keyring cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg /path/to/cert-manager-vx.y.z.tgz
+```
+
+- GPG keyring: [`cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg`](https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg)
+
+If you know what you're doing and you want the signing key in a format that's easy to import into GPG,
+it's available in an ASCII armored version:
+
+- ASCII-armored signing key: [`cert-manager-pgp-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.asc`](https://cert-manager.io/public-keys/cert-manager-pgp-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.asc)
diff --git a/content/v1.12-docs/installation/compatibility.md b/content/v1.12-docs/installation/compatibility.md
new file mode 100644
index 0000000000..516bc941a0
--- /dev/null
+++ b/content/v1.12-docs/installation/compatibility.md
@@ -0,0 +1,114 @@
+---
+title: Compatibility with Kubernetes Platform Providers
+description: 'cert-manager installation: Cloud provider compatibility'
+---
+
+Below you will find details on various compatibility issues and quirks that you
+may be affected by when deploying cert-manager. If you believe we've missed something
+please feel free to raise an issue or a pull request with the details!
+
+
+If you're using AWS Fargate or else if you've specifically configured
+cert-manager to run the host's network, be aware that kubelet listens on port
+`10250` by default which clashes with the default port for the cert-manager
+webhook.
+
+As such, you'll need to change the webhook's port when setting up cert-manager.
+
+For installations using Helm, you can set the `webhook.securePort` parameter
+when installing cert-manager either using a command line flag or an entry in
+your `values.yaml` file.
+
+If you have a port clash, you could see confusing error messages regarding
+untrusted certs. See [#3237](https://github.com/cert-manager/cert-manager/issues/3237)
+for more details.
+
+
+## GKE
+
+When Google configure the control plane for private clusters, they automatically
+configure VPC peering between your Kubernetes cluster's network and a separate
+Google-managed project.
+
+In order to restrict what Google are able to access within your cluster, the
+firewall rules configured restrict access to your Kubernetes pods. This means
+that the webhook won't work, and you'll see errors such as
+`Internal error occurred: failed calling admission webhook ... the server is
+currently unable to handle the request`.
+
+In order to use the webhook component with a GKE private cluster, you must
+configure an additional firewall rule to allow the GKE control plane access to
+your webhook pod.
+
+You can read more information on how to add firewall rules for the GKE control
+plane nodes in the [GKE
+docs](https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters#add_firewall_rules).
+
+
+### GKE Autopilot
+
+GKE Autopilot mode with Kubernetes < 1.21 does not support cert-manager,
+due to a [restriction on mutating admission webhooks](https://github.com/cert-manager/cert-manager/issues/3717).
+
+As of October 2021, only the "rapid" Autopilot release channel has rolled
+out version 1.21 for Kubernetes masters. Installation via the helm chart
+may end in an error message but cert-manager is reported to be working by
+some users. Feedback and PRs are welcome.
+
+**Problem**: GKE Autopilot does not allow modifications to the `kube-system`-namespace.
+
+Historically we've used the `kube-system` namespace to prevent multiple installations of cert-manager in the same cluster.
+
+Installing cert-manager in these environments with default configuration can cause issues with bootstrapping.
+Some signals are:
+
+* `cert-manager-cainjector` logging errors like:
+
+```text
+E0425 09:04:01.520150 1 leaderelection.go:334] error initially creating leader election record: leases.coordination.k8s.io is forbidden: User "system:serviceaccount:cert-manager:cert-manager-cainjector" cannot create resource "leases" in API group "coordination.k8s.io" in the namespace "kube-system": GKEAutopilot authz: the namespace "kube-system" is managed and the request's verb "create" is denied
+```
+
+* `cert-manager-startupapicheck` not completing and logging messages like:
+
+```text
+Not ready: the cert-manager webhook CA bundle is not injected yet
+```
+
+**Solution**: Configure cert-manager to use a different namespace for leader election, like this:
+
+```console
+helm install \
+ cert-manager jetstack/cert-manager \
+ --namespace cert-manager \
+ --create-namespace \
+ --version ${CERT_MANAGER_VERSION} --set global.leaderElection.namespace=cert-manager
+```
+
+The implication for a `kubectl apply` type installation is then either "you must manually update the manifests prior to installation by replacing `kube-system` with cert-manager" or "Don't install cert-manager using kubectl apply. Helm is the recommended solution".
+
+## AWS EKS
+
+When using a custom CNI (such as Weave or Calico) on EKS, the webhook cannot be
+reached by cert-manager. This happens because the control plane cannot be
+configured to run on a custom CNI on EKS, so the CNIs differ between control
+plane and worker nodes.
+
+To address this, the webhook can be run in the host network so it can be reached
+by cert-manager, by setting the `webhook.hostNetwork` key to true on your
+deployment, or, if using Helm, configuring it in your `values.yaml` file.
+
+Note that running on the host network will necessitate changing the webhook's
+port; see the warning at the top of the page for details.
+
+### AWS Fargate
+
+It's worth noting that using AWS Fargate doesn't allow much network configuration and
+will cause the webhook's port to clash with the kubelet running on port 10250, as seen
+in [#3237](https://github.com/cert-manager/cert-manager/issues/3237).
+
+When deploying cert-manager on Fargate, you _must_ change the port on which
+the webhook listens. See the warning at the top of this page for more details.
+
+Because Fargate forces you to use its networking, you cannot manually set the networking
+type and options such as `webhook.hostNetwork` on the helm chart will cause your
+cert-manager deployment to fail in surprising ways.
diff --git a/content/docs/installation/featureflags.md b/content/v1.12-docs/installation/featureflags.md
similarity index 98%
rename from content/docs/installation/featureflags.md
rename to content/v1.12-docs/installation/featureflags.md
index 10548df563..65ce69a027 100644
--- a/content/docs/installation/featureflags.md
+++ b/content/v1.12-docs/installation/featureflags.md
@@ -62,7 +62,7 @@ See `--feature-gates` flags on cert-manager controller and webhook to enable any
- `StableCertificateRequestName`. Added in cert-manager 1.10.0. Will enable generation of `CertificateRequest` resources with a fixed name. See [`cert-manager#5487`](https://github.com/cert-manager/cert-manager/pull/5487)
-- `UseCertificateRequestBasicConstraints`. Added in cert-manager 1.11.0. Makes cert-manager add a basic constraints section to certificate signing requests with the CA constraint set to the correct value. See [`cert-manager#5552`](https://github.com/cert-manager/cert-manager/pull/5552)
+- `UseCertificateRequestBasicConstraints`. Added in cert-manager 1.12.0. Makes cert-manager add a basic constraints section to certificate signing requests with the CA constraint set to the correct value. See [`cert-manager#5552`](https://github.com/cert-manager/cert-manager/pull/5552)
- `ValidateCAA`. Added in cert-manager 0.7.2. CAA checking when issuing a certificate.
diff --git a/content/v1.12-docs/installation/helm.md b/content/v1.12-docs/installation/helm.md
new file mode 100644
index 0000000000..64845005c1
--- /dev/null
+++ b/content/v1.12-docs/installation/helm.md
@@ -0,0 +1,207 @@
+---
+title: Helm
+description: 'cert-manager installation: Using Helm'
+---
+
+## Installing with Helm
+
+cert-manager provides Helm charts as a first-class method of installation on both Kubernetes and OpenShift.
+
+Be sure never to embed cert-manager as a sub-chart of other Helm charts; cert-manager manages
+non-namespaced resources in your cluster and care must be taken to ensure that it is installed exactly once.
+
+### Prerequisites
+
+- [Install Helm version 3 or later](https://helm.sh/docs/intro/install/).
+- Install a [supported version of Kubernetes or OpenShift](./supported-releases.md).
+- Read [Compatibility with Kubernetes Platform Providers](./compatibility.md) if you are using Kubernetes on a cloud platform.
+
+### Steps
+
+
+#### 1. Add the Helm repository
+
+This repository is the only supported source of cert-manager charts. There are some other mirrors and copies across the internet, but those are entirely unofficial and could present a security risk.
+
+Notably, the "Helm stable repository" version of cert-manager is deprecated and should not be used.
+
+```bash
+helm repo add jetstack https://charts.jetstack.io
+```
+
+#### 2. Update your local Helm chart repository cache:
+
+```bash
+helm repo update
+```
+
+#### 3. Install `CustomResourceDefinitions`
+
+cert-manager requires a number of CRD resources, which can be installed manually using `kubectl`,
+or using the `installCRDs` option when installing the Helm chart.
+
+##### Option 1: installing CRDs with `kubectl`
+
+
+```bash
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.6/cert-manager.crds.yaml
+```
+
+##### Option 2: install CRDs as part of the Helm release
+
+To automatically install and manage the CRDs as part of your Helm release, you
+must add the `--set installCRDs=true` flag to your Helm installation command.
+
+Uncomment the relevant line in the next steps to enable this.
+
+Note that if you're using a `helm` version based on Kubernetes `v1.18` or below (Helm `v3.2`), `installCRDs` will not work with cert-manager `v0.16`. See the [v0.16 upgrade notes](./upgrading/upgrading-0.15-0.16.md#helm) for more details.
+
+#### 4. Install cert-manager
+
+To install the cert-manager Helm chart, use the [Helm install command](https://helm.sh/docs/helm/helm_install/) as described below.
+
+```bash
+helm install \
+ cert-manager jetstack/cert-manager \
+ --namespace cert-manager \
+ --create-namespace \
+ --version v1.12.6 \
+ # --set installCRDs=true
+```
+
+A full list of available Helm values is on [cert-manager's ArtifactHub page](https://artifacthub.io/packages/helm/cert-manager/cert-manager).
+
+The example below shows how to tune the cert-manager installation by overwriting the default Helm values:
+
+```bash
+helm install \
+ cert-manager jetstack/cert-manager \
+ --namespace cert-manager \
+ --create-namespace \
+ --version v1.12.6 \
+ # --set installCRDs=true
+ --set prometheus.enabled=false \ # Example: disabling prometheus using a Helm parameter
+ --set webhook.timeoutSeconds=4 # Example: changing the webhook timeout using a Helm parameter
+```
+
+Once you have deployed cert-manager, you can [verify](./verify.md) the installation.
+
+### Installing cert-manager as subchart
+
+If you have configured cert-manager as a subchart all the components of cert-manager will be installed into the namespace of the helm release you are installing.
+
+There may be a situation where you want to specify the namespace to install cert-manager different to the umbrella chart's namespace.
+
+This is a [known issue](https://github.com/helm/helm/issues/5358) with helm and subcharts, that you can't specify the namespace for the subchart and is being solved by most public charts by allowing users to set the namespace via the values file, but needs to be a capability added to the chart by the maintainers.
+
+This capability is now available in the cert-manager chart and can be set either in the values file or via the `--set` switch.
+
+#### Example usage
+
+Below is an example `Chart.yaml` with cert-manager as a subchart
+
+```yaml
+apiVersion: v2
+name: example_chart
+description: A Helm chart with cert-manager as subchart
+type: application
+version: 0.1.0
+appVersion: "0.1.0"
+dependencies:
+ - name: cert-manager
+ version: v1.12.6
+ repository: https://charts.jetstack.io
+ alias: cert-manager
+ condition: cert-manager.enabled
+```
+You can then override the namespace in 2 ways
+1. In `Values.yaml` file
+```yaml
+cert-manager: #defined by either the name or alias of your dependency in Chart.yaml
+ namespace: security
+```
+2. In the helm command using `--set`
+```bash
+helm install example example_chart \
+ --namespace example \
+ --create-namespace \
+ --set cert-manager.namespace=security
+```
+
+The above example will install cert-manager into the security namespace.
+
+## Output YAML
+
+Instead of directly installing cert-manager using Helm, a static YAML manifest can be created using the [Helm template command](https://helm.sh/docs/helm/helm_template/).
+This static manifest can be tuned by providing the flags to overwrite the default Helm values:
+
+```bash
+helm template \
+ cert-manager jetstack/cert-manager \
+ --namespace cert-manager \
+ --create-namespace \
+ --version v1.12.6 \
+ # --set prometheus.enabled=false \ # Example: disabling prometheus using a Helm parameter
+ # --set installCRDs=true \ # Uncomment to also template CRDs
+ > cert-manager.custom.yaml
+```
+
+## Uninstalling
+
+> **Warning**: To uninstall cert-manager you should always use the same process for
+> installing but in reverse. Deviating from the following process whether
+> cert-manager has been installed from static manifests or Helm can cause issues
+> and potentially broken states. Please ensure you follow the below steps when
+> uninstalling to prevent this happening.
+
+Before continuing, ensure that all cert-manager resources that have been created
+by users have been deleted. You can check for any existing resources with the
+following command:
+
+```bash
+kubectl get Issuers,ClusterIssuers,Certificates,CertificateRequests,Orders,Challenges --all-namespaces
+```
+
+Once all these resources have been deleted you are ready to uninstall
+cert-manager using the procedure determined by how you installed.
+
+### Uninstalling with Helm
+
+Uninstalling cert-manager from a `helm` installation is a case of running the
+installation process, *in reverse*, using the delete command on both `kubectl`
+and `helm`.
+
+
+```bash
+helm --namespace cert-manager delete cert-manager
+```
+
+Next, delete the cert-manager namespace:
+
+```bash
+kubectl delete namespace cert-manager
+```
+
+Finally, delete the cert-manager
+[`CustomResourceDefinitions`](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
+using the link to the version `vX.Y.Z` you installed:
+> **Warning**: This command will also remove installed cert-manager CRDs. All
+> cert-manager resources (e.g. `certificates.cert-manager.io` resources) will
+> be removed by Kubernetes' garbage collector.
+
+```bash
+kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/vX.Y.Z/cert-manager.crds.yaml
+```
+
+### Namespace Stuck in Terminating State
+
+If the namespace has been marked for deletion without deleting the cert-manager
+installation first, the namespace may become stuck in a terminating state. This
+is typically due to the fact that the [`APIService`](https://kubernetes.io/docs/tasks/access-kubernetes-api/setup-extension-api-server) resource still exists
+however the webhook is no longer running so is no longer reachable. To resolve
+this, ensure you have run the above commands correctly, and if you're still
+experiencing issues then run:
+
+```bash
+kubectl delete apiservice v1beta1.webhook.cert-manager.io
+```
diff --git a/content/v1.12-docs/installation/kubectl.md b/content/v1.12-docs/installation/kubectl.md
new file mode 100644
index 0000000000..f93d6ece06
--- /dev/null
+++ b/content/v1.12-docs/installation/kubectl.md
@@ -0,0 +1,124 @@
+---
+title: kubectl apply
+description: Learn how to install cert-manager using kubectl and static manifests
+---
+
+Learn how to install cert-manager using kubectl and static manifests.
+
+## Prerequisites
+
+- [Install `kubectl` version `>= v1.19.0`](https://kubernetes.io/docs/tasks/tools/). (otherwise, you'll have issues updating the CRDs - see [v0.16 upgrade notes](./upgrading/upgrading-0.15-0.16.md#issue-with-older-versions-of-kubectl))
+- Install a [supported version of Kubernetes or OpenShift](./supported-releases.md).
+- Read [Compatibility with Kubernetes Platform Providers](./compatibility.md) if you are using Kubernetes on a cloud platform.
+
+## Steps
+
+All resources (the [`CustomResourceDefinitions`](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions) and the cert-manager, cainjector and webhook components)
+are included in a single YAML manifest file:
+
+Install all cert-manager components:
+
+```bash
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.6/cert-manager.yaml
+```
+
+By default, cert-manager will be installed into the `cert-manager`
+namespace. It is possible to run cert-manager in a different namespace, although
+you'll need to make modifications to the deployment manifests.
+
+Once you have deployed cert-manager, you can [verify the installation](./verify.md).
+
+## Permissions Errors on Google Kubernetes Engine
+
+When running on GKE (Google Kubernetes Engine), you might encounter a 'permission denied' error when creating some
+of the required resources. This is a nuance of the way GKE handles RBAC and IAM permissions,
+and as such you might need to elevate your own privileges to that of a "cluster-admin" **before**
+running `kubectl apply`.
+
+If you have already run `kubectl apply`, you should run it again after elevating your permissions:
+
+```bash
+kubectl create clusterrolebinding cluster-admin-binding \
+ --clusterrole=cluster-admin \
+ --user=$(gcloud config get-value core/account)
+```
+
+## Uninstalling
+> **Warning**: To uninstall cert-manager you should always use the same process for
+> installing but in reverse. Deviating from the following process whether
+> cert-manager has been installed from static manifests or Helm can cause issues
+> and potentially broken states. Please ensure you follow the below steps when
+> uninstalling to prevent this happening.
+
+Before continuing, ensure that unwanted cert-manager resources that have been created
+by users have been deleted. You can check for any existing resources with the
+following command:
+
+```bash
+kubectl get Issuers,ClusterIssuers,Certificates,CertificateRequests,Orders,Challenges --all-namespaces
+```
+It is recommended that you delete all these resources before uninstalling cert-manager.
+If you plan on reinstalling later and don't want to lose some custom resources, you can keep them.
+However, this can potentially lead to problems with finalizers. Some resources, like
+`Challenges`, should be deleted to avoid [getting stuck in a pending state](#namespace-stuck-in-terminating-state).
+
+Once the unneeded resources have been deleted, you are ready to uninstall
+cert-manager using the procedure determined by how you installed.
+
+> **Warning**: Uninstalling cert-manager or simply deleting a `Certificate` resource can result in
+> TLS `Secret`s being deleted if they have `metadata.ownerReferences` set by cert-manager.
+> You can control whether owner references are added to `Secret`s using the `--enable-certificate-owner-ref` controller flag.
+> By default, this flag is set to false, which means that no owner references are added.
+> However, in cert-manager v1.8 and older, changing the flag's value from true to false _did not_
+> result in existing owner references being removed. This behavior was fixed in cert-manager v1.8.
+> Do check the owner references to confirm that they actually are removed.
+
+### Uninstalling with regular manifests
+
+Uninstalling from an installation with regular manifests is a case of running
+the installation process, *in reverse*, using the delete command of `kubectl`.
+
+Delete the installation manifests using a link to your currently running version
+`vX.Y.Z` like so:
+> **Warning**: This command will also remove installed cert-manager CRDs. All
+> cert-manager resources (e.g. `certificates.cert-manager.io` resources) will
+> be removed by Kubernetes' garbage collector.
+> You cannot keep any custom resources if you delete the `CustomResourceDefinition`s.
+> If you want to keep resources, you should manage `CustomResourceDefinition`s separately.
+
+```bash
+kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/vX.Y.Z/cert-manager.yaml
+```
+
+### Namespace Stuck in Terminating State
+
+If the namespace has been marked for deletion without deleting the cert-manager
+installation first, the namespace may become stuck in a terminating state. This
+is typically due to the fact that the [`APIService`](https://kubernetes.io/docs/tasks/access-kubernetes-api/setup-extension-api-server) resource still exists
+however the webhook is no longer running so is no longer reachable. To resolve
+this, ensure you have run the above commands correctly, and if you're still
+experiencing issues then run:
+
+```bash
+kubectl delete apiservice v1beta1.webhook.cert-manager.io
+```
+
+#### Deleting pending challenges
+
+`Challenge`s can get stuck in a pending state when the finalizer is unable to complete
+and Kubernetes is waiting for the cert-manager controller to finish.
+This happens when the controller is no longer running to remove the flag,
+and the resources are defined as needing to wait.
+You can fix this problem by doing what the controller does manually.
+
+First, delete existing cert-manager webhook configurations, if any:
+
+```bash
+kubectl delete mutatingwebhookconfigurations cert-manager-webhook
+```
+
+Then change the `.metadata.finalizers` field to an empty list by editing the challenge resource:
+
+```bash
+kubectl edit challenge
+```
diff --git a/content/v1.12-docs/installation/operator-lifecycle-manager.md b/content/v1.12-docs/installation/operator-lifecycle-manager.md
new file mode 100644
index 0000000000..c24591a385
--- /dev/null
+++ b/content/v1.12-docs/installation/operator-lifecycle-manager.md
@@ -0,0 +1,243 @@
+---
+title: Operator Lifecycle Manager
+description: 'cert-manager installation: Using OLM'
+---
+
+## Installation managed by OLM
+
+### Prerequisites
+
+- Install a [supported version of Kubernetes or OpenShift](./supported-releases.md).
+- Read [Compatibility with Kubernetes Platform Providers](./compatibility.md) if you are using Kubernetes on a cloud platform.
+
+### Option 1: Installing from OperatorHub Web Console on OpenShift
+
+cert-manager is in the [Red Hat-provided Operator catalog][] called "community-operators".
+On OpenShift 4 you can install cert-manager from the [OperatorHub web console][] or from the command line.
+These installation methods are described in Red Hat's [Adding Operators to a cluster][] documentation.
+
+> ⚠️ In cert-manager 1.10 the [secure computing (seccomp) profile](https://kubernetes.io/docs/tutorials/security/seccomp/) for all the Pods
+> is set to `RuntimeDefault`.
+> On some versions and configurations of OpenShift this can cause the Pod to be rejected by the
+> [Security Context Constraints admission webhook](https://docs.openshift.com/container-platform/4.10/authentication/managing-security-context-constraints.html#admission_configuring-internal-oauth).
+>
+> 📖 Read the [Breaking Changes section in the 1.10 release notes](https://cert-manager.io/docs/release-notes/release-notes-1.10/#on-openshift-the-cert-manager-pods-may-fail-until-you-modify-security-context-constraints) before installing or upgrading from an older version to 1.10 or newer.
+
+[Red Hat-provided Operator catalog]: https://docs.openshift.com/container-platform/4.7/operators/understanding/olm-rh-catalogs.html#olm-rh-catalogs_olm-rh-catalogs
+[OperatorHub web console]: https://docs.openshift.com/container-platform/4.7/operators/understanding/olm-understanding-operatorhub.html
+[Adding Operators to a cluster]: https://docs.openshift.com/container-platform/4.7/operators/admin/olm-adding-operators-to-cluster.html
+
+
+### Option 2: Installing from OperatorHub.io
+
+Browse to the [cert-manager page on OperatorHub.io](https://operatorhub.io/operator/cert-manager),
+click the "Install" button and follow the installation instructions.
+
+### Option 3: Manual install via `kubectl operator` plugin
+
+[Install OLM][] and [install the `kubectl operator` plugin][]
+from the [Krew Kubectl plugins index][] and then use that to install the cert-manager as follows:
+
+```sh
+operator-sdk olm install
+kubectl krew install operator
+kubectl operator install cert-manager -n operators --channel stable --approval Automatic
+```
+
+You can monitor the progress of the installation as follows:
+
+```sh
+kubectl get events -w -n operators
+```
+
+And you can see the status of the installation with:
+
+```sh
+kubectl operator list
+```
+
+[install OLM]: https://sdk.operatorframework.io/docs/installation/
+[install the `kubectl operator` plugin]: https://github.com/operator-framework/kubectl-operator#install
+[Krew Kubectl plugins index]: https://krew.sigs.k8s.io/plugins/#:~:text=cert-manager
+
+## Release Channels
+
+Whichever installation method you chose, there will now be an [OLM Subscription resource][] for cert-manager,
+tracking the "stable" release channel. E.g.
+
+```console
+$ kubectl get subscription cert-manager -n operators -o yaml
+...
+spec:
+ channel: stable
+ installPlanApproval: Automatic
+ name: cert-manager
+...
+status:
+ currentCSV: cert-manager.v1.7.1
+ state: AtLatestKnown
+...
+```
+
+This means that OLM will discover new cert-manager releases in the stable channel,
+and, depending on the Subscription settings it will upgrade cert-manager automatically,
+when new releases become available.
+Read [Manually Approving Upgrades via Subscriptions][] for information about automatic and manual upgrades.
+
+[OLM Subscription resource]: https://olm.operatorframework.io/docs/concepts/crds/subscription/
+[Manually Approving Upgrades via Subscriptions]: https://olm.operatorframework.io/docs/concepts/crds/subscription/#manually-approving-upgrades-via-subscriptions
+
+**NOTE:** There is a single release channel called "stable" which will contain all cert-manager releases, shortly after they are released.
+In future we may introduce other release channels with alternative release schedules,
+in accordance with [OLM's Recommended Channel Naming][].
+
+[OLM's Recommended Channel Naming]: https://olm.operatorframework.io/docs/best-practices/channel-naming/#recommended-channel-naming
+
+## Debugging installation issues
+
+If you have any issues with your installation, please refer to the
+[FAQ](../faq/README.md).
+
+## Configuration
+
+The configuration options are quite limited when you install cert-manager using OLM.
+There are a few Deployment settings which can be overridden permanently in the Subscription
+and most other elements of the cert-manager manifests can be changed by editing the ClusterServiceVersion,
+but changes to the ClusterServiceVersion are temporary and will be lost if OLM upgrades cert-manager,
+because an upgrade results in a new ClusterServiceVersion resource.
+
+### Configuration Via Subscription
+
+When you create an OLM Subscription you can override **some** of the cert-manager Deployment settings,
+but the options are quite limited.
+The configuration which you add to the Subscription will be applied immediately to the current cert-manager Deployments.
+It will also be re-applied if OLM upgrades cert-manager.
+
+> 🔰 Read the [Configuring Operators deployed by OLM](https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/subscription-config.md#configuring-operators-deployed-by-olm) design doc in the OLM repository.
+>
+> 🔰 Refer to the [Subscription API documentation](https://pkg.go.dev/github.com/operator-framework/api@v0.14.0/pkg/operators/v1alpha1#Subscription).
+
+Here are some examples of configuration that can be achieved by modifying the Subscription resource.
+In each case we assume that you are starting with the following [default Subscription from OperatorHub.io](https://operatorhub.io/install/cert-manager.yaml):
+
+```yaml
+# cert-manager.yaml
+apiVersion: operators.coreos.com/v1alpha1
+kind: Subscription
+metadata:
+ name: my-cert-manager
+ namespace: operators
+spec:
+ channel: stable
+ name: cert-manager
+ source: operatorhubio-catalog
+ sourceNamespace: olm
+```
+
+```bash
+kubectl create -f https://operatorhub.io/install/cert-manager.yaml
+```
+
+#### Change the Resource Requests and Limits
+
+It is possible to change the resource requests and limits by adding a `config` stanza to the Subscription:
+
+```yaml
+# resources-patch.yaml
+spec:
+ config:
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "250m"
+ limits:
+ memory: "128Mi"
+ cpu: "500m"
+```
+
+
+```bash
+kubectl -n operators patch subscription my-cert-manager --type merge --patch-file resources-patch.yaml
+```
+
+You will see **all** the cert-manager Pods are restarted with the new resources:
+
+```console
+$ kubectl -n operators get pods -o "custom-columns=name:.metadata.name,mem:.spec.containers[*].resources"
+name mem
+cert-manager-669867589c-n8dcn map[limits:map[cpu:500m memory:128Mi] requests:map[cpu:250m memory:100Mi]]
+cert-manager-cainjector-7b7fff8b9c-dxw6b map[limits:map[cpu:500m memory:128Mi] requests:map[cpu:250m memory:100Mi]]
+cert-manager-webhook-975bc87b5-tqdj4 map[limits:map[cpu:500m memory:128Mi] requests:map[cpu:250m memory:100Mi]]
+```
+
+> ⚠️ This configuration will apply to **all** the cert-manager Deployments.
+> This is a known limitation of OLM which [does not support configuration of individual Deployments](https://github.com/operator-framework/operator-lifecycle-manager/issues/1794).
+
+#### Change the NodeSelector
+
+It is possible to change the `nodeSelector` for cert-manager Pods by adding the following stanza to the Subscription:
+
+```yaml
+# nodeselector-patch.yaml
+spec:
+ config:
+ nodeSelector:
+ kubernetes.io/arch: amd64
+```
+
+```bash
+kubectl -n operators patch subscription my-cert-manager --type merge --patch-file nodeselector-patch.yaml
+```
+
+You will see **all** the cert-manager Pods are restarted with the new `nodeSelector`:
+
+```console
+$ kubectl -n operators get pods -o "custom-columns=name:.metadata.name,nodeselector:.spec.nodeSelector"
+name nodeselector
+cert-manager-5b6b8f7d74-k7l94 map[kubernetes.io/arch:amd64 kubernetes.io/os:linux]
+cert-manager-cainjector-b89cd6f46-kdkk2 map[kubernetes.io/arch:amd64 kubernetes.io/os:linux]
+cert-manager-webhook-8464bc7cc8-64b4w map[kubernetes.io/arch:amd64 kubernetes.io/os:linux]
+```
+
+> ⚠️ This configuration will apply to **all** the cert-manager Deployments.
+> This is a known limitation of OLM which [does not support configuration of individual Deployments](https://github.com/operator-framework/operator-lifecycle-manager/issues/1794).
+
+### Configuration Via ClusterServiceVersion (CSV)
+
+The ClusterServiceVersion (CSV) resource contains the templates for all the cert-manager Deployments.
+If you patch these templates, OLM will immediately roll out the changes to the Deployments.
+
+> ⚠️ If OLM upgrades cert-manager your changes will be lost because it will create a new CSV with default Deployment templates.
+
+Nevertheless, editing (patching) the CSV can be a useful way to override certain cert-manager settings. An example:
+
+#### Change the log level of cert-manager components
+
+The following JSON patch will append `-v=6` to command line arguments of the cert-manager controller-manager
+(the first container of the first Deployment).
+
+```bash
+kubectl patch csv cert-manager.v1.12.6 \
+ --type json \
+ -p '[{"op": "add", "path": "/spec/install/spec/deployments/0/spec/template/spec/containers/0/args/-", "value": "-v=6" }]'
+```
+
+You will see the controller-manager Pod is restarted with the new arguments.
+
+```console
+$ kubectl -n operators get pods -o "custom-columns=name:.metadata.name,args:.spec.containers[0].args"
+name args
+cert-manager-797979cbdb-g444r [-v=2 --cluster-resource-namespace=$(POD_NAMESPACE) --leader-election-namespace=kube-system -v=6]
+...
+```
+
+> 🔰 Refer to the [ClusterServiceVersion API documentation](https://pkg.go.dev/github.com/operator-framework/api@v0.14.0/pkg/operators/v1alpha1#ClusterServiceVersion).
+
+## Uninstall
+
+Below is the processes for uninstalling cert-manager on OpenShift.
+
+> ⚠️ To uninstall cert-manager you should always use the same process for
+> installing but in reverse. Deviating from the following process can cause
+> issues and potentially broken states. Please ensure you follow the below steps
+> when uninstalling to prevent this happening.
diff --git a/content/docs/installation/other-tools.md b/content/v1.12-docs/installation/other-tools.md
similarity index 100%
rename from content/docs/installation/other-tools.md
rename to content/v1.12-docs/installation/other-tools.md
diff --git a/content/v1.12-docs/installation/uninstall.md b/content/v1.12-docs/installation/uninstall.md
new file mode 100644
index 0000000000..de06fbc9e7
--- /dev/null
+++ b/content/v1.12-docs/installation/uninstall.md
@@ -0,0 +1,14 @@
+---
+title: Uninstall
+description: 'cert-manager installation: Uninstalling cert-manager'
+---
+
+cert-manager supports running on [Kubernetes](https://kubernetes.io) and
+[OpenShift](https://www.openshift.com). The uninstallation process between the
+two platforms is similar. Select the method that was used for installing
+cert-manager to go to the relevant uninstall documentation.
+
+- [kubectl](./kubectl.md#uninstalling)
+- [helm](./helm.md#uninstalling)
+
+If you need to preserve cert-manager custom resources (`Certificate`s, `Issuer`s etc), that are not version controlled or backed up by other means, take a look at our [backup and restore guide](../tutorials/backup.md).
diff --git a/content/docs/installation/verify.md b/content/v1.12-docs/installation/verify.md
similarity index 100%
rename from content/docs/installation/verify.md
rename to content/v1.12-docs/installation/verify.md
diff --git a/content/v1.12-docs/manifest.json b/content/v1.12-docs/manifest.json
new file mode 100644
index 0000000000..4d84895861
--- /dev/null
+++ b/content/v1.12-docs/manifest.json
@@ -0,0 +1,368 @@
+{
+ "routes": [
+ {
+ "title": "cert-manager",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/README.md"
+ },
+ {
+ "title": "Getting Started",
+ "path": "/v1.12-docs/getting-started/README.md"
+ },
+ {
+ "title": "Installation",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/installation/README.md"
+ },
+ {
+ "title": "Cloud Compatibility",
+ "path": "/v1.12-docs/installation/compatibility.md"
+ },
+ {
+ "title": "kubectl apply",
+ "path": "/v1.12-docs/installation/kubectl.md"
+ },
+ {
+ "title": "Helm",
+ "path": "/v1.12-docs/installation/helm.md"
+ },
+ {
+ "title": "OperatorHub (OLM)",
+ "path": "/v1.12-docs/installation/operator-lifecycle-manager.md"
+ },
+ {
+ "title": "Other tools",
+ "path": "/v1.12-docs/installation/other-tools.md"
+ },
+ {
+ "title": "Verifying",
+ "path": "/v1.12-docs/installation/verify.md"
+ },
+ {
+ "title": "Feature flags",
+ "path": "/v1.12-docs/installation/featureflags.md"
+ },
+ {
+ "title": "Uninstall",
+ "path": "/v1.12-docs/installation/uninstall.md"
+ },
+ {
+ "title": "API compatibility",
+ "path": "/v1.12-docs/installation/api-compatibility.md"
+ },
+ {
+ "title": "Signature Verification",
+ "path": "/v1.12-docs/installation/code-signing.md"
+ },
+ {
+ "title": "Best Practice",
+ "path": "/v1.12-docs/installation/best-practice.md"
+ }
+ ]
+ },
+ {
+ "title": "Configuration",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/configuration/README.md"
+ },
+ {
+ "title": "SelfSigned",
+ "path": "/v1.12-docs/configuration/selfsigned.md"
+ },
+ {
+ "title": "CA",
+ "path": "/v1.12-docs/configuration/ca.md"
+ },
+ {
+ "title": "Vault",
+ "path": "/v1.12-docs/configuration/vault.md"
+ },
+ {
+ "title": "Venafi",
+ "path": "/v1.12-docs/configuration/venafi.md"
+ },
+ {
+ "title": "External",
+ "path": "/v1.12-docs/configuration/external.md"
+ },
+ {
+ "title": "ACME",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/configuration/acme/README.md"
+ },
+ {
+ "title": "HTTP01",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/configuration/acme/http01/README.md"
+ },
+ {
+ "title": "External Load Balancer",
+ "path": "/v1.12-docs/configuration/acme/http01/externalloadbalancer.md"
+ }
+ ]
+ },
+ {
+ "title": "DNS01",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/configuration/acme/dns01/README.md"
+ },
+ {
+ "title": "ACMEDNS",
+ "path": "/v1.12-docs/configuration/acme/dns01/acme-dns.md"
+ },
+ {
+ "title": "Akamai",
+ "path": "/v1.12-docs/configuration/acme/dns01/akamai.md"
+ },
+ {
+ "title": "AzureDNS",
+ "path": "/v1.12-docs/configuration/acme/dns01/azuredns.md"
+ },
+ {
+ "title": "Cloudflare",
+ "path": "/v1.12-docs/configuration/acme/dns01/cloudflare.md"
+ },
+ {
+ "title": "DigitalOcean",
+ "path": "/v1.12-docs/configuration/acme/dns01/digitalocean.md"
+ },
+ {
+ "title": "Google CloudDNS",
+ "path": "/v1.12-docs/configuration/acme/dns01/google.md"
+ },
+ {
+ "title": "RFC-2136",
+ "path": "/v1.12-docs/configuration/acme/dns01/rfc2136.md"
+ },
+ {
+ "title": "Route53",
+ "path": "/v1.12-docs/configuration/acme/dns01/route53.md"
+ },
+ {
+ "title": "Webhook",
+ "path": "/v1.12-docs/configuration/acme/dns01/webhook.md"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "title": "Usage",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/usage/README.md"
+ },
+ {
+ "title": "Certificate Resources",
+ "path": "/v1.12-docs/usage/certificate.md"
+ },
+ {
+ "title": "Prometheus Metrics",
+ "path": "/v1.12-docs/usage/prometheus-metrics.md"
+ },
+ {
+ "title": "Securing Ingress Resources",
+ "path": "/v1.12-docs/usage/ingress.md"
+ },
+ {
+ "title": "Securing Gateway Resources",
+ "path": "/v1.12-docs/usage/gateway.md"
+ },
+ {
+ "title": "Securing Istio Service Mesh",
+ "path": "/v1.12-docs/usage/istio.md"
+ },
+ {
+ "title": "CSI Driver",
+ "path": "/v1.12-docs/usage/csi.md"
+ },
+ {
+ "title": "Kubernetes CertificateSigningRequests",
+ "path": "/v1.12-docs/usage/kube-csr.md"
+ },
+ {
+ "title": "Policy for cert-manager certificates",
+ "path": "/v1.12-docs/usage/approver-policy.md"
+ }
+ ]
+ },
+ {
+ "title": "Tutorials",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/tutorials/README.md"
+ },
+ {
+ "title": "Securing NGINX-ingress",
+ "path": "/v1.12-docs/tutorials/acme/nginx-ingress.md"
+ },
+ {
+ "title": "GKE + Ingress + Let's Encrypt",
+ "path": "/v1.12-docs/tutorials/getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/README.md"
+ },
+ {
+ "title": "AKS + LoadBalancer + Let's Encrypt",
+ "path": "/v1.12-docs/tutorials/getting-started-aks-letsencrypt/README.md"
+ },
+ {
+ "title": "Migrating from Kube-LEGO",
+ "path": "/v1.12-docs/tutorials/acme/migrating-from-kube-lego.md"
+ },
+ {
+ "title": "Backup and Restore Resources",
+ "path": "/v1.12-docs/tutorials/backup.md"
+ },
+ {
+ "title": "DNS Validation",
+ "path": "/v1.12-docs/tutorials/acme/dns-validation.md"
+ },
+ {
+ "title": "HTTP Validation",
+ "path": "/v1.12-docs/tutorials/acme/http-validation.md"
+ },
+ {
+ "title": "Pomerium Ingress",
+ "path": "/v1.12-docs/tutorials/acme/pomerium-ingress.md"
+ },
+ {
+ "title": "EKS + Ingress + Venafi",
+ "path": "/v1.12-docs/tutorials/venafi/venafi.md"
+ },
+ {
+ "title": "Securing the istio Service Mesh using cert-manager",
+ "path": "/v1.12-docs/tutorials/istio-csr/istio-csr.md"
+ },
+ {
+ "title": "Syncing Secrets Across Namespaces",
+ "path": "/v1.12-docs/tutorials/syncing-secrets-across-namespaces.md"
+ },
+ {
+ "title": "Securing Ingresses with ZeroSSL",
+ "path": "/v1.12-docs/tutorials/zerossl/zerossl.md"
+ }
+ ]
+ },
+ {
+ "title": "Troubleshooting",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/troubleshooting/README.md"
+ },
+ {
+ "title": "Troubleshooting ACME / Let's Encrypt Certificates",
+ "path": "/v1.12-docs/troubleshooting/acme.md"
+ },
+ {
+ "title": "Troubleshooting webhook",
+ "path": "/v1.12-docs/troubleshooting/webhook.md"
+ }
+ ]
+ },
+ {
+ "title": "FAQ",
+ "path": "/v1.12-docs/faq/README.md"
+ },
+ {
+ "title": "Concepts",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/concepts/README.md"
+ },
+ {
+ "title": "Issuer",
+ "path": "/v1.12-docs/concepts/issuer.md"
+ },
+ {
+ "title": "Certificate",
+ "path": "/v1.12-docs/concepts/certificate.md"
+ },
+ {
+ "title": "CertificateRequest",
+ "path": "/v1.12-docs/concepts/certificaterequest.md"
+ },
+ {
+ "title": "ACME Orders and Challenges",
+ "path": "/v1.12-docs/concepts/acme-orders-challenges.md"
+ },
+ {
+ "title": "Webhook",
+ "path": "/v1.12-docs/concepts/webhook.md"
+ },
+ {
+ "title": "CA Injector",
+ "path": "/v1.12-docs/concepts/ca-injector.md"
+ }
+ ]
+ },
+ {
+ "title": "Reference",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/reference/README.md"
+ },
+ {
+ "title": "Command Line Tool (cmctl)",
+ "path": "/v1.12-docs/reference/cmctl.md"
+ },
+ {
+ "title": "TLS Terminology",
+ "path": "/v1.12-docs/reference/tls-terminology.md"
+ },
+ {
+ "title": "Components / Docker Images",
+ "routes": [
+ {
+ "title": "Introduction",
+ "path": "/v1.12-docs/cli/README.md"
+ },
+ {
+ "title": "acmesolver",
+ "path": "/v1.12-docs/cli/acmesolver.md"
+ },
+ {
+ "title": "cainjector",
+ "path": "/v1.12-docs/cli/cainjector.md"
+ },
+ {
+ "title": "cmctl",
+ "path": "/v1.12-docs/cli/cmctl.md"
+ },
+ {
+ "title": "controller",
+ "path": "/v1.12-docs/cli/controller.md"
+ },
+ {
+ "title": "webhook",
+ "path": "/v1.12-docs/cli/webhook.md"
+ }
+ ]
+ },
+ {
+ "title": "API Reference",
+ "path": "/v1.12-docs/reference/api-docs.md"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/content/v1.12-docs/reference/README.md b/content/v1.12-docs/reference/README.md
new file mode 100644
index 0000000000..473828e355
--- /dev/null
+++ b/content/v1.12-docs/reference/README.md
@@ -0,0 +1,15 @@
+---
+title: Reference
+description: Reference material including TLS terminology, API documentation, and information about the command line flags of the cert-manager components.
+---
+
+This section contains reference material including TLS terminology, API documentation, and information about the command line flags of the cert-manager components.
+
+* [TLS Terminology](./tls-terminology.md):
+ Learn about the TLS terminology used in the cert-manager documentation such as `publicly trusted`, `self-signed`, `root`, `intermediate` and `leaf` _certificate_.
+
+* [Components / Docker Images](../cli/README.md):
+ Learn about the command line flags of the cert-manager Docker images: `controller`, `webhook`, `cainjector`, `acmesolver`, which run in containers in your cluster.
+
+* [API Reference](./api-docs.md):
+ Learn about the cert-manager API which includes Custom Resources such as Certificate, CertificateRequest, Issuer and ClusterIssuer.
diff --git a/content/v1.12-docs/reference/api-docs.md b/content/v1.12-docs/reference/api-docs.md
new file mode 100644
index 0000000000..e766b7cfeb
--- /dev/null
+++ b/content/v1.12-docs/reference/api-docs.md
@@ -0,0 +1,5764 @@
+---
+title: API Reference
+description: >-
+ cert-manager API documentation, including Custom Resources such as
+ Certificate, CertificateRequest, Issuer and ClusterIssuer
+---
+
cert-manager API documentation, including various Custom Resource Definitions
The URL of the ACME Challenge resource for this challenge. This can be used to lookup details about the status of this challenge.
+
+
+
+
+ authorizationURL
+
+ string
+
+
+
The URL to the ACME Authorization resource that this challenge is a part of.
+
+
+
+
+ dnsName
+
+ string
+
+
+
dnsName is the identifier that this challenge is for, e.g. example.com. If the requested DNSName is a ‘wildcard’, this field MUST be set to the non-wildcard domain, e.g. for *.example.com, it must be example.com.
+
+
+
+
+ wildcard
+
+ bool
+
+
+ (Optional)
+
wildcard will be true if this challenge is for a wildcard identifier, for example ‘*.example.com’.
The type of ACME challenge this resource represents. One of “HTTP-01” or “DNS-01”.
+
+
+
+
+ token
+
+ string
+
+
+
The ACME challenge token for this challenge. This is the raw value returned from the ACME server.
+
+
+
+
+ key
+
+ string
+
+
+
+ The ACME challenge key for this challenge For HTTP01 challenges, this is the value that must be responded with to complete the HTTP01 challenge in the format:
+ <private key JWK thumbprint>.<key from acme server for challenge>. For DNS01 challenges, this is the base64 encoded SHA256 sum of the
+ <private key JWK thumbprint>.<key from acme server for challenge>
+ text that must be set as the TXT record content.
+
References a properly configured ACME-type Issuer which should be used to create this Challenge. If the Issuer does not exist, processing will be retried. If the Issuer is not an ‘ACME’ Issuer, an error will be returned and the Challenge will be marked as failed.
IssuerRef references a properly configured ACME-type Issuer which should be used to create this Order. If the Issuer does not exist, processing will be retried. If the Issuer is not an ‘ACME’ Issuer, an error will be returned and the Order will be marked as failed.
+
+
+
+
+ commonName
+
+ string
+
+
+ (Optional)
+
CommonName is the common name as specified on the DER encoded CSR. If specified, this value must also be present in dnsNames or ipAddresses. This field must match the corresponding field on the DER encoded CSR.
+
+
+
+
+ dnsNames
+
+ []string
+
+
+ (Optional)
+
DNSNames is a list of DNS names that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR.
+
+
+
+
+ ipAddresses
+
+ []string
+
+
+ (Optional)
+
IPAddresses is a list of IP addresses that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR.
ACMEAuthorization contains data returned from the ACME server on an authorization that must be completed in order validate a DNS name on an ACME Order resource.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ url
+
+ string
+
+
+
URL is the URL of the Authorization that must be completed
+
+
+
+
+ identifier
+
+ string
+
+
+ (Optional)
+
Identifier is the DNS name to be validated as part of this authorization
+
+
+
+
+ wildcard
+
+ bool
+
+
+ (Optional)
+
Wildcard will be true if this authorization is for a wildcard DNS name. If this is true, the identifier will be the non-wildcard version of the DNS name. For example, if ‘*.example.com’ is the DNS name being validated, this field will be ‘true’ and the ‘identifier’ field will be ‘example.com’.
InitialState is the initial state of the ACME authorization when first fetched from the ACME server. If an Authorization is already ‘valid’, the Order controller will not create a Challenge resource for the authorization. This will occur when working with an ACME server that enables ‘authz reuse’ (such as Let’s Encrypt’s production endpoint). If not set and ‘identifier’ is set, the state is assumed to be pending and a Challenge will be created.
Challenges specifies the challenge types offered by the ACME server. One of these challenge types will be selected when validating the DNS name and an appropriate Challenge resource will be created to perform the ACME challenge process.
Challenge specifies a challenge offered by the ACME server for an Order. An appropriate Challenge resource can be created to perform the ACME challenge process.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ url
+
+ string
+
+
+
URL is the URL of this challenge. It can be used to retrieve additional metadata about the Challenge from the ACME server.
+
+
+
+
+ token
+
+ string
+
+
+
Token is the token that must be presented for this challenge. This is used to compute the ‘key’ that must also be presented.
+
+
+
+
+ type
+
+ string
+
+
+
Type is the type of challenge being offered, e.g. ‘http-01’, ‘dns-01’, ‘tls-sni-01’, etc. This is the raw value retrieved from the ACME server. Only ‘http-01’ and ‘dns-01’ are supported by cert-manager, other values will be ignored.
An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. A selector may be provided to use different solving strategies for different DNS names. Only one of HTTP01 or DNS01 must be provided.
Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the ‘default’ solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead.
Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. *.example.com) using the HTTP01 challenge mechanism.
ACMEChallengeSolverHTTP01 contains configuration detailing how to solve HTTP01 challenges within a Kubernetes cluster. Typically this is accomplished through creating ‘routes’ of some description that configure ingress controllers to direct traffic to ‘solver pods’, which are responsible for responding to the ACME server’s HTTP requests. Only one of Ingress / Gateway can be specified.
The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for ‘/.well-known/acme-challenge/XYZ’ to ‘challenge solver’ pods that are provisioned by cert-manager for each Challenge to be completed.
The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future.
Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort.
+
+
+
+
+ ingressClassName
+
+ string
+
+
+ (Optional)
+
This field configures the field ingressClassName on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of class, name or ingressClassName may be specified.
+
+
+
+
+ class
+
+ string
+
+
+ (Optional)
+
This field configures the annotation kubernetes.io/ingress.class when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of class, name or ingressClassName may be specified.
+
+
+
+
+ name
+
+ string
+
+
+ (Optional)
+
The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of class, name or ingressClassName may be specified.
ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the ‘labels’ and ‘annotations’ fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values.
PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored.
ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the ‘labels’ and ‘annotations’ fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values.
keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes Secret which holds the symmetric MAC key of the External Account Binding. The key is the index string that is paired with the key data in the Secret and should not be confused with the key data itself, or indeed with the External Account Binding keyID above. The secret key stored in the Secret must be un-padded, base64 URL encoded data.
Deprecated: keyAlgorithm field exists for historical compatibility reasons and should not be used. The algorithm is now hardcoded to HS256 in golang/x/crypto/acme.
ACMEIssuer contains the specification for an ACME issuer. This uses the RFC8555 specification to obtain certificates by completing ‘challenges’ to prove ownership of domain identifiers. Earlier draft versions of the ACME specification are not supported.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ email
+
+ string
+
+
+ (Optional)
+
Email is the email address to be associated with the ACME account. This field is optional, but it is strongly recommended to be set. It will be used to contact you in case of issues with your account or certificates, including expiry notification emails. This field may be updated after the account is initially registered.
+
+
+
+
+ server
+
+ string
+
+
+
Server is the URL used to access the ACME server’s ‘directory’ endpoint. For example, for Let’s Encrypt’s staging endpoint, you would use: “https://acme-staging-v02.api.letsencrypt.org/directory”. Only ACME v2 endpoints (i.e. RFC 8555) are supported.
+
+
+
+
+ preferredChain
+
+ string
+
+
+ (Optional)
+
PreferredChain is the chain to use if the ACME server outputs multiple. PreferredChain is no guarantee that this one gets delivered by the ACME endpoint. For example, for Let’s Encrypt’s DST crosssign you would use: “DST Root CA X3” or “ISRG Root X1” for the newer Let’s Encrypt root CA. This value picks the first certificate bundle in the ACME alternative chains that has a certificate with this value as its issuer’s CN
+
+
+
+
+ caBundle
+
+ []byte
+
+
+ (Optional)
+
Base64-encoded bundle of PEM CAs which can be used to validate the certificate chain presented by the ACME server. Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various kinds of security vulnerabilities. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection.
+
+
+
+
+ skipTLSVerify
+
+ bool
+
+
+ (Optional)
+
INSECURE: Enables or disables validation of the ACME server TLS certificate. If true, requests to the ACME server will not have the TLS certificate chain validated. Mutually exclusive with CABundle; prefer using CABundle to prevent various kinds of security vulnerabilities. Only enable this option in development environments. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. Defaults to false.
ExternalAccountBinding is a reference to a CA external account of the ACME server. If set, upon registration cert-manager will attempt to associate the given external account credentials with the registered ACME account.
PrivateKey is the name of a Kubernetes Secret resource that will be used to store the automatically generated ACME account private key. Optionally, a key may be specified to select a specific entry within the named Secret resource. If key is not specified, a default of tls.key will be used.
Solvers is a list of challenge solvers that will be used to solve ACME challenges for the matching domains. Solver configurations must be provided in order to obtain certificates from an ACME server. For more information, see: https://cert-manager.io/docs/configuration/acme/
+
+
+
+
+ disableAccountKeyGeneration
+
+ bool
+
+
+ (Optional)
+
Enables or disables generating a new ACME account key. If true, the Issuer resource will not request a new account but will expect the account key to be supplied via an existing secret. If false, the cert-manager system will generate a new ACME account key for the Issuer. Defaults to false.
+
+
+
+
+ enableDurationFeature
+
+ bool
+
+
+ (Optional)
+
Enables requesting a Not After date on certificates that matches the duration of the certificate. This is not supported by all ACME servers like Let’s Encrypt. If set to true when the ACME server does not support it it will create an error on the Order. Defaults to false.
HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone.
ACMEIssuerDNS01ProviderCloudflare is a structure containing the DNS configuration for Cloudflare. One of apiKeySecretRef or apiTokenSecretRef must be provided.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ email
+
+ string
+
+
+ (Optional)
+
Email of the account, only required when using API key based authentication.
API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.
ACMEIssuerDNS01ProviderRFC2136 is a structure containing the configuration for RFC2136 DNS
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ nameserver
+
+ string
+
+
+
The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required.
The name of the secret containing the TSIG value. If tsigKeyName is defined, this field is required.
+
+
+
+
+ tsigKeyName
+
+ string
+
+
+ (Optional)
+
The TSIG Key name configured in the DNS. If tsigSecretSecretRef is defined, this field is required.
+
+
+
+
+ tsigAlgorithm
+
+ string
+
+
+ (Optional)
+
The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when tsigSecretSecretRef and tsigKeyName are defined. Supported values are (case-insensitive): HMACMD5 (default), HMACSHA1, HMACSHA256 or HMACSHA512.
Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata
+
+
+
+
+ hostedZoneID
+
+ string
+
+
+ (Optional)
+
If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call.
+
+
+
+
+ region
+
+ string
+
+
+
Always set the region when using AccessKeyID and SecretAccessKey
ACMEIssuerDNS01ProviderWebhook specifies configuration for a webhook DNS01 provider, including where to POST ChallengePayload resources.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ groupName
+
+ string
+
+
+
The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation.
+
+
+
+
+ solverName
+
+ string
+
+
+
The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. ‘cloudflare’.
Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation’s documentation.
URI is the unique account identifier, which can also be used to retrieve account details from the CA
+
+
+
+
+ lastRegisteredEmail
+
+ string
+
+
+ (Optional)
+
LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer
+
+
+
+
+ lastPrivateKeyHash
+
+ string
+
+
+ (Optional)
+
LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer
CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. By default, the None strategy will be applied (i.e. do not follow CNAMEs).
CertificateDNSNameSelector selects certificates using a label selector, and can optionally select individual DNS names within those certificates. If both MatchLabels and DNSNames are empty, this selector will match all certificates and DNS names within them.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ matchLabels
+
+ map[string]string
+
+
+ (Optional)
+
A label selector that is used to refine the set of certificate’s that this challenge solver will apply to.
+
+
+
+
+ dnsNames
+
+ []string
+
+
+ (Optional)
+
List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected.
+
+
+
+
+ dnsZones
+
+ []string
+
+
+ (Optional)
+
List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected.
The URL of the ACME Challenge resource for this challenge. This can be used to lookup details about the status of this challenge.
+
+
+
+
+ authorizationURL
+
+ string
+
+
+
The URL to the ACME Authorization resource that this challenge is a part of.
+
+
+
+
+ dnsName
+
+ string
+
+
+
dnsName is the identifier that this challenge is for, e.g. example.com. If the requested DNSName is a ‘wildcard’, this field MUST be set to the non-wildcard domain, e.g. for *.example.com, it must be example.com.
+
+
+
+
+ wildcard
+
+ bool
+
+
+ (Optional)
+
wildcard will be true if this challenge is for a wildcard identifier, for example ‘*.example.com’.
The type of ACME challenge this resource represents. One of “HTTP-01” or “DNS-01”.
+
+
+
+
+ token
+
+ string
+
+
+
The ACME challenge token for this challenge. This is the raw value returned from the ACME server.
+
+
+
+
+ key
+
+ string
+
+
+
+ The ACME challenge key for this challenge For HTTP01 challenges, this is the value that must be responded with to complete the HTTP01 challenge in the format:
+ <private key JWK thumbprint>.<key from acme server for challenge>. For DNS01 challenges, this is the base64 encoded SHA256 sum of the
+ <private key JWK thumbprint>.<key from acme server for challenge>
+ text that must be set as the TXT record content.
+
References a properly configured ACME-type Issuer which should be used to create this Challenge. If the Issuer does not exist, processing will be retried. If the Issuer is not an ‘ACME’ Issuer, an error will be returned and the Challenge will be marked as failed.
Used to denote whether this challenge should be processed or not. This field will only be set to true by the ‘scheduling’ component. It will only be set to false by the ‘challenges’ controller, after the challenge has reached a final state or timed out. If this field is set to false, the challenge controller will not take any more action.
+
+
+
+
+ presented
+
+ bool
+
+
+ (Optional)
+
presented will be set to true if the challenge values for this challenge are currently ‘presented’. This does not imply the self check is passing. Only that the values have been ‘submitted’ for the appropriate challenge mechanism (i.e. the DNS01 TXT record has been presented, or the HTTP01 configuration has been configured).
+
+
+
+
+ reason
+
+ string
+
+
+ (Optional)
+
Contains human readable information on why the Challenge is in the current state.
IssuerRef references a properly configured ACME-type Issuer which should be used to create this Order. If the Issuer does not exist, processing will be retried. If the Issuer is not an ‘ACME’ Issuer, an error will be returned and the Order will be marked as failed.
+
+
+
+
+ commonName
+
+ string
+
+
+ (Optional)
+
CommonName is the common name as specified on the DER encoded CSR. If specified, this value must also be present in dnsNames or ipAddresses. This field must match the corresponding field on the DER encoded CSR.
+
+
+
+
+ dnsNames
+
+ []string
+
+
+ (Optional)
+
DNSNames is a list of DNS names that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR.
+
+
+
+
+ ipAddresses
+
+ []string
+
+
+ (Optional)
+
IPAddresses is a list of IP addresses that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR.
URL of the Order. This will initially be empty when the resource is first created. The Order controller will populate this field when the Order is first processed. This field will be immutable after it is initially set.
+
+
+
+
+ finalizeURL
+
+ string
+
+
+ (Optional)
+
FinalizeURL of the Order. This is used to obtain certificates for this order once it has been completed.
Authorizations contains data returned from the ACME server on what authorizations must be completed in order to validate the DNS names specified on the Order.
+
+
+
+
+ certificate
+
+ []byte
+
+
+ (Optional)
+
Certificate is a copy of the PEM encoded certificate for this Order. This field will be populated after the order has been successfully finalized with the ACME server, and the order has transitioned to the ‘valid’ state.
+ State represents the state of an ACME resource, such as an Order. The possible options here map to the corresponding values in the ACME specification. Full details of these values can be found here: https://tools.ietf.org/html/draft-ietf-acme-acme-15#section-7.1.6
+ Clients utilising this type must also gracefully handle unknown values, as the contents of this enumeration may be added to over time.
+
+
+
+
+
+
Value
+
Description
+
+
+
+
+
+
"errored"
+
+
+
Errored signifies that the ACME resource has errored for some reason. This is a catch-all state, and is used for marking internal cert-manager errors such as validation failures. This is a final state.
+
+
+
+
+
"expired"
+
+
+
Expired signifies that an ACME resource has expired. If an Order is marked ‘Expired’, one of its validations may have expired or the Order itself. This is a final state.
+
+
+
+
+
"invalid"
+
+
+
Invalid signifies that an ACME resource is invalid for some reason. If an Order is marked ‘invalid’, one of its validations be have invalid for some reason. This is a final state.
+
+
+
+
+
"pending"
+
+
+
Pending signifies that an ACME resource is still pending and is not yet ready. If an Order is marked ‘Pending’, the validations for that Order are still in progress. This is a transient state.
+
+
+
+
+
"processing"
+
+
+
Processing signifies that an ACME resource is being processed by the server. If an Order is marked ‘Processing’, the validations for that Order are currently being processed. This is a transient state.
+
+
+
+
+
"ready"
+
+
+
Ready signifies that an ACME resource is in a ready state. If an order is ‘ready’, all of its challenges have been completed successfully and the order is ready to be finalized. Once finalized, it will transition to the Valid state. This is a transient state.
+
+
+
+
+
""
+
+
+
Unknown is not a real state as part of the ACME spec. It is used to represent an unrecognised value.
+
+
+
+
+
"valid"
+
+
+
Valid signifies that an ACME resource is in a valid state. If an order is ‘valid’, it has been finalized with the ACME server and the certificate can be retrieved from the ACME server using the certificate URL stored in the Order’s status subresource. This is a final state.
A Certificate resource should be created to ensure an up to date and signed x509 certificate is stored in the Kubernetes Secret resource named in spec.secretName.
+
The stored certificate will be renewed before it expires (as configured by spec.renewBefore).
LiteralSubject is an LDAP formatted string that represents the X.509 Subject field. Use this instead of the Subject field if you need to ensure the correct ordering of the RDN sequence, such as when issuing certs for LDAP authentication. See https://github.com/cert-manager/cert-manager/issues/3203, https://github.com/cert-manager/cert-manager/issues/4424. This field is alpha level and is only supported by cert-manager installations where LiteralCertificateSubject feature gate is enabled on both cert-manager controller and webhook.
+
+
+
+
+ commonName
+
+ string
+
+
+ (Optional)
+
CommonName is a common name to be used on the Certificate. The CommonName should have a length of 64 characters or fewer to avoid generating invalid CSRs. This value is ignored by TLS clients when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4
The requested ‘duration’ (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types. If unset this defaults to 90 days. Certificate will be renewed either 2⁄3 through its duration or renewBefore period before its expiry, whichever is later. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration
+ How long before the currently issued certificate’s expiry cert-manager should renew the certificate. The default is 2⁄3 of the issued certificate’s duration. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration
+ https://golang.org/pkg/time/#ParseDuration
+
+
+
+
+
+ dnsNames
+
+ []string
+
+
+ (Optional)
+
DNSNames is a list of DNS subjectAltNames to be set on the Certificate.
+
+
+
+
+ ipAddresses
+
+ []string
+
+
+ (Optional)
+
IPAddresses is a list of IP address subjectAltNames to be set on the Certificate.
+
+
+
+
+ uris
+
+ []string
+
+
+ (Optional)
+
URIs is a list of URI subjectAltNames to be set on the Certificate.
+
+
+
+
+ emailAddresses
+
+ []string
+
+
+ (Optional)
+
EmailAddresses is a list of email subjectAltNames to be set on the Certificate.
+
+
+
+
+ secretName
+
+ string
+
+
+
SecretName is the name of the secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer.
SecretTemplate defines annotations and labels to be copied to the Certificate’s Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate’s Secret.
IssuerRef is a reference to the issuer for this certificate. If the kind field is not set, or set to Issuer, an Issuer resource with the given name in the same namespace as the Certificate will be used. If the kind field is set to ClusterIssuer, a ClusterIssuer with the provided name will be used. The name field in this stanza is required at all times.
+
+
+
+
+ isCA
+
+ bool
+
+
+ (Optional)
+
IsCA will mark this Certificate as valid for certificate signing. This will automatically add the cert sign usage to the list of usages.
Options to control private keys used for the Certificate.
+
+
+
+
+ encodeUsagesInRequest
+
+ bool
+
+
+ (Optional)
+
EncodeUsagesInRequest controls whether key usages should be present in the CertificateRequest
+
+
+
+
+ revisionHistoryLimit
+
+ int32
+
+
+ (Optional)
+
revisionHistoryLimit is the maximum number of CertificateRequest revisions that are maintained in the Certificate’s history. Each revision represents a single CertificateRequest created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number. If set, revisionHistoryLimit must be a value of 1 or greater. If unset (nil), revisions will not be garbage collected. Default value is nil.
+ AdditionalOutputFormats defines extra output formats of the private key and signed certificate chain to be written to this Certificate’s target Secret. This is an Alpha Feature and is only enabled with the
+ --feature-gates=AdditionalCertificateOutputFormats=true option on both the controller and webhook components.
+
Status of the Certificate. This is set and managed automatically.
+
+
+
+
+
CertificateRequest
+
+
A CertificateRequest is used to request a signed certificate from one of the configured issuers.
+
+ All fields within the CertificateRequest’s spec are immutable after creation. A CertificateRequest will either succeed or fail, as denoted by its status.state
+ field.
+
+
A CertificateRequest is a one-shot resource, meaning it represents a single point in time request for a certificate and cannot be re-used.
IssuerRef is a reference to the issuer for this CertificateRequest. If the kind field is not set, or set to Issuer, an Issuer resource with the given name in the same namespace as the CertificateRequest will be used. If the kind field is set to ClusterIssuer, a ClusterIssuer with the provided name will be used. The name field in this stanza is required at all times. The group field refers to the API group of the issuer which defaults to cert-manager.io if empty.
+
+
+
+
+ request
+
+ []byte
+
+
+
The PEM-encoded x509 certificate signing request to be submitted to the CA for signing.
+
+
+
+
+ isCA
+
+ bool
+
+
+ (Optional)
+
IsCA will request to mark the certificate as valid for certificate signing when submitting to the issuer. This will automatically add the cert sign usage to the list of usages.
Usages is the set of x509 usages that are requested for the certificate. If usages are set they SHOULD be encoded inside the CSR spec Defaults to digital signature and key encipherment if not specified.
+
+
+
+
+ username
+
+ string
+
+
+ (Optional)
+
Username contains the name of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable.
+
+
+
+
+ uid
+
+ string
+
+
+ (Optional)
+
UID contains the uid of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable.
+
+
+
+
+ groups
+
+ []string
+
+
+ (Optional)
+
Groups contains group membership of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable.
+
+
+
+
+ extra
+
+ map[string][]string
+
+
+ (Optional)
+
Extra contains extra attributes of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable.
Status of the CertificateRequest. This is set and managed automatically.
+
+
+
+
+
ClusterIssuer
+
+
A ClusterIssuer represents a certificate issuing authority which can be referenced as part of issuerRef fields. It is similar to an Issuer, however it is cluster-scoped and therefore can be referenced by resources that exist in any namespace, not just the same namespace as the referent.
Status of the ClusterIssuer. This is set and managed automatically.
+
+
+
+
+
Issuer
+
+
An Issuer represents a certificate issuing authority which can be referenced as part of issuerRef fields. It is scoped to a single namespace and can therefore only be referenced by resources within the same namespace.
SecretName is the name of the secret used to sign Certificates issued by this Issuer.
+
+
+
+
+ crlDistributionPoints
+
+ []string
+
+
+ (Optional)
+
The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set, certificates will be issued without distribution points set.
+
+
+
+
+ ocspServers
+
+ []string
+
+
+ (Optional)
+
The OCSP server list is an X.509 v3 extension that defines a list of URLs of OCSP responders. The OCSP responders can be queried for the revocation status of an issued certificate. If not set, the certificate will be issued with no OCSP servers set. For example, an OCSP server URL could be “http://ocsp.int-x3.letsencrypt.org”.
CertificateAdditionalOutputFormat defines an additional output format of a Certificate resource. These contain supplementary data formats of the signed certificate chain and paired private key.
LastTransitionTime is the timestamp corresponding to the last status change of this condition.
+
+
+
+
+ reason
+
+ string
+
+
+ (Optional)
+
Reason is a brief machine readable explanation for the condition’s last transition.
+
+
+
+
+ message
+
+ string
+
+
+ (Optional)
+
Message is a human readable description of the details of the last transition, complementing reason.
+
+
+
+
+ observedGeneration
+
+ int64
+
+
+ (Optional)
+
If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Certificate.
CertificateConditionType represents an Certificate condition value.
+
+
+
+
+
Value
+
Description
+
+
+
+
+
+
"Issuing"
+
+
+
+ A condition added to Certificate resources when an issuance is required. This condition will be automatically added and set to true if: * No keypair data exists in the target Secret * The data stored in the Secret cannot be decoded * The private key and certificate do not have matching public keys * If a CertificateRequest for the current revision exists and the certificate data stored in the Secret does not match the
+ status.certificate on the CertificateRequest. * If no CertificateRequest resource exists for the current revision, the options on the Certificate resource are compared against the x509 data in the Secret, similar to what’s done in earlier versions. If there is a mismatch, an issuance is triggered. This condition may also be added by external API consumers to trigger a re-issuance manually for any other reason.
+
+
It will be removed by the ‘issuing’ controller upon completing issuance.
+
+
+
+
+
"Ready"
+
+
+
CertificateConditionReady indicates that a certificate is ready for use. This is defined as: - The target secret exists - The target secret contains a certificate that has not expired - The target secret contains a private key valid for the certificate - The commonName and dnsNames attributes match those specified on the Certificate
+ CertificateOutputFormatType specifies which additional output formats should be written to the Certificate’s target Secret. Allowed values are DER or CombinedPEM. When Type is set to DER an additional entry key.der will be written to the Secret, containing the binary format of the private key. When Type is set to CombinedPEM an additional entry tls-combined.pem
+ will be written to the Secret, containing the PEM formatted private key and signed certificate chain (tls.key + tls.crt concatenated).
+
+
+
+
+
+
Value
+
Description
+
+
+
+
+
+
"CombinedPEM"
+
+
+
+ CertificateOutputFormatCombinedPEM writes the Certificate’s signed certificate chain and private key, in PEM format, to the
+ tls-combined.pem target Secret Data key. The value at this key will include the private key PEM document, followed by at least one new line character, followed by the chain of signed certificate PEM documents (<private key> + \n + <signed certificate chain>).
+
+
+
+
+
+
"DER"
+
+
+
CertificateOutputFormatDER writes the Certificate’s private key in DER binary format to the key.der target Secret Data key.
CertificatePrivateKey contains configuration options for private keys used by the Certificate controller. This allows control of how private keys are rotated.
RotationPolicy controls how private keys should be regenerated when a re-issuance is being processed. If set to Never, a private key will only be generated if one does not already exist in the target spec.secretName. If one does exists but it does not have the correct algorithm or size, a warning will be raised to await user intervention. If set to Always, a private key matching the specified requirements will be generated whenever a re-issuance occurs. Default is ‘Never’ for backward compatibility.
The private key cryptography standards (PKCS) encoding for this certificate’s private key to be encoded in. If provided, allowed values are PKCS1 and PKCS8 standing for PKCS#1 and PKCS#8, respectively. Defaults to PKCS1 if not specified.
Algorithm is the private key algorithm of the corresponding private key for this certificate. If provided, allowed values are either RSA,Ed25519 or ECDSA If algorithm is specified and size is not provided, key size of 256 will be used for ECDSA key algorithm and key size of 2048 will be used for RSA key algorithm. key size is ignored when using the Ed25519 key algorithm.
+
+
+
+
+ size
+
+ int
+
+
+ (Optional)
+
Size is the key bit size of the corresponding private key for this certificate. If algorithm is set to RSA, valid values are 2048, 4096 or 8192, and will default to 2048 if not specified. If algorithm is set to ECDSA, valid values are 256, 384 or 521, and will default to 256 if not specified. If algorithm is set to Ed25519, Size is ignored. No other values are allowed.
CertificateRequestConditionType represents an Certificate condition value.
+
+
+
+
+
Value
+
Description
+
+
+
+
+
+
"Approved"
+
+
+
+ CertificateRequestConditionApproved indicates that a certificate request is approved and ready for signing. Condition must never have a status of
+ False, and cannot be modified once set. Cannot be set alongside Denied.
+
+
+
+
+
+
"Denied"
+
+
+
+ CertificateRequestConditionDenied indicates that a certificate request is denied, and must never be signed. Condition must never have a status of
+ False, and cannot be modified once set. Cannot be set alongside Approved.
+
+
+
+
+
+
"InvalidRequest"
+
+
+
CertificateRequestConditionInvalidRequest indicates that a certificate signer has refused to sign the request due to at least one of the input parameters being invalid. Additional information about why the request was rejected can be found in the reason and message fields.
+
+
+
+
+
"Ready"
+
+
+
CertificateRequestConditionReady indicates that a certificate is ready for use. This is defined as: - The target certificate exists in CertificateRequest.Status
IssuerRef is a reference to the issuer for this CertificateRequest. If the kind field is not set, or set to Issuer, an Issuer resource with the given name in the same namespace as the CertificateRequest will be used. If the kind field is set to ClusterIssuer, a ClusterIssuer with the provided name will be used. The name field in this stanza is required at all times. The group field refers to the API group of the issuer which defaults to cert-manager.io if empty.
+
+
+
+
+ request
+
+ []byte
+
+
+
The PEM-encoded x509 certificate signing request to be submitted to the CA for signing.
+
+
+
+
+ isCA
+
+ bool
+
+
+ (Optional)
+
IsCA will request to mark the certificate as valid for certificate signing when submitting to the issuer. This will automatically add the cert sign usage to the list of usages.
Usages is the set of x509 usages that are requested for the certificate. If usages are set they SHOULD be encoded inside the CSR spec Defaults to digital signature and key encipherment if not specified.
+
+
+
+
+ username
+
+ string
+
+
+ (Optional)
+
Username contains the name of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable.
+
+
+
+
+ uid
+
+ string
+
+
+ (Optional)
+
UID contains the uid of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable.
+
+
+
+
+ groups
+
+ []string
+
+
+ (Optional)
+
Groups contains group membership of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable.
+
+
+
+
+ extra
+
+ map[string][]string
+
+
+ (Optional)
+
Extra contains extra attributes of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable.
List of status conditions to indicate the status of a CertificateRequest. Known condition types are Ready and InvalidRequest.
+
+
+
+
+ certificate
+
+ []byte
+
+
+ (Optional)
+
+ The PEM encoded x509 certificate resulting from the certificate signing request. If not set, the CertificateRequest has either not been completed or has failed. More information on failure can be found by checking the
+ conditions field.
+
+
+
+
+
+ ca
+
+ []byte
+
+
+ (Optional)
+
The PEM encoded x509 certificate of the signer, also known as the CA (Certificate Authority). This is set on a best-effort basis by different issuers. If not set, the CA is assumed to be unknown/not available.
CertificateSecretTemplate defines the default labels and annotations to be copied to the Kubernetes Secret resource named in CertificateSpec.secretName.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ annotations
+
+ map[string]string
+
+
+ (Optional)
+
Annotations is a key value map to be copied to the target Kubernetes Secret.
+
+
+
+
+ labels
+
+ map[string]string
+
+
+ (Optional)
+
Labels is a key value map to be copied to the target Kubernetes Secret.
LiteralSubject is an LDAP formatted string that represents the X.509 Subject field. Use this instead of the Subject field if you need to ensure the correct ordering of the RDN sequence, such as when issuing certs for LDAP authentication. See https://github.com/cert-manager/cert-manager/issues/3203, https://github.com/cert-manager/cert-manager/issues/4424. This field is alpha level and is only supported by cert-manager installations where LiteralCertificateSubject feature gate is enabled on both cert-manager controller and webhook.
+
+
+
+
+ commonName
+
+ string
+
+
+ (Optional)
+
CommonName is a common name to be used on the Certificate. The CommonName should have a length of 64 characters or fewer to avoid generating invalid CSRs. This value is ignored by TLS clients when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4
The requested ‘duration’ (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types. If unset this defaults to 90 days. Certificate will be renewed either 2⁄3 through its duration or renewBefore period before its expiry, whichever is later. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration
+ How long before the currently issued certificate’s expiry cert-manager should renew the certificate. The default is 2⁄3 of the issued certificate’s duration. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration
+ https://golang.org/pkg/time/#ParseDuration
+
+
+
+
+
+ dnsNames
+
+ []string
+
+
+ (Optional)
+
DNSNames is a list of DNS subjectAltNames to be set on the Certificate.
+
+
+
+
+ ipAddresses
+
+ []string
+
+
+ (Optional)
+
IPAddresses is a list of IP address subjectAltNames to be set on the Certificate.
+
+
+
+
+ uris
+
+ []string
+
+
+ (Optional)
+
URIs is a list of URI subjectAltNames to be set on the Certificate.
+
+
+
+
+ emailAddresses
+
+ []string
+
+
+ (Optional)
+
EmailAddresses is a list of email subjectAltNames to be set on the Certificate.
+
+
+
+
+ secretName
+
+ string
+
+
+
SecretName is the name of the secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer.
SecretTemplate defines annotations and labels to be copied to the Certificate’s Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate’s Secret.
IssuerRef is a reference to the issuer for this certificate. If the kind field is not set, or set to Issuer, an Issuer resource with the given name in the same namespace as the Certificate will be used. If the kind field is set to ClusterIssuer, a ClusterIssuer with the provided name will be used. The name field in this stanza is required at all times.
+
+
+
+
+ isCA
+
+ bool
+
+
+ (Optional)
+
IsCA will mark this Certificate as valid for certificate signing. This will automatically add the cert sign usage to the list of usages.
Options to control private keys used for the Certificate.
+
+
+
+
+ encodeUsagesInRequest
+
+ bool
+
+
+ (Optional)
+
EncodeUsagesInRequest controls whether key usages should be present in the CertificateRequest
+
+
+
+
+ revisionHistoryLimit
+
+ int32
+
+
+ (Optional)
+
revisionHistoryLimit is the maximum number of CertificateRequest revisions that are maintained in the Certificate’s history. Each revision represents a single CertificateRequest created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number. If set, revisionHistoryLimit must be a value of 1 or greater. If unset (nil), revisions will not be garbage collected. Default value is nil.
+ AdditionalOutputFormats defines extra output formats of the private key and signed certificate chain to be written to this Certificate’s target Secret. This is an Alpha Feature and is only enabled with the
+ --feature-gates=AdditionalCertificateOutputFormats=true option on both the controller and webhook components.
+
LastFailureTime is set only if the lastest issuance for this Certificate failed and contains the time of the failure. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). If the latest issuance has succeeded this field will be unset.
RenewalTime is the time at which the certificate will be next renewed. If not set, no upcoming renewal is scheduled.
+
+
+
+
+ revision
+
+ int
+
+
+ (Optional)
+
The current ‘revision’ of the certificate as issued.
+
+ When a CertificateRequest resource is created, it will have the
+ cert-manager.io/certificate-revision set to one greater than the current value of this field.
+
+
Upon issuance, this field will be set to the value of the annotation on the CertificateRequest resource used to issue the certificate.
+
Persisting the value on the CertificateRequest resource allows the certificates controller to know whether a request is part of an old issuance or if it is part of the ongoing revision’s issuance by checking if the revision value in the annotation is greater than this field.
+
+
+
+
+ nextPrivateKeySecretName
+
+ string
+
+
+ (Optional)
+
+ The name of the Secret resource containing the private key to be used for the next certificate iteration. The keymanager controller will automatically set this field if the
+ Issuing condition is set to True. It will automatically unset this field when the Issuing condition is not set or False.
+
+
+
+
+
+ failedIssuanceAttempts
+
+ int
+
+
+ (Optional)
+
The number of continuous failed issuance attempts up till now. This field gets removed (if set) on a successful issuance and gets set to 1 if unset and an issuance has failed. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1).
LastTransitionTime is the timestamp corresponding to the last status change of this condition.
+
+
+
+
+ reason
+
+ string
+
+
+ (Optional)
+
Reason is a brief machine readable explanation for the condition’s last transition.
+
+
+
+
+ message
+
+ string
+
+
+ (Optional)
+
Message is a human readable description of the details of the last transition, complementing reason.
+
+
+
+
+ observedGeneration
+
+ int64
+
+
+ (Optional)
+
If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Issuer.
IssuerConditionType represents an Issuer condition value.
+
+
+
+
+
Value
+
Description
+
+
+
+
+
+
"Ready"
+
+
+
IssuerConditionReady represents the fact that a given Issuer condition is in ready state and able to issue certificates. If the status of this condition is False, CertificateRequest controllers should prevent attempts to sign certificates.
CA configures this issuer to sign certificates using a signing CA keypair stored in a Secret resource. This is used to build internal PKIs that are managed by cert-manager.
+ JKS configures options for storing a JKS keystore in the spec.secretName
+ Secret resource.
+
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ create
+
+ bool
+
+
+
+ Create enables JKS keystore creation for the Certificate. If true, a file named keystore.jks will be created in the target Secret resource, encrypted using the password stored in passwordSecretRef. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named truststore.jks will also be created in the target Secret resource, encrypted using the password stored in passwordSecretRef
+ containing the issuing Certificate Authority
+
+ PKCS12 configures options for storing a PKCS12 keystore in the
+ spec.secretName Secret resource.
+
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ create
+
+ bool
+
+
+
Create enables PKCS12 keystore creation for the Certificate. If true, a file named keystore.p12 will be created in the target Secret resource, encrypted using the password stored in passwordSecretRef. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named truststore.p12 will also be created in the target Secret resource, encrypted using the password stored in passwordSecretRef containing the issuing Certificate Authority
PKCS1 key encoding will produce PEM files that include the type of private key as part of the PEM header, e.g. BEGIN RSA PRIVATE KEY. If the keyAlgorithm is set to ‘ECDSA’, this will produce private keys that use the BEGIN EC PRIVATE KEY header.
+
+
+
+
+
"PKCS8"
+
+
+
+ PKCS8 key encoding will produce PEM files with the BEGIN PRIVATE KEY
+ header. It encodes the keyAlgorithm of the private key as part of the DER encoded PEM block.
+
Configures an issuer to ‘self sign’ certificates using the private key used to create the CertificateRequest object.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ crlDistributionPoints
+
+ []string
+
+
+ (Optional)
+
The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set certificate will be issued without CDP. Values are strings.
ServiceAccountRef is a service account used by cert-manager to request a token. The audience cannot be configured. The audience is generated by cert-manager and takes the form vault://namespace-name/issuer-name for an Issuer and vault://issuer-name for a ClusterIssuer. The expiration of the token is also set by cert-manager to 10 minutes.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ name
+
+ string
+
+
+
Name of the ServiceAccount used to request a token.
Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The key field must be specified and denotes which entry within the Secret resource is used as the app role secret.
Path is the mount path of the Vault PKI backend’s sign endpoint, e.g: “my_pki_mount/sign/my-role-name”.
+
+
+
+
+ namespace
+
+ string
+
+
+ (Optional)
+
Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: “ns1” More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces
+
+
+
+
+ caBundle
+
+ []byte
+
+
+ (Optional)
+
Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by Vault. Only used if using HTTPS to connect to Vault and ignored for HTTP connections. Mutually exclusive with CABundleSecretRef. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection.
Reference to a Secret containing a bundle of PEM-encoded CAs to use when verifying the certificate chain presented by Vault when using HTTPS. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. If no key for the Secret is specified, cert-manager will default to ‘ca.crt’.
Authenticate against Vault using a Kubernetes ServiceAccount token stored in a Secret.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ mountPath
+
+ string
+
+
+ (Optional)
+
The Vault mountPath here is the mount path to use when authenticating with Vault. For example, setting a value to /v1/auth/foo, will use the path /v1/auth/foo/login to authenticate with Vault. If unspecified, the default value “/v1/auth/kubernetes” will be used.
The required Secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. Use of ‘ambient credentials’ is not supported.
A reference to a service account that will be used to request a bound token (also known as “projected token”). Compared to using “secretRef”, using this field means that you don’t rely on statically bound tokens. To use this field, you must configure an RBAC rule to let cert-manager request a token.
+
+
+
+
+ role
+
+ string
+
+
+
A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies.
Configures an issuer to sign certificates using a Venafi TPP or Cloud policy zone.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ zone
+
+ string
+
+
+
Zone is the Venafi Policy Zone to use for this issuer. All requests made to the Venafi platform will be restricted by the named zone policy. This field is required.
CredentialsRef is a reference to a Secret containing the username and password for the TPP server. The secret must contain two keys, ‘username’ and ‘password’.
+
+
+
+
+ caBundle
+
+ []byte
+
+
+ (Optional)
+
Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain.
A reference to an object in the same namespace as the referent. If the referent is a cluster-scoped resource (e.g. a ClusterIssuer), the reference instead refers to the resource with the given name in the configured ‘cluster resource namespace’, which is set as a flag on the controller component (and defaults to the namespace that cert-manager runs in).
DynamicServingConfig makes the webhook generate a CA and persist it into Secret resources. This CA will be used by all instances of the webhook for signing serving certificates.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ secretNamespace
+
+ string
+
+
+
Namespace of the Kubernetes Secret resource containing the TLS certificate used as a CA to sign dynamic serving certificates.
+
+
+
+
+ secretName
+
+ string
+
+
+
Namespace of the Kubernetes Secret resource containing the TLS certificate used as a CA to sign dynamic serving certificates.
+
+
+
+
+ dnsNames
+
+ []string
+
+
+
DNSNames that must be present on serving certificates signed by the CA.
FilesystemServingConfig enables using a certificate and private key found on the local filesystem. These files will be periodically polled in case they have changed, and dynamically reloaded.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ certFile
+
+ string
+
+
+
Path to a file containing TLS certificate & chain to serve with
+
+
+
+
+ keyFile
+
+ string
+
+
+
Path to a file containing a TLS private key to server with
TLSConfig configures how TLS certificates are sourced for serving. Only one of ‘filesystem’ or ‘dynamic’ may be specified.
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ cipherSuites
+
+ []string
+
+
+
cipherSuites is the list of allowed cipher suites for the server. Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). If not specified, the default for the Go version will be used and may change over time.
+
+
+
+
+ minTLSVersion
+
+ string
+
+
+
minTLSVersion is the minimum TLS version supported. Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). If not specified, the default for the Go version will be used and may change over time.
Filesystem enables using a certificate and private key found on the local filesystem. These files will be periodically polled in case they have changed, and dynamically reloaded.
When Dynamic serving is enabled, the webhook will generate a CA used to sign webhook certificates and persist it into a Kubernetes Secret resource (for other replicas of the webhook to consume). It will then generate a certificate in-memory for itself using this CA to serve with. The CAs certificate can then be copied into the appropriate Validating, Mutating and Conversion webhook configuration objects (typically by cainjector).
+
+
+
+
+
WebhookConfiguration
+
+
+
+
+
Field
+
Description
+
+
+
+
+
+ securePort
+
+ int
+
+
+
securePort is the port number to listen on for secure TLS connections from the kube-apiserver. Defaults to 6443.
+
+
+
+
+ healthzPort
+
+ int
+
+
+
healthzPort is the port number to listen on (using plaintext HTTP) for healthz connections. Defaults to 6080.
tlsConfig is used to configure the secure listener’s TLS settings.
+
+
+
+
+ kubeConfig
+
+ string
+
+
+
kubeConfig is the kubeconfig file used to connect to the Kubernetes apiserver. If not specified, the webhook will attempt to load the in-cluster-config.
+
+
+
+
+ apiServerHost
+
+ string
+
+
+
apiServerHost is used to override the API server connection address. Deprecated: use kubeConfig instead.
+
+
+
+
+ enablePprof
+
+ bool
+
+
+
enablePprof configures whether pprof is enabled.
+
+
+
+
+ pprofAddress
+
+ string
+
+
+
pprofAddress configures the address on which /debug/pprof endpoint will be served if enabled. Defaults to ‘localhost:6060’.
+
+
+
+
+ featureGates
+
+ map[string]bool
+
+
+ (Optional)
+
featureGates is a map of feature names to bools that enable or disable experimental features. Default: nil
+
+
+
+
+
+
+ Generated with gen-crd-api-reference-docs on git commit fe41951.
+
diff --git a/content/v1.12-docs/reference/cmctl.md b/content/v1.12-docs/reference/cmctl.md
new file mode 100644
index 0000000000..095c9dfe6e
--- /dev/null
+++ b/content/v1.12-docs/reference/cmctl.md
@@ -0,0 +1,344 @@
+---
+title: The cert-manager Command Line Tool (cmctl)
+description: |
+ cmctl is a command line tool that can help you manage cert-manager and its resources inside your cluster
+---
+
+`cmctl` is a command line tool that can help you manage cert-manager and its resources inside your cluster.
+
+## Installation
+
+### Homebrew
+
+On Mac or Linux if you have [Homebrew](https://brew.sh) installed, you can
+install `cmctl` with:
+
+```console
+brew install cmctl
+```
+
+This will also install shell completion.
+
+### Manual Installation
+
+You need the `cmctl.tar.gz` file for the platform you're using, these can be
+found on our
+[GitHub releases page](https://github.com/cert-manager/cert-manager/releases).
+In order to use `cmctl` you need its binary to be accessible under
+the name `cmctl` in your `$PATH`.
+Run the following commands to set up the CLI. Replace OS and ARCH with your
+systems equivalents:
+
+```console
+OS=$(go env GOOS); ARCH=$(go env GOARCH); curl -fsSL -o cmctl.tar.gz https://github.com/cert-manager/cert-manager/releases/latest/download/cmctl-$OS-$ARCH.tar.gz
+tar xzf cmctl.tar.gz
+sudo mv cmctl /usr/local/bin
+```
+
+You can run `cmctl help` to test the CLI is set up properly:
+
+```console
+$ cmctl help
+
+cmctl is a CLI tool manage and configure cert-manager resources for Kubernetes
+
+Usage: cmctl [command]
+
+Available Commands:
+ approve Approve a CertificateRequest
+ check Check cert-manager components
+ completion Generate completion scripts for the cert-manager CLI
+ convert Convert cert-manager config files between different API versions
+ create Create cert-manager resources
+ deny Deny a CertificateRequest
+ experimental Interact with experimental features
+ help Help about any command
+ inspect Get details on certificate related resources
+ renew Mark a Certificate for manual renewal
+ status Get details on current status of cert-manager resources
+ upgrade Tools that assist in upgrading cert-manager
+ version Print the cert-manager CLI version and the deployed cert-manager version
+
+Flags:
+ -h, --help help for cmctl
+ --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+
+Use "cmctl [command] --help" for more information about a command.
+```
+
+> There is also a [legacy kubectl plugin](#legacy-kubectl-plugin), but it is no longer recommended
+> because the standalone `cmctl` binary provides better [auto-completion](#completion).
+
+## Commands
+
+### Approve and Deny CertificateRequests
+
+CertificateRequests can be
+[approved or denied](../concepts/certificaterequest.md#approval) using their
+respective cmctl commands:
+
+> **Note**: The internal cert-manager approver may automatically approve all
+> CertificateRequests unless disabled with the flag on the cert-manager-controller
+> `--controllers=*,-certificaterequests-approver`
+
+```bash
+$ cmctl approve -n istio-system mesh-ca --reason "pki-team" --message "this certificate is valid"
+Approved CertificateRequest 'istio-system/mesh-ca'
+```
+
+```bash
+$ cmctl deny -n my-app my-app --reason "example.com" --message "violates policy"
+Denied CertificateRequest 'my-app/my-app'
+```
+
+### Convert
+
+`cmctl convert` can be used to convert cert-manager manifest files between
+different API versions. Both YAML and JSON formats are accepted. The command
+either takes a file name, directory path, or a URL as input. The contents is
+converted into the format of the latest API version known to cert-manager, or
+the one specified by `--output-version` flag.
+
+The default output will be printed to stdout in YAML format. One can use the
+option `-o` to change the output destination.
+
+For example, this will output `cert.yaml` in the latest API version:
+
+```console
+cmctl convert -f cert.yaml
+```
+
+### Create
+
+`cmctl create` can be used to create cert-manager resources manually.
+Sub-commands are available to create different resources:
+
+#### CertificateRequest
+
+To create a cert-manager CertificateRequest, use `cmctl create
+certificaterequest`. The command takes in the name of the CertificateRequest to
+be created, and creates a new CertificateRequest resource based on the YAML
+manifest of a Certificate resource as specified by `--from-certificate-file`
+flag, by generating a private key locally and creating a 'certificate signing
+request' to be submitted to a cert-manager Issuer. The private key will be
+written to a local file, where the default is `.key`, or it can be
+specified using the `--output-key-file` flag.
+
+If you wish to wait for the CertificateRequest to be signed and store the X.509
+certificate in a file, you can set the `--fetch-certificate` flag. The default
+timeout when waiting for the issuance of the certificate is 5 minutes, but can
+be specified with the `--timeout` flag. The default name of the file storing the
+X.509 certificate is `.crt`, you can use the `
+--output-certificate-file` flag to specify otherwise.
+
+Note that the private key and the X.509 certificate are both written to file,
+and are **not** stored inside Kubernetes.
+
+For example this will create a CertificateRequest resource with the name "my-cr"
+based on the cert-manager Certificate described in `my-certificate.yaml` while
+storing the private key and X.509 certificate in `my-cr.key` and `my-cr.crt`
+respectively.
+
+```console
+cmctl create certificaterequest my-cr --from-certificate-file my-certificate.yaml --fetch-certificate --timeout 20m
+```
+
+### Renew
+
+`cmctl` allows you to manually trigger a renewal of a specific certificate.
+This can be done either one certificate at a time, using label selectors (`-l app=example`), or with the `--all` flag:
+
+For example, you can renew the certificate `example-com-tls`:
+```console
+$ kubectl get certificate
+NAME READY SECRET AGE
+example-com-tls True example-com-tls 1d
+
+$ cmctl renew example-com-tls
+Manually triggered issuance of Certificate default/example-com-tls
+
+$ kubectl get certificaterequest
+NAME READY AGE
+example-com-tls-tls-8rbv2 False 10s
+```
+
+You can also renew all certificates in a given namespace:
+
+```console
+$ cmctl renew --namespace=app --all
+```
+
+The renew command allows several options to be specified:
+* `--all` renew all Certificates in the given Namespace, or all namespaces when combined with `--all-namespaces`
+* `-A` or `--all-namespaces` mark Certificates across namespaces for renewal
+* `-l` `--selector` allows set a label query to filter on
+as well as `kubectl` like global flags like `--context` and `--namespace`.
+
+### Status Certificate
+
+`cmctl status certificate` outputs the details of the current status of a
+Certificate resource and related resources like CertificateRequest, Secret,
+Issuer, as well as Order and Challenges if it is a ACME Certificate. The
+command outputs information about the resources, including Conditions, Events
+and resource specific fields like Key Usages and Extended Key Usages of the
+Secret or Authorizations of the Order. This will be helpful for troubleshooting
+a Certificate.
+
+The command takes in one argument specifying the name of the Certificate
+resource and the namespace can be specified as usual with the `-n` or
+`--namespace` flag.
+
+This example queries the status of the Certificate named `my-certificate` in
+namespace `my-namespace`.
+
+```console
+cmctl status certificate my-certificate -n my-namespace
+```
+
+### Completion
+
+`cmctl` supports auto-completion for both subcommands as well as suggestions for
+runtime objects.
+
+```console
+$ cmctl approve -n
+default kube-node-lease kube-public kube-system local-path-storage
+```
+
+Completion can be installed for your environment by following the instructions
+for the shell you are using. It currently supports bash, fish, zsh, and
+powershell.
+
+```console
+$ cmctl completion help
+```
+
+---
+
+### Experimental
+`cmctl x` has experimental sub-commands for operations which are currently under
+evaluation to be included into cert-manager proper. The behavior and interface
+of these commands are subject to change or removal in future releases.
+
+
+#### Create
+`cmctl x create` can be used to create cert-manager resources manually.
+Sub-commands are available to create different resources:
+
+##### CertificateSigningRequest
+To create a [CertificateSigningRequest](../usage/kube-csr.md), use
+```console
+cmctl x create csr
+```
+This command takes the name of the CertificateSigningRequest to be created, as
+well as a file containing a Certificate manifest (`-f,
+--from-certificate-file`). This command will generate a private key, based on
+the options of the Certificate, and write it to the local file `.key`, or
+specified by `-k, --output-key-file`.
+
+```bash
+$ cmctl x create csr -f my-cert.yaml my-req
+```
+
+
+
+
+cert-manager **will not** automatically approve CertificateSigningRequests. If
+you are not running a custom approver in your cluster, you will likely need to
+manually approve the CertificateSigningRequest:
+
+```bash
+$ kubectl certificate approve
+```
+
+
+
+This command can also wait for the CertificateSigningRequest to be signed using
+the flag `-w, --fetch-certificate`. Once signed it will write the resulting
+signed certificate to the local file `.crt`, or specified by `-c,
+--output-certificate-file`.
+
+```bash
+$ cmctl x create csr -f my-cert.yaml my-req -w
+```
+
+#### Install
+
+```bash
+cmctl x install
+```
+
+This command makes sure that the required `CustomResourceDefinitions` are installed together with the cert-manager, cainjector and webhook components.
+Under the hood, a procedure similar to the [Helm install procedure](../installation/helm.md#steps) is used.
+
+You can also use `cmctl x install` to customize the installation of cert-manager.
+
+The example below shows how to tune the cert-manager installation by overriding the default Helm values:
+
+```bash
+cmctl x install \
+ --set prometheus.enabled=false \ # Example: disabling prometheus using a Helm parameter
+ --set webhook.timeoutSeconds=4s # Example: changing the wehbook timeout using a Helm parameter
+```
+
+You can find [a full list of the install parameters on cert-manager's ArtifactHub page](https://artifacthub.io/packages/helm/cert-manager/cert-manager#configuration). These are the same parameters that are available when using the Helm chart.
+Once you have deployed cert-manager, you can [verify](../installation/verify.md) the installation.
+
+The CLI also allows the user to output the templated manifest to `stdout`, instead of installing the manifest on the cluster.
+
+```bash
+cmctl x install --dry-run > cert-manager.custom.yaml
+```
+
+#### Uninstall
+
+```bash
+cmctl x uninstall
+```
+
+This command uninstalls any Helm-managed release of cert-manager.
+
+The CRDs will be deleted if you installed cert-manager with the option `--set CRDs=true`.
+
+Most of the features supported by `helm uninstall` are also supported by this command.
+
+Some example uses:
+
+```bash
+cmctl x uninstall
+
+cmctl x uninstall --namespace my-cert-manager
+
+cmctl x uninstall --dry-run
+
+cmctl x uninstall --no-hooks
+```
+
+### Upgrade
+
+Tools that assist in upgrading cert-manager
+
+```bash
+$ cmctl upgrade --help
+```
+##### Migrate API version
+
+This command can be used to prepare a cert-manager installation that was created
+before cert-manager `v1` for upgrading to a cert-manager version `v1.6` or later.
+It ensures that any cert-manager custom resources that may have been stored in etcd at
+a deprecated API version get migrated to `v1`. See [Migrating Deprecated API
+Resources](https://cert-manager.io/docs/installation/upgrading/remove-deprecated-apis) for more context.
+
+```bash
+$ cmctl upgrade migrate-api-version --qps 5 --burst 10
+```
+
+## Legacy kubectl plugin
+
+While the kubectl plugin is supported, it is recommended to use `cmctl` as this enables a better experience via tab auto-completion.
+
+To install the plugin you need the `kubectl-cert-manager.tar.gz` file for the platform you're using,
+these can be found on our [GitHub releases page](https://github.com/cert-manager/cert-manager/releases).
+In order to use the kubectl plugin you need its binary to be accessible under the name `kubectl-cert_manager` in your `$PATH`.
+
+You can run `kubectl cert-manager help` to test that the plugin is set up properly.
diff --git a/content/v1.12-docs/reference/tls-terminology.md b/content/v1.12-docs/reference/tls-terminology.md
new file mode 100644
index 0000000000..23b6df3447
--- /dev/null
+++ b/content/v1.12-docs/reference/tls-terminology.md
@@ -0,0 +1,79 @@
+---
+title: TLS Terminology
+description: |
+ Learn about the TLS terminology used in the cert-manager documentation such as publicly trusted, self-signed, root, intermediate and leaf certificate
+---
+
+Learn about the TLS terminology used in the cert-manager documentation such as `publicly trusted`, `self-signed`, `root`, `intermediate` and `leaf` _certificate_.
+
+## Overview
+
+With TLS being so widely deployed, terminology can sometimes get confused or be used to mean different things, and that reality
+combined with the complexity of TLS can lead to serious misunderstandings and confusion.
+
+For further reference, you might want to check out some relevant RFCs:
+
+- [RFC 5246: TLS 1.2](https://datatracker.ietf.org/doc/html/rfc5246)
+- [RFC 8446: TLS 1.3](https://datatracker.ietf.org/doc/html/rfc8446)
+- [RFC 5280: X.509](https://datatracker.ietf.org/doc/html/rfc5280)
+
+## Definitions
+
+### `publicly trusted`
+
+What does "publicly trusted" mean?
+
+Broadly speaking, a "publicly trusted" certificate is one that you can use on the Internet and expect
+that most reasonably up-to-date computers will be able to verify it using their system trust store.
+
+There isn't a single standard trust store containing certs which are "publicly trusted", but generally most
+of the commonly seen trust stores are similar. An example would be [Mozilla's CA Certificate Program](https://wiki.mozilla.org/CA).
+
+### What does "self-signed" mean? Is my CA self-signed?
+
+Self-signed means exactly what it says; a certificate is self-signed if it is signed by its own private key.
+
+Self-signed is a commonly confused term, however, and is very frequently misused to mean "not publicly trusted". We tend to use terms
+like "private PKI" to denote the situation where an organization might have their own internal CA certificates which wouldn't
+be trusted outside of the organization.
+
+As an example, there are _many_ self-signed certificates in [Mozilla's CA Certificate Program](https://wiki.mozilla.org/CA), but
+all of those certificates would usually be described as "publicly trusted".
+
+Your certificate is self-signed only if it's signed with its own key.
+
+### What's the difference between "root", "intermediate", and "leaf" certificates?
+
+cert-manager uses the following definitions:
+
+#### Root Certificates
+
+Roots are self-signed certificates and almost always marked as CA certificates. They're usually not sent over the wire
+during a TLS handshake because they need to be explicitly trusted in order to be validated.
+
+Roots are sometimes defined as "CA certificates which are explicitly trusted"---which can include certificates which
+aren't self-signed. cert-manager doesn't use this definition.
+
+Changing trust stores to include new roots or remove old ones is a non-trivial task which can take months or years for publicly
+trusted roots. For this reason roots are usually issued with very long lifetimes, often on the order of decades.
+
+#### Intermediate Certificates
+
+Intermediates are CA certificates signed by another CA. Most intermediates will be signed by a root certificate, but it's
+possible to construct longer chains where an intermediate can be signed by another intermediate.
+
+Intermediate certificates are usually issued with a much shorter lifetime than the CA which signed them. On the
+Internet, intermediate certificates are used on network-connected machines for day-to-day issuance so that the
+highly-valuable root certificates can remain entirely offline.
+
+While intermediate certificates can also be explicitly trusted via addition to a trust store, they're usually validated
+by "walking up" the chain and validating signatures until an explicitly trusted self-signed root certificate is found.
+
+#### Leaf Certificates
+
+Leaf certificates are usually used to represent a particular identity, rather than being used to sign other certificates.
+On the Internet leaf certificates usually identify a particular domain, such as `example.com`.
+
+Leaf certificates are sent first in a chain of certificates and represent the end of that chain. They must be sent
+along with any intermediates required to create a chain which can be validated by verifying signatures up to a trusted
+root certificate.
diff --git a/content/v1.12-docs/troubleshooting/README.md b/content/v1.12-docs/troubleshooting/README.md
new file mode 100644
index 0000000000..fff96f1672
--- /dev/null
+++ b/content/v1.12-docs/troubleshooting/README.md
@@ -0,0 +1,116 @@
+---
+title: Troubleshooting
+description: |
+ Learn how to debug common problems with cert-manager
+---
+
+In this section, you will learn troubleshooting techniques that will help you find the root cause if your Certificate fails to be issued or renewed.
+
+This section also includes the following guides:
+
+* [Troubleshooting Problems with ACME / Let's Encrypt Certificates](./acme.md):
+ Learn more about how the ACME issuer works and how to diagnose problems with it.
+* [Troubleshooting Problems with the Webhook](./webhook.md):
+ Learn how to diagnose problems with the cert-manager webhook.
+
+## Overview
+
+When troubleshooting cert-manager your best friend is `kubectl describe`, this will give you information on the resources as well as recent events. It is not advised to use the logs as these are quite verbose and only should be looked at if the following steps do not provide help.
+
+cert-manager consists of multiple custom resources that live inside your Kubernetes cluster, these resources are linked together and are often created by one another. When such an event happens it will be reflected in a Kubernetes event, you can see these per-namespace using `kubectl get event`, or in the output of `kubectl describe` when looking at a single resource.
+
+## Troubleshooting a failed certificate request
+
+There are several resources that are involved in requesting a certificate.
+
+```
+
+ ( +---------+ )
+ ( | Ingress | ) Optional ACME Only!
+ ( +---------+ )
+ | |
+ | +-------------+ +--------------------+ | +-------+ +-----------+
+ |-> | Certificate |----> | CertificateRequest | ----> | | Order | ----> | Challenge |
+ +-------------+ +--------------------+ | +-------+ +-----------+
+ |
+```
+
+The cert-manager flow all starts at a `Certificate` resource, you can create this yourself or your Ingress resource will do this for you if you have the [correct annotations](../usage/ingress.md) set.
+
+### 1. Checking the Certificate resource
+First we have to check if we have a `Certificate` resource created in our namespace. We can get these using `kubectl get certificate`.
+```console
+$ kubectl get certificate
+NAME READY AGE
+example-com-tls False 1h
+```
+
+If none is present and you plan to use the [ingress-shim](../usage/ingress.md): check the ingress annotations more about that is in the [ingress troubleshooting guide](../usage/ingress.md#troubleshooting).
+If you are not using the ingress-shim: check the output of the command you used to create the certificate.
+
+If you see one with ready status `False` you can get more info using `kubectl describe certificate`, if the status is `True` that means that cert-manager has successfully issued a certificate.
+```console
+$ kubectl describe certificate
+[...]
+Status:
+ Conditions:
+ Last Transition Time: 2020-05-15T21:45:22Z
+ Message: Issuing certificate as Secret does not exist
+ Reason: DoesNotExist
+ Status: False
+ Type: Ready
+ Next Private Key Secret Name: example-tls-wtlww
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Issuing 105s cert-manager Issuing certificate as Secret does not exist
+ Normal Generated 105s cert-manager Stored new private key in temporary Secret resource "example-tls-wtlww"
+ Normal Requested 104s cert-manager Created new CertificateRequest resource "example-tls-bw5t9"
+```
+
+Here you will find more info about the current certificate status under `Status` as well as detailed information about what happened to it under `Events`. Both will help you determine the current state of the certificate.
+The last status is `Created new CertificateRequest resource`, it is worth taking a look at in which state `CertificateRequest` is to get more info on why our `Certificate` isn't getting issued.
+
+### 2. Checking the `CertificateRequest`
+The `CertificateRequest` resource represents a CSR in cert-manager and passes this CSR on onto the issuer.
+You can find the name of the `CertificateRequest` in the `Certificate` event log or using `kubectl get certificaterequest`
+
+To get more info we again run `kubectl describe`:
+```console
+$ kubectl describe certificaterequest
+API Version: cert-manager.io/v1
+Kind: CertificateRequest
+Spec:
+ Request: [...]
+ Issuer Ref:
+ Group: cert-manager.io
+ Kind: ClusterIssuer
+ Name: letencrypt-production
+Status:
+ Conditions:
+ Last Transition Time: 2020-05-15T21:45:36Z
+ Message: Waiting on certificate issuance from order example-tls-fqtfg-1165244518: "pending"
+ Reason: Pending
+ Status: False
+ Type: Ready
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal OrderCreated 8m20s cert-manager Created Order resource example-tls-fqtfg-1165244518
+```
+
+Here we will see any issue regarding the Issuer configuration as well as Issuer responses.
+
+### 3. Check the issuer state
+If in the above steps you saw an issuer not ready error you can do the same steps again for (cluster)issuer resources:
+```console
+$ kubectl describe issuer
+$ kubectl describe clusterissuer
+```
+
+These will allow you to get any error messages regarding accounts or network issues with your issuer.
+Troubleshooting ACME issuers is described in more detail in [Troubleshooting Issuing ACME Certificates](./acme.md).
+
+### 4. ACME Troubleshooting
+ACME (e.g. Let's Encrypt) issuers have 2 additional resources inside cert-manager: `Orders` and `Challenges`.
+Troubleshooting these is described in [Troubleshooting Issuing ACME Certificates](./acme.md).
diff --git a/content/v1.12-docs/troubleshooting/acme.md b/content/v1.12-docs/troubleshooting/acme.md
new file mode 100644
index 0000000000..c8b527b1cf
--- /dev/null
+++ b/content/v1.12-docs/troubleshooting/acme.md
@@ -0,0 +1,226 @@
+---
+title: Troubleshooting Problems with ACME / Let's Encrypt Certificates
+description: |
+ Learn how to diagnose problems if cert-manager fails to renew ACME / Let's Encrypt Certificates.
+---
+
+Learn how to diagnose problems if cert-manager fails to renew ACME / Let's Encrypt Certificates.
+
+## Overview
+
+When requesting ACME certificates, cert-manager will create `Order` and
+`Challenges` to complete the request. As such, there are more resources to
+investigate and debug if there is a problem during the process. You can read
+more about these resources in the [concepts
+pages](../concepts/acme-orders-challenges.md).
+
+Before you start here you should probably take a look at our [general troubleshooting guide](./README.md)
+
+## 1. Troubleshooting (Cluster)Issuers
+
+First of all check if the (Cluster)Issuer you're using is in a ready state:
+```bash
+$ kubectl get issuer
+$ kubectl get clusterissuer
+NAME READY AGE
+letsencrypt True 38m
+letsencrypt-http False 32m
+```
+
+If you see `False` check the status using `kubectl describe`. For example:
+```bash
+$ kubectl describe issuer letsencrypt-http
+$ kubectl describe clusterissuer letsencrypt-http
+Name: letsencrypt
+API Version: cert-manager.io/v1
+Kind: Issuer
+Spec:
+ Acme:
+ Email: cert-manager@example.com
+ Private Key Secret Ref:
+ Name: letsencrypt
+ Server: https://acme-staging-v02.api.letsencrypt.org/directory
+Status:
+ Acme:
+ Conditions:
+ Message: Failed to update ACME account:400 urn:ietf:params:acme:error:invalidEmail: Unable to update account :: invalid contact domain. Contact emails @example.com are forbidden
+ Reason: ErrUpdateACMEAccount
+ Status: False
+ Type: Ready
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Warning ErrUpdateACMEAccount 101s (x3 over 106s) cert-manager Failed to update ACME account:400 urn:ietf:params:acme:error:invalidEmail: Unable to update account :: invalid contact domain. Contact emails @example.com are forbidden
+```
+
+### Common errors
+
+* `Failed to update ACME account:400 urn:ietf:params:acme:error:invalidEmail`: the email you specified in the Issuer configuration isn't valid.
+* `Error initializing issuer: Failed to register ACME account: secrets "acme-key" already exists`: there might be a leftover account from a previous issuer that is no longer valid, you should remove the secret so it can be recreated.
+* `Error accepting challenge: 400 urn:ietf:params:acme:error:malformed: Unable to update challenge :: authorization must be pending`: this suggests that the authorization was not in 'pending' state at a time when cert-manager sent a request to the ACME server to accept the challenge. This may be because the domain validation has already failed and the authorization has been marked as 'invalid'. Check the authorization URL on the status of the `Order` or `Challenge` to see the status of the authorization and any additional information.
+
+## 2. Troubleshooting Orders
+
+When we run a describe on the `CertificateRequest` resource we see that an `Order` that has
+been created:
+
+```bash
+$ kubectl describe certificaterequest example-com-2745722290
+...
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal OrderCreated 5s cert-manager Created Order resource default/example-com-2745722290-439160286
+```
+
+Orders are a request to an ACME instance to issue a certificate.
+By running `kubectl describe order` on a particular order,
+information can be gleaned about failures in the process:
+
+```console
+$ kubectl describe order example-com-2745722290-439160286
+...
+Reason:
+State: pending
+URL: https://acme-v02.api.letsencrypt.org/acme/order/41123272/265506123
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Created 1m cert-manager Created Challenge resource "example-com-2745722290-439160286-0" for domain "test1.example.com"
+ Normal Created 1m cert-manager Created Challenge resource "example-com-2745722290-439160286-1" for domain "test2.example.com"
+```
+
+Here we can see that cert-manager has created two Challenge resources to verify we control specific domains,
+a requirements of the ACME order to obtain a signed certificate.
+
+You can then go on to run
+`kubectl describe challenge example-com-2745722290-439160286-0` to further debug the
+progress of the Order.
+
+Once an Order is successful, you should see an event like the following:
+
+```bash
+$ kubectl describe order example-com-2745722290-439160286
+...
+Reason:
+State: valid
+URL: https://acme-v02.api.letsencrypt.org/acme/order/41123272/265506123
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Created 72s cert-manager Created Challenge resource "example-com-2745722290-439160286-0" for domain "test1.example.com"
+ Normal Created 72s cert-manager Created Challenge resource "example-com-2745722290-439160286-1" for domain "test2.example.com"
+ Normal OrderValid 4s cert-manager Order completed successfully
+```
+
+You can see some additional information about the state of the [ACME authorization](https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.4) that needs to be validated as part of this order using the authorization URL from the status of the `Order`:
+
+```bash
+$ kubectl get order -ojsonpath='{.status.authorizations[x].url}'
+```
+
+If the Order is not completing successfully, you can debug the challenges
+for the Order by running `kubectl describe` on the `Challenge` resource which is described in the following steps.
+
+## 3. Troubleshooting Challenges
+
+In order to determine why an ACME Order is not being finished, we can debug
+using the `Challenge` resources that cert-manager has created.
+
+In order to determine which `Challenge` is failing, you can run
+`kubectl get challenges`:
+
+
+```console
+$ kubectl get challenges
+...
+NAME STATE DOMAIN REASON AGE
+example-com-2745722290-4391602865-0 pending example.com Waiting for dns-01 challenge propagation 22s
+```
+
+This shows that the challenge has been presented using the DNS01 solver
+successfully and now cert-manager is waiting for the 'self check' to pass.
+
+You can get more information about the challenge and it's lifecycle by using `kubectl describe`:
+
+```bash
+$ kubectl describe challenge example-com-2745722290-4391602865-0
+...
+Status:
+ Presented: true
+ Processing: true
+ Reason: Waiting for dns-01 challenge propagation
+ State: pending
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Started 19s cert-manager Challenge scheduled for processing
+ Normal Presented 16s cert-manager Presented challenge using dns-01 challenge mechanism
+```
+
+Progress about the state of each challenge will be recorded either as Events
+or on the Challenge's `status` block (as shown above).
+
+In case of DNS01 you will find any errors from your DNS provider here.
+
+Both HTTP01 and DNS01 go through a "self-check" first before cert-manager presents the challenge to the ACME provider.
+This is done not to overload the ACME provider with failed challenges due to DNS or loadbalancer propagations.
+The status of this can be found in the Status block of the describe:
+```console
+$ kubectl describe challenge
+[...]
+Status:
+ Presented: true
+ Processing: true
+ Reason: Waiting for http-01 challenge propagation: failed to perform self check GET request 'http://example.com/.well-known/acme-challenge/_fgdLz0i3TFiZW4LBjuhjgd5nTOkaMBhxYmTY': Get "http://example.com/.well-known/acme-challenge/_fgdLz0i3TFiZW4LBjuhjgd5nTOkaMBhxYmTY: remote error: tls: handshake failure
+ State: pending
+[...]
+```
+
+In this example our HTTP01 check fails due a network issue.
+You will also see any errors coming from your DNS provider here.
+
+You can also see some additional information about the state of the [ACME authorization](https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.4) that the challenge should validate using the authorization URL on from the status of the `Challenge`:
+
+```bash
+$ kubectl get challenge -ojsonpath='{.spec.authorizationURL}'
+```
+
+### HTTP01 troubleshooting
+First of all check if you can see the challenge URL from the public internet, if this does not work check your Ingress and firewall configuration as well as the service and pod cert-manager created to solve the ACME challenge.
+If this does work check if your cluster can see it too. It is important to test this from inside a Pod. If you get a connection error it is suggested to check the cluster's network configuration.
+If you receive a `tls: handshake failure`, try setting the annotation `cert-manager.io/issue-temporary-certificate: "true"` on the Ingress or Certificate resource. This will issue a temporary self signed certificate for the ingress controller to use before the actual certificate is issued.
+If you still are having issues, there may be an issue with your ingress controller handling multiple resources for the same hostname, in this case, the annotation `acme.cert-manager.io/http01-edit-in-place: "true"` is likely required.
+
+For example when using GKE with the Google Cloud Loadbalancer it is recommended to set:
+```
+cert-manager.io/issue-temporary-certificate: "true"
+acme.cert-manager.io/http01-edit-in-place: "true"
+```
+This will allow the Google Cloud Loadbalancer to propagate a HTTPS endpoint correctly with a temporary certificate, the `http01-edit-in-place` part will prevent GKE from assigning a 2nd IP address for the challenge endpoint.
+
+#### Got 404 status code
+If your challenge self-check fails with a 404 not found error. Make sure to check the following:
+
+* you can access the URL from the public internet
+* the ACME solver pod is up and running
+* use `kubectl describe ingress` to check the status of the HTTP01 solver ingress. (unless you use `acme.cert-manager.io/http01-edit-in-place`, then check the same ingress as your domain)
+
+### DNS01 troubleshooting
+If you see no error events about your DNS provider you can check the following
+Check if you can see the `_acme_challenge.domain` TXT DNS record from the public internet, or in your DNS provider's interface.
+cert-manager will check if a DNS record has been propagated by querying the cluster's DNS solver. If you are able to see it from the public internet but not from inside the cluster you might want to change [the DNS server for self-check](../configuration/acme/dns01/README.md#setting-nameservers-for-dns01-self-check) as some cloud providers overwrite DNS internally.
+
+#### cert-manager identifies the wrong zone for your domain name
+cert-manager by default uses SOA (Start of Authority) records to determine which zone name to use at your DNS provider.
+Some DNS resolvers will filter this information, if this is the case cert-manager cannot determine the zone and it is advised to [change the DNS server for DNS01 self-checks](../configuration/acme/dns01/README.md#setting-nameservers-for-dns01-self-check).
+
+If you use `dnsmasq` as your DNS server, this may occur if you use the [`--filterwin2k` flag](http://www.thekelleys.org.uk/dnsmasq/docs/setup.html).
+In [OpenWRT there is a `filterwin2k` configuration option](https://openwrt.org/docs/guide-user/base-system/dhcp#all_options).
+And in [LuCI there is a "Filter useless" option](https://github.com/openwrt/luci/blob/15757dd5b18f9e00ba3c9b38af4d46702a31fe33/modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js#L217-L219).
+By enabling this flag, `dnsmasq` drops all `SOA` records.
+
+## March 2020 Let's Encrypt CAA Rechecking Bug
+Following the [announcement on March 4](https://community.letsencrypt.org/t/revoking-certain-certificates-on-march-4/114864) Let's Encrypt will be revoking a number of certificates due to a bug in the way they validate CAA records, we have created a tool to analyse your existing cert-manager managed certificates and compare their serial numbers to the publicised list of revoked certificates.
+It's advised that all users of Let's Encrypt & cert-manager run a check using this tool to ensure they do not experience any invalid certificate errors in clusters.
+You can find a copy of the checker tool here: https://github.com/jetstack/letsencrypt-caa-bug-checker.
diff --git a/content/v1.12-docs/troubleshooting/webhook.md b/content/v1.12-docs/troubleshooting/webhook.md
new file mode 100644
index 0000000000..b842dcb9de
--- /dev/null
+++ b/content/v1.12-docs/troubleshooting/webhook.md
@@ -0,0 +1,1071 @@
+---
+title: The Definitive Debugging Guide for the cert-manager Webhook Pod
+description: 'This guide helps you debug communication issues between the Kubernetes API server and the cert-manager webhook Pod.'
+---
+
+> Last verified: 8 Sept 2022
+
+The cert-manager webhook is a pod that runs as part of your cert-manager
+installation. When applying a manifest with `kubectl`, the Kubernetes API server
+calls the cert-manager webhook over TLS to validate your manifests. This guide
+helps you debug communication issues between the Kubernetes API server and the
+cert-manager webhook pod.
+
+The error messages listed in this page are encountered while installing or
+upgrading cert-manager, or shortly after installing or upgrading cert-manager
+when trying to create a Certificate, Issuer, or any other cert-manager custom
+resource.
+
+In the below diagram, we show the common pattern when debugging an issue with
+the cert-manager webhook: when creating a cert-manager custom resource, the API
+server connects over TLS to the cert-manager webhook pod. The red cross
+indicates that the API server fails talking to the webhook.
+
+
+
+The rest of this document presents error messages you may encounter.
+
+## Error: `connect: connection refused`
+
+> This issue was reported in 4 GitHub issues ([#2736](https://github.com/jetstack/cert-manager/issues/2736 "Getting WebHook Connection Refused error when using Azure DevOps Pipelines"), [#3133](https://github.com/jetstack/cert-manager/issues/3133 "Failed calling webhook webhook.cert-manager.io: connect: connection refused"), [#3445](https://github.com/jetstack/cert-manager/issues/3445 "Connection refused for cert-manager-webhook service"), [#4425](https://github.com/cert-manager/cert-manager/issues/4425 "Webhook error")), was reported in 1 GitHub issue in an external project ([`aws-load-balancer-controller#1563`](https://github.com/kubernetes-sigs/aws-load-balancer-controller/issues/1563 "Internal error occurred: failed calling webhook webhook.cert-manager.io, no endpoints available")), on Stack Overflow ([`serverfault#1076563`](https://web.archive.org/web/20210903183221/https://serverfault.com/questions/1076563/creating-issuer-for-kubernetes-cert-manager-is-causing-404-and-500-error "Creating issuer for kubernetes cert-manager is causing 404 and 500 error")), and was mentioned in 13 Slack messages that can be listed with the search `in:#cert-manager in:#cert-manager-dev ":443: connect: connection refused"`. This error message can also be found in other projects that are building webhooks ([`kubewarden-controller#110`](https://github.com/kubewarden/kubewarden-controller/issues/110 "Investigate failure on webhooks not ready when installing cert-manager from helm chart: connection refused")).
+
+Shortly after installing or upgrading cert-manager, you may hit this error when
+creating a Certificate, Issuer, or any other cert-manager custom resource. For
+example, creating an Issuer resource with the following command:
+
+```sh
+kubectl apply -f- < 10.96.20.99 (webhook pod) TCP 59466 → 443 [SYN]
+10.96.20.99 (webhook pod) -> 192.168.1.43 (apiserver) TCP 443 → 59466 [RST, ACK]
+```
+
+The `RST` packet is sent by the Linux kernel when nothing is listening to the
+requested port. The `RST` packet can also be returned by one of the TCP hops,
+e.g., a firewall, as detailed in the Stack Overflow page [What can be the
+reasons of connection refused errors?](https://stackoverflow.com/a/2333446/3808537)
+
+Note that firewalls usually don't return an `RST` packet; they usually drop the
+`SYN` packet entirely, and you end up with the error message `i/o timeout` or
+`context deadline exceeded`. If that is the case, continue your investigation
+with the section [Error: `i/o timeout` (connectivity issue)](#io-timeout) and [Error: `context
+deadline exceeded`](#context-deadline-exceeded) respectively.
+
+Let's eliminate the possible causes from the closest to the source of the TCP
+connection (the API server) to its destination (the pod `cert-manager-webhook`).
+
+Let's imagine that the name `cert-manager-webhook.cert-manager.svc` was resolved
+to 10.43.183.232. This is a cluster IP. The control plane node, in which the API
+server process runs, uses its iptables to rewrite the IP destination using the
+pod IP. That might be the first problem: sometimes, no pod IP is associated with
+a given cluster IP because the kubelet doesn't fill in the Endpoint resource
+with pod IPs as long as the readiness probe doesn't work.
+
+Let us first check whether it is a problem with the Endpoint resource:
+
+```sh
+kubectl get endpoints -n cert-manager cert-manager-webhook
+```
+
+A valid output would look like this:
+
+```text
+NAME ENDPOINTS AGE
+cert-manager-webhook 10.244.0.2:10250 27d ✅
+```
+
+If you have this valid output and have the `connect: connection refused`, then
+the issue is deeper in the networking stack. We won't dig into this case, but
+you might want to use `tcpdump` and Wireshark to see whether traffic properly
+flows from the API server to the node's host namespace. The traffic from the
+host namespace to the pod's namespace already works fine since the kubelet was
+already able to reach the readiness endpoint.
+
+Common issues include firewall dropping traffic from the control plane to
+workers; for example, the API server on GKE is only allowed to talk to worker
+nodes (which is where the cert-manager webhook is running) over port
+`10250`. In EKS, your security groups might deny traffic from your control
+plane VPC towards your workers VPC over TCP `10250`.
+
+If you see ``, it indicates that the cert-manager webhook is properly
+running but its readiness endpoint can't be reached:
+
+```text
+NAME ENDPOINTS AGE
+cert-manager-webhook 236d ❌
+```
+
+To fix ``, you will have to check whether the cert-manager-webhook
+deployment is healthy. The endpoints stays at `` while the
+cert-manager-webhook isn't marked as `healthy`.
+
+```sh
+kubectl get pod -n cert-manager -l app.kubernetes.io/name=webhook
+```
+
+You should see that the pod is `Running`, and that the number of containers that
+are ready is `0/1`:
+
+```text
+NAME READY STATUS RESTARTS AGE
+cert-manager-76578c9687-24kmr 0/1 Running 7 (8h ago) 28d ❌
+```
+
+We won't be detailing the case where you get `1/1` and `Running`, since it would
+indicate an inconsistent state in Kubernetes.
+
+Continuing with `0/1`, that means the readiness endpoint isn't answering. When
+that happens, no endpoint is created. The next step is to figure out why the
+readiness endpoint isn't answering. Let us see which port the kubelet is using
+when hitting the readiness endpoint:
+
+```sh
+kubectl -n cert-manager get deploy cert-manager-webhook -oyaml | grep -A5 readiness
+```
+
+In our example, the port that the kubelet will try to hit is 6080:
+
+```yaml
+readinessProbe:
+ failureThreshold: 3
+ httpGet:
+ path: /healthz
+ port: 6080 # ✨
+ scheme: HTTP
+```
+
+Now, let us port-forward to that port and see if `/healthz` works. In a shell
+session, run:
+
+```sh
+kubectl -n cert-manager port-forward deploy/cert-manager-webhook 6080
+```
+
+In another shell session, run:
+
+```sh
+curl -sS --dump-header - 127.0.0.1:6080/healthz
+```
+
+The happy output is:
+
+```http
+HTTP/1.1 200 OK ✅
+Date: Tue, 07 Jun 2022 17:16:56 GMT
+Content-Length: 0
+```
+
+If the readiness endpoint doesn't work, you will see:
+
+```text
+curl: (7) Failed to connect to 127.0.0.1 port 6080 after 0 ms: Connection refused ❌
+```
+
+At this point, verify that the readiness endpoint is configured on that same
+port. Let us see the logs to check that our webhook is listening on 6080 for its
+readiness endpoint:
+
+```console
+$ kubectl logs -n cert-manager -l app.kubernetes.io/name=webhook | head -10
+I0607 webhook.go:129] "msg"="using dynamic certificate generating using CA stored in Secret resource"
+I0607 server.go:133] "msg"="listening for insecure healthz connections" "address"=":6081" ❌
+I0607 server.go:197] "msg"="listening for secure connections" "address"=":10250"
+I0607 dynamic_source.go:267] "msg"="Updated serving TLS certificate"
+...
+```
+
+In the above example, the issue was a misconfiguration of the readiness port. In
+the webhook deployment, the argument `--healthz-port=6081` was mismatched with
+the readiness configuration.
+
+
+
+## Error: `i/o timeout` (connectivity issue)
+
+> This error message was reported 26 times on Slack. To list these messages, do a search with `in:#cert-manager in:#cert-manager-dev "443: i/o timeout"`. The error message was reported in 2 GitHub issues ([#2811](https://github.com/cert-manager/cert-manager/issues/2811 "i/o timeout from apiserver when connecting to webhook on k3s"), [#4073](https://github.com/cert-manager/cert-manager/issues/4073 "Internal error occurred: failed calling webhook"))
+
+```text
+Error from server (InternalError): error when creating "STDIN": Internal error occurred:
+ failed calling webhook "webhook.cert-manager.io": failed to call webhook:
+ Post "https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=10s":
+ dial tcp 10.0.0.69:443: i/o timeout
+```
+
+When the API server tries to talk to the cert-manager webhook, the `SYN` packet
+is never answered, and the connection times out. If we were to run tcpdump
+inside the webhook's net namespace, we would see:
+
+```text
+192.168.1.43 (apiserver) -> 10.0.0.69 (webhook pod) TCP 44772 → 443 [SYN]
+192.168.1.43 (apiserver) -> 10.0.0.69 (webhook pod) TCP [TCP Retransmission] 44772 → 443 [SYN]
+192.168.1.43 (apiserver) -> 10.0.0.69 (webhook pod) TCP [TCP Retransmission] 44772 → 443 [SYN]
+192.168.1.43 (apiserver) -> 10.0.0.69 (webhook pod) TCP [TCP Retransmission] 44772 → 443 [SYN]
+```
+
+This issue is caused by the `SYN` packet being dropped somewhere.
+
+
+
+### Cause 1: GKE Private Cluster
+
+The default Helm configuration should work with GKE private clusters, but
+changing `securePort` might break it.
+
+For context, unlike public GKE clusters where the control plane can freely talk
+to pods over any TCP port, the control plane in private GKE clusters can only
+talk to the pods in worker nodes over TCP port `10250` and `443`. These two open
+ports refer to the `containerPort` inside the pod, not the port called `port` in
+the Service resource.
+
+For it to work, the `containerPort` inside the Deployment must match either
+`10250` or `443`; `containerPort` is configured by the Helm value
+`webhook.securePort`. By default, `webhook.securePort` is set to `10250`.
+
+To see if something is off with the `containerPort`, let us start looking at the
+Service resource:
+
+```sh
+kubectl get svc -n cert-manager cert-manager-webhook -oyaml
+```
+
+Looking at the output, we see that the `targetPort` is set to `"https"`:
+
+```yaml
+apiVersion: v1
+kind: Service
+metadata:
+ name: cert-manager-webhook
+spec:
+ ports:
+ - name: https
+ port: 443 # ❌ This port is not the cause.
+ protocol: TCP
+ targetPort: "https" # 🌟 This port might be the cause.
+```
+
+The reason the above `port: 443` can't be the cause is because kube-proxy, which
+also runs on the control plane node, translates the webhook's cluster IP to a
+pod IP, and also translates the above `port: 443` to the value in
+`containerPort`.
+
+To see how what is behind the target port `"https"`, we look at the
+Deployment resource:
+
+```sh
+kubectl get deploy -n cert-manager cert-manager-webhook -oyaml | grep -A3 ports:
+```
+
+The output shows that the `containerPort` is not set to `10250`, meaning that
+a new firewall rule will have to be added in Google Cloud.
+
+```yaml
+ ports:
+ - containerPort: 12345 # 🌟 This port matches neither 10250 nor 443.
+ name: https
+ protocol: TCP
+```
+
+To recap, if the above `containerPort` is something other than `443` or `10250` and
+you prefer not changing `containerPort` to `10250`, you will have to add a
+new firewall rule. You can read the section [Adding a firewall rule in a
+GKE private
+cluster](https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters#add_firewall_rules)
+in the Google documentation.
+
+For context, the reason we did not default `securePort` to `443` is because
+binding to `443` requires one additional Linux capability
+(`NET_BIND_SERVICE`); on the other side, `10250` doesn't require any
+additional capability.
+
+### Cause 2: EKS on a custom CNI
+
+If you are on EKS and you are using a custom CNI such as Weave or Calico,
+the Kubernetes API server (which is in its own node) might not be able to
+reach the webhook pod. This happens because the control plane cannot be
+configured to run on a custom CNI on EKS, meaning that the CNIs cannot
+enable connectivity between the API server and the pods running in the
+worker nodes.
+
+Supposing that you are using Helm, the workaround is to add the following
+value in your `values.yaml` file:
+
+```yaml
+webhook:
+ hostNetwork: true
+ securePort: 10260
+```
+
+Or if you are using Helm from the command-line, use the following flag:
+
+```sh
+--set webhook.hostNetwork=true --set webhook.securePort=10260
+```
+
+By setting `hostNetwork` to `true`, the webhook pod will be run in the
+host's network namespace. By running in the host's network namespace, the
+webhook pod becomes accessible over the node's IP, which means you will
+work around the fact that kube-apiserver can't reach any pod IPs nor
+cluster IPs.
+
+By setting `securePort` to `10260` instead of relying on the default value
+(which is `10250`), you will prevent a conflict between the webhook and the
+kubelet. The kubelet, which is an agent that runs on every Kubernetes
+worker node and runs directly on the host, uses the port `10250` to
+expose its internal API to kube-apiserver.
+
+To understand how `hostnetwork` and `securePort` interact, we have to look
+at how the TCP connection is established. When the kube-apiserver process
+tries to connect to the webhook pod, kube-proxy (which also runs on control
+plane nodes, even without a CNI) kicks in and translates the webhook's
+cluster IP to the webhook's host IP:
+
+```diagram
+ https://cert-manager-webhook.cert-manager.svc:443/validate
+ |
+ |Step 1: resolve to the cluster IP
+ v
+ https://10.43.103.211:443/validate
+ |
+ |Step 2: send TCP packet
+ v
+ src: 172.28.0.1:43021
+ dst: 10.43.103.211:443
+ |
+ |Step 3: kube-proxy rewrite (cluster IP to host IP)
+ v
+ src: 172.28.0.1:43021
+ dst: 172.28.0.2:10260
+ |
+ | control-plane node
+ | (host IP: 172.28.0.1)
+------------|--------------------------------------------------
+ | (host IP: 172.28.0.2)
+ v worker node
+ +-------------------+
+ | webhook pod |
+ | listens on |
+ | 172.28.0.2:10260 |
+ +-------------------+
+```
+
+The reason `10250` is used as the default `securePort` is because it works
+around another limitation with GKE Private Clusters, as detailed in the
+above section [GKE Private Cluster](#gke-private-cluster).
+
+### Cause 3: Network Policies, Calico
+
+Assuming that you are using the Helm chart and that you are using the
+default value of `webhook.securePort` (which is `10250`), and that you are
+using a network policy controller such as Calico, check that there exists a
+policy allowing traffic from the API server to the webhook pod over TCP
+port `10250`.
+
+### Cause 4: EKS and Security Groups
+
+Assuming that you are using the Helm chart and that you are using the
+default value of `webhook.securePort` (which is `10250`), you might want to
+check that your AWS Security Groups allow TCP traffic over `10250` from the
+control plane's VPC to the workers VPC.
+
+### Other causes
+
+If none of the above causes apply, you will need to figure out why the
+webhook is unreachable.
+
+To debug reachability issues (i.e., packets being dropped), we advise to
+use `tcpdump` along with Wireshark at every TCP hop. You can follow the
+article [Debugging Kubernetes Networking: my `kube-dns` is not
+working!](https://maelvls.dev/debugging-kubernetes-networking/) to learn
+how to use `tcpdump` with Wireshark to debug networking issues.
+
+## Error: `x509: certificate is valid for xxx.internal, not cert-manager-webhook.cert-manager.svc` (EKS with Fargate pods)
+
+```text
+Internal error occurred: failed calling webhook "webhook.cert-manager.io":
+ Post https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=30s:
+ x509: certificate is valid for ip-192-168-xxx-xxx.xxx.compute.internal,
+ not cert-manager-webhook.cert-manager.svc
+```
+
+> This issue was first reported in
+> [#3237](https://github.com/cert-manager/cert-manager/issues/3237 "Can't
+> create an issuer when cert-manager runs on EKS in Fargate pods (AWS)").
+
+This is probably because you are running on EKS with Fargate enabled.
+Fargate creates a microVM per pod, and the VM's kernel is used to run the
+container in its own namespace. The problem is that each microVM gets its
+own kubelet. As for any Kubernetes node, the VM's port `10250` is listened to
+by a kubelet process. And `10250` is also the port that the cert-manager
+webhook listens on.
+
+But that's not a problem: the kubelet process and the cert-manager webhook
+process are running in two separate network namespaces, and ports don't
+clash. That's the case both in traditional Kubernetes nodes, as well as
+inside a Fargate microVM.
+
+The problem arises when the API server tries hitting the Fargate pod: the
+microVM's host net namespace is configured to port-forward every possible port
+for maximum compatibility with traditional pods, as demonstrated in the Stack
+Overflow page [EKS Fargate connect to local kubelet][66445207]. But the port
+`10250` is already used by the microVM's kubelet, so anything hitting this port
+won't be port-forwarded and will hit the kubelet instead.
+
+[66445207]: https://stackoverflow.com/questions/66445207 "EKS Fargate connect to local kubelet"
+
+To sum up, the cert-manager webhook looks healthy and is able to listen to port
+`10250` as per its logs, but the microVM's host does not port-forward `10250` to the
+webhook's net namespace. That's the reason you see a message about an unexpected
+domain showing up when doing the TLS handshake: although the cert-manager
+webhook is properly running, the kubelet is the one responding to the API
+server.
+
+This is a limitation of Fargate's microVMs: the IP of the pod and the IP of the
+node are the same. It gives you the same experience as traditional pods, but it
+poses networking challenges.
+
+To fix the issue, the trick is to change the port the cert-manager webhook is
+listening on. Using Helm, we can use the parameter `webhook.securePort`:
+
+```sh
+helm install \
+ cert-manager jetstack/cert-manager \
+ --namespace cert-manager \
+ --create-namespace \
+ --version v1.8.0 \
+ --set webhook.securePort=10260
+```
+
+## Error: `service "cert-managercert-manager-webhook" not found`
+
+```text
+Error from server (InternalError): error when creating "test-resources.yaml": Internal error occurred:
+ failed calling webhook "webhook.cert-manager.io": failed to call webhook:
+ Post "https://cert-managercert-manager-webhook.cert-manager.svc:443/mutate?timeout=10s":
+ service "cert-managercert-manager-webhook" not found
+```
+
+> This error was reported in 2 GitHub issues ([#3195](https://github.com/jetstack/cert-manager/issues/3195 "service cert-manager-webhook not found"),
+> [#4999](https://github.com/cert-manager/cert-manager/issues/4999 "Verification on 1.7.2 fails (Kubectl apply), service cert-manager-webhook not found")).
+
+We do not know the cause of this error, please comment on one of the GitHub
+issues above if you happen to come across it.
+
+## Error: `no endpoints available for service "cert-manager-webhook"` (OVHCloud)
+
+```text
+Error: INSTALLATION FAILED: Internal error occurred:
+ failed calling webhook "webhook.cert-manager.io":
+ Post https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=30s:
+ no endpoints available for service "cert-manager-webhook"
+```
+
+> This issue was first reported once in Slack
+> ([1](https://kubernetes.slack.com/archives/C4NV3DWUC/p1634118489064400?thread_ts=1592676867.472700&cid=C4NV3DWUC)).
+
+This error is rare and was only seen in OVHcloud managed Kubernetes clusters,
+where the etcd resource quota is quite low. etcd is the database where your
+Kubernetes resources (such as pods and deployments) are stored. OVHCloud limits
+the disk space used by your resources in etcd. When the limit is reached, the
+whole cluster starts behaving erratically and one symptom is that Endpoint
+resources aren't created by the kubelet.
+
+To verify that it is in fact a problem of quota, you should be able to see the
+following messages in your kube-apiserver logs:
+
+```sh
+rpc error: code = Unknown desc = ETCD storage quota exceeded
+rpc error: code = Unknown desc = quota computation: etcdserver: not capable
+rpc error: code = Unknown desc = The OVHcloud storage quota has been reached
+```
+
+The workaround is to remove some resources such as CertificateRequest resources
+to get under the limit, as explained in OVHCloud's [ETCD Quotas error,
+troubleshooting](https://docs.ovh.com/gb/en/kubernetes/etcd-quota-error/) page.
+
+## Error: `x509: certificate has expired or is not yet valid`
+
+> This error message was reported once in Slack
+> ([1](https://kubernetes.slack.com/archives/C4NV3DWUC/p1618579222346800)).
+
+When using `kubectl apply`:
+
+```text
+Internal error occurred: failed calling webhook "webhook.cert-manager.io":
+ Post https://kubernetes.default.svc:443/apis/webhook.cert-manager.io/v1beta1/mutations?timeout=30s:
+ x509: certificate has expired or is not yet valid
+```
+
+> This error message was reported once in Slack
+([1](https://kubernetes.slack.com/archives/C4NV3DWUC/p1618579222346800)).
+
+Please answer to the above Slack message since we are still unsure as to what
+may cause this issue; to get access to the Kubernetes Slack, visit
+[https://slack.k8s.io/](https://slack.k8s.io/).
+
+## Error: `net/http: request canceled while waiting for connection`
+
+```text
+Error from server (InternalError): error when creating "STDIN":
+ Internal error occurred: failed calling webhook "webhook.cert-manager.io":
+ Post https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=30s:
+ net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
+```
+
+> This error message was reported once in Slack
+([1](https://kubernetes.slack.com/archives/C4NV3DWUC/p1632849763397100)).
+
+
+
+## Error: `context deadline exceeded`
+
+> This error message was reported in GitHub issues ([2319](https://github.com/cert-manager/cert-manager/issues/2319 "Documenting context deadline exceeded errors relating to the webhook, on bare metal"), [2706](https://github.com/cert-manager/cert-manager/issues/2706 "") [5189](https://github.com/cert-manager/cert-manager/issues/5189 "Post https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=10s: context deadline exceeded"), [5004](https://github.com/cert-manager/cert-manager/issues/5004 "After installing cert-manager using kubectl, cmctl check api fails with https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=10s: context deadline exceeded")), and once [on Stack Overflow](https://stackoverflow.com/questions/72059332/how-can-i-fix-failed-calling-webhook-webhook-cert-manager-io).
+
+This error appears with cert-manager 0.12 and above when trying to apply an
+Issuer or any other cert-manager custom resource after having installed or
+upgraded cert-manager:
+
+```text
+Error from server (InternalError): error when creating "STDIN":
+ Internal error occurred: failed calling webhook "webhook.cert-manager.io":
+ Post https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=30s:
+ context deadline exceeded
+```
+
+> ℹ️ In older releases of cert-manager (0.11 and below), the webhook relied on
+> the [APIService
+> mechanism](https://kubernetes.io/docs/tasks/extend-kubernetes/setup-extension-api-server/),
+> and the message looked a bit different but the cause was the same:
+>
+> ```text
+> Error from server (InternalError): error when creating "STDIN":
+> Internal error occurred: failed calling webhook "webhook.certmanager.k8s.io":
+> Post https://kubernetes.default.svc:443/apis/webhook.certmanager.k8s.io/v1beta1/mutations?timeout=30s:
+> context deadline exceeded
+> ```
+
+> ℹ️ The message `context deadline exceeded` also appears when using `cmctl
+> check api`. The cause is identical, you can continue reading this section to
+> debug it.
+>
+> ```text
+> Not ready: Internal error occurred: failed calling webhook "webhook.cert-manager.io": failed to call webhook:
+> Post "https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=10s":
+> context deadline exceeded
+> ```
+
+The trouble with the message `context deadline exceeded` is that it obfuscates
+the part of the HTTP connection that timed out. When this message appears, we
+can't tell which part of the HTTP interaction timed out. It might be the DNS
+resolution, the TCP handshake, the TLS handshake, sending the HTTP request or
+receiving the HTTP response.
+
+> ℹ️ For context, the query parameter `?timeout=30s` that you can see in the
+> above error messages is a timeout that the API server decides when calling the
+> webhook. It is often set to 10 or 30 seconds.
+
+The following diagram shows what are the three errors that may be hidden behind
+the all-catching "context deadline exceeded" error message, represented by the
+outer box, that is usually thrown after 30 seconds:
+
+
+
+```diagram
+ context deadline exceeded
+ |
+ 30 seconds |
+ timeout v
+ +-------------------------------------------------------------------------+
+ | |
+ | i/o timeout |
+ | | net/http: TLS handshake timeout |
+ | 10 seconds | | |
+ | timeout v | |
+ |------------+ 30 seconds | net/http: request canceled |
+ |TCP | timeout v while awaiting headers |
+ |handshake +---------------------+ | |
+ |------------| TLS | | |
+ | | handshake +------------+ 10 seconds | |
+ | +---------------------| sending | timeout v |
+ | | request +------------+ |
+ | +------------|receiving |------+ |
+ | |resp. header| recv.| |
+ | +------------+ resp.| |
+ | | body +-----+
+ | +------|other|
+ | |logic|
+ | +-----+
+ +-------------------------------------------------------------------------+
+ <----------> <---------------------------------------------->
+ connectivity webhook-side
+ issue issue
+```
+
+In the rest of the section, we will be trying to trigger one of the three "more
+specific" errors:
+
+- `i/o timeout` is the TCP handshake timeout and comes from
+ [`DialTimeout`](https://pkg.go.dev/net#DialTimeout) in the Kubernetes
+ apiserver. The name resolution may be the cause, but usually, this message
+ appears after the API server sent the `SYN` packet and waited for 10 seconds
+ for the `SYN-ACK` packet to be received from the cert-manager webhook.
+- `net/http: request canceled while waiting for connection (Client.Timeout
+ exceeded while awaiting headers)` is the HTTP response timeout and comes from
+ [here](https://github.com/kubernetes/kubernetes/blob/abba1492f/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go#L96-L101)
+ and is configured to [30
+ seconds](https://github.com/kubernetes/kubernetes/blob/abba1492f/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go#L36-L38).
+ The Kubernetes API server already sent the HTTP request is is waiting for the
+ HTTP response headers (e.g., `HTTP/1.1 200 OK`).
+- `net/http: TLS handshake timeout` is when the TCP handshake is done, and the
+ Kubernetes API server sent the initial TLS handshake packet (`ClientHello`)
+ and waited for 10 seconds for the cert-manager webhook to answer with the
+ `ServerHello` packet.
+
+We can sort these three messages in two categories: either it is a connectivity
+issue (`SYN` is dropped), or it is a webhook issue (i.e., the TLS certificate is
+wrong, or the webhook is not returning any HTTP response):
+
+| Timeout message | Category |
+|-----------------------------------------------------|--------------------|
+| `i/o timeout` | connectivity issue |
+| `net/http: TLS handshake timeout` | webhook-side issue |
+| `net/http: request canceled while awaiting headers` | webhook-side issue |
+
+The first step is to rule out a webhook-side issue. In your shell session, run
+the following:
+
+```sh
+kubectl -n cert-manager port-forward deploy/cert-manager-webhook 10250
+```
+
+In another shell session, check that you can reach the webhook:
+
+```sh
+curl -vsS --resolve cert-manager-webhook.cert-manager.svc:10250:127.0.0.1 \
+ --service-name cert-manager-webhook-ca \
+ --cacert <(kubectl -n cert-manager get secret cert-manager-webhook-ca -ojsonpath='{.data.ca\.crt}' | base64 -d) \
+ https://cert-manager-webhook.cert-manager.svc:10250/validate 2>&1 -d@- <<'EOF' | sed '/^* /d; /bytes data]$/d; s/> //; s/< //'
+{"kind":"AdmissionReview","apiVersion":"admission.k8s.io/v1","request":{"requestKind":{"group":"cert-manager.io","version":"v1","kind":"Certificate"},"requestResource":{"group":"cert-manager.io","version":"v1","resource":"certificates"},"name":"foo","namespace":"default","operation":"CREATE","object":{"apiVersion":"cert-manager.io/v1","kind":"Certificate","spec":{"dnsNames":["foo"],"issuerRef":{"group":"cert-manager.io","kind":"Issuer","name":"letsencrypt"},"secretName":"foo","usages":["digital signature"]}}}}
+EOF
+```
+
+The happy output looks like this:
+
+```http
+POST /validate HTTP/1.1
+Host: cert-manager-webhook.cert-manager.svc:10250
+User-Agent: curl/7.83.0
+Accept: */*
+Content-Length: 1299
+Content-Type: application/x-www-form-urlencoded
+
+HTTP/1.1 200 OK
+Date: Wed, 08 Jun 2022 14:52:21 GMT
+Content-Length: 2029
+Content-Type: text/plain; charset=utf-8
+
+...
+"response": {
+ "uid": "",
+ "allowed": true
+}
+```
+
+If the response shows `200 OK`, we can rule out a webhook-side issue. Since the
+initial error message was `context deadline exceeded` and not an apiserver-side
+issue such as `x509: certificate signed by unknown authority` or `x509:
+certificate has expired or is not yet valid`, we can conclude that the problem
+is a connectivity issue: the Kubernetes API server isn't able to establish a TCP
+connection to the cert-manager webhook. Please follow the instructions in the
+section [Error: `i/o timeout` (connectivity issue)](#io-timeout) above to
+continue debugging.
+
+## Error: `net/http: TLS handshake timeout`
+
+> This error message was reported in 1 GitHub issue ([#2602](https://github.com/cert-manager/cert-manager/issues/2602 "Internal error occurred: failed calling webhook webhook.cert-manager.io: Post https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=30s: net/http: TLS handshake timeout")).
+
+```text
+Error from server (InternalError): error when creating "STDIN":
+ Internal error occurred: failed calling webhook "webhook.cert-manager.io":
+ Post https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=30s:
+ net/http: TLS handshake timeout
+```
+
+Looking at the [above diagram](#diagram), this error message indicates that the
+Kubernetes API server successfully established a TCP connection to the pod IP
+associated with the cert-manager webhook. The TLS handshake timeout means that
+the cert-manager webhook process isn't the one ending the TCP connection: there
+is some HTTP proxy in between that is probably waiting for a plain HTTP request
+instead a `ClientHello` packet.
+
+We do not know the cause of this error. Please comment on the above GitHub
+issue if you notice this error.
+
+## Error: `HTTP probe failed with statuscode: 500`
+
+> This error message was reported in 2 GitHub issue ([#3185](https://github.com/cert-manager/cert-manager/issues/3185 "kubectl install cert-manager: Readiness probe failed: HTTP probe failed with statuscode: 500"), [#4557](https://github.com/cert-manager/cert-manager/issues/4557 "kubectl install cert-manager: Readiness probe failed: HTTP probe failed with statuscode: 500")).
+
+The error message is visible as an event on the cert-manager webhook:
+
+```text
+Warning Unhealthy (x13 over 15s) kubelet, node83
+ Readiness probe failed: HTTP probe failed with statuscode: 500
+```
+
+We do not know the cause of this error. Please comment on the above GitHub
+issue if you notice this error.
+
+## Error: `Service Unavailable`
+
+> This error was reported in 1 GitHub issue ([#4281](https://github.com/cert-manager/cert-manager/issues/4281 "Can't deploy Issuer, Service Unavailable"))
+
+```text
+Error from server (InternalError): error when creating "STDIN": Internal error occurred:
+ failed calling webhook "webhook.cert-manager.io":
+ Post "https://my-cert-manager-webhook.default.svc:443/mutate?timeout=10s":
+ Service Unavailable
+```
+
+The above message appears in Kubernetes clusters using the Weave CNI.
+
+We do not know the cause of this error. Please comment on the above GitHub
+issue if you notice this error.
+
+## Error: `failed calling admission webhook: the server is currently unable to handle the request`
+
+> This issue was reported in 4 GitHub issues ([1369](https://github.com/cert-manager/cert-manager/issues/1369 "the server is currently unable to handle the request"), [1425](https://github.com/cert-manager/cert-manager/issues/1425 "Verifying Install: failed calling admission webhook (Azure, GKE private cluster)") [3542](https://github.com/cert-manager/cert-manager/issues/3542 "SSL Certificate Manager has got expired, we need to renew SSL certificate in existing ClusterIssuer Kubernetes Service (AKS)"), [4852](https://github.com/cert-manager/cert-manager/issues/4852 "error: unable to retrieve the complete list of server APIs: webhook.cert-manager.io/v1beta1: the server is currently unable to handle the request (AKS)"))
+
+```text
+Error from server (InternalError): error when creating "test-resources.yaml": Internal error occurred:
+ failed calling admission webhook "issuers.admission.certmanager.k8s.io":
+ the server is currently unable to handle the request
+```
+
+We do not know the cause of this error. Please comment in one of the above
+GitHub issues if you are able to reproduce this error.
+
+## Error: `x509: certificate signed by unknown authority`
+
+> Reported in GitHub issues
+> ([2602](https://github.com/cert-manager/cert-manager/issues/2602#issuecomment-606474055 "x509: certificate signed by unknown authority"))
+
+When installing or upgrading cert-manager and using a namespace that is not
+`cert-manager`:
+
+```text
+Error: UPGRADE FAILED: release core-l7 failed, and has been rolled back due to atomic being set:
+ failed to create resource: conversion webhook for cert-manager.io/v1alpha3, Kind=ClusterIssuer failed:
+ Post https://cert-manager-webhook.core-l7.svc:443/convert?timeout=30s:
+ x509: certificate signed by unknown authority
+```
+
+A very similar error message may show when creating an Issuer or any other
+cert-manager custom resource:
+
+```text
+Internal error occurred: failed calling webhook "webhook.cert-manager.io":
+ Post https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=30s:
+ x509: certificate signed by unknown authority`
+```
+
+With `cmctl install` and `cmctl check api`, you might see the following error
+message:
+
+```text
+2022/06/06 15:36:30 Not ready: the cert-manager webhook CA bundle is not injected yet
+ (Internal error occurred: conversion webhook for cert-manager.io/v1alpha2, Kind=Certificate failed:
+ Post "https://-cert-manager-webhook.cert-manager.svc:443/convert?timeout=30s":
+ x509: certificate signed by unknown authority)
+```
+
+If you are using cert-manager 0.14 and below with Helm, and that you are
+installing in a namespace different from `cert-manager`, the CRD manifest had
+the namespace name `cert-manager` hardcoded. You can see the hardcoded namespace
+in the following annotation:
+
+```sh
+kubectl get crd issuers.cert-manager.io -oyaml | grep inject
+```
+
+You will see the following:
+
+```yaml
+cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca
+# ^^^^^^^^^^^^
+# hardcoded
+```
+
+> **Note 1:** this bug in the cert-manager Helm chart was [was
+fixed](https://github.com/cert-manager/cert-manager/commit/f33beefc) in
+cert-manager 0.15.
+>
+> **Note 2:** since cert-manager 1.6, this annotation is [no longer
+> used](https://github.com/cert-manager/cert-manager/pull/4841) on the
+> cert-manager CRDs since conversion is no longer needed.
+
+The solution, if you are still using cert-manager 0.14 or below, is to render
+the manifest using `helm template`, then edit the annotation to use the correct
+namespace, and then use `kubectl apply` to install cert-manager.
+
+If you are using cert-manager 1.6 and below, the issue might be due to the
+cainjector being stuck trying to inject the self-signed certificate that the
+cert-manager webhook created and stored in the Secret resource
+`cert-manager-webhook-ca` into the `spec.caBundle` field of the cert-manager
+CRDs. The first step is to check whether the cainjector is running with no
+problem:
+
+```console
+$ kubectl -n cert-manager get pods -l app.kubernetes.io/name=cainjector
+NAME READY STATUS RESTARTS AGE
+cert-manager-cainjector-5c55bb7cb4-6z4cf 1/1 Running 11 (31h ago) 28d
+```
+
+Looking at the logs, you will be able to tell if the leader election worked. It
+can take up to one minute for the leader election work to complete.
+
+```console
+I0608 start.go:126] "starting" version="v1.8.0" revision="e466a521bc5455def8c224599c6edcd37e86410c"
+I0608 leaderelection.go:248] attempting to acquire leader lease kube-system/cert-manager-cainjector-leader-election...
+I0608 leaderelection.go:258] successfully acquired lease kube-system/cert-manager-cainjector-leader-election
+I0608 controller.go:186] cert-manager/secret/customresourcedefinition/controller/controller-for-secret-customresourcedefinition "msg"="Starting Controller"
+I0608 controller.go:186] cert-manager/certificate/customresourcedefinition/controller/controller-for-certificate-customresourcedefinition "msg"="Starting Controller"
+I0608 controller.go:220] cert-manager/secret/customresourcedefinition/controller/controller-for-secret-customresourcedefinition "msg"="Starting workers" "worker count"=1
+I0608 controller.go:220] cert-manager/certificate/customresourcedefinition/controller/controller-for-certificate-customresourcedefinition "msg"="Starting workers" "worker count"=1
+```
+
+The happy output contains lines like this:
+
+```console
+I0608 sources.go:184] cert-manager/secret/customresourcedefinition/generic-inject-reconciler
+ "msg"="Extracting CA from Secret resource" "resource_name"="issuers.cert-manager.io" "secret"="cert-manager/cert-manager-webhook-ca"
+I0608 controller.go:178] cert-manager/secret/customresourcedefinition/generic-inject-reconciler
+ "msg"="updated object" "resource_name"="issuers.cert-manager.io"
+```
+
+Now, look for any message that indicates that the Secret resource that the
+cert-manager webhook created can't be loaded. The two error messages that might
+show up are:
+
+```text
+E0608 sources.go:201] cert-manager/secret/customresourcedefinition/generic-inject-reconciler
+ "msg"="unable to fetch associated secret" "error"="Secret \"cert-manager-webhook-caq\" not found"
+```
+
+The following message indicates that the given CRD has been skipped because the
+annotation is missing. You can ignore these messages:
+
+```text
+I0608 controller.go:156] cert-manager/secret/customresourcedefinition/generic-inject-reconciler
+ "msg"="failed to determine ca data source for injectable" "resource_name"="challenges.acme.cert-manager.io"
+```
+
+If nothing seems wrong with the cainjector logs, you will want to check that the
+`spec.caBundle` field in the validation, mutation, and conversion configurations
+are correct. The Kubernetes API server uses the contents of that field to trust
+the cert-manager webhook. The `caBundle` contains the self-signed CA created by
+the cert-manager webhook when it started.
+
+```console
+$ kubectl get validatingwebhookconfigurations cert-manager-webhook -ojson | jq '.webhooks[].clientConfig'
+{
+ "caBundle": "LS0tLS1...LS0tLS0K",
+ "service": {
+ "name": "cert-manager-webhook",
+ "namespace": "cert-manager",
+ "path": "/validate",
+ "port": 443
+ }
+}
+```
+
+```console
+$ kubectl get mutatingwebhookconfigurations cert-manager-webhook -ojson | jq '.webhooks[].clientConfig'
+{
+ "caBundle": "LS0tLS1...RFLS0tLS0K",
+ "service": {
+ "name": "cert-manager-webhook",
+ "namespace": "cert-manager",
+ "path": "/validate",
+ "port": 443
+ }
+}
+```
+
+Let us see the contents of the `caBundle`:
+
+```console
+$ kubectl get mutatingwebhookconfigurations cert-manager-webhook -ojson \
+ | jq '.webhooks[].clientConfig.caBundle' -r | base64 -d \
+ | openssl x509 -noout -text -in -
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ ee:8f:4f:c8:55:7b:16:76:d8:6a:a2:e5:94:bc:7c:6b
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: CN = cert-manager-webhook-ca
+ Validity
+ Not Before: May 10 16:13:37 2022 GMT
+ Not After : May 10 16:13:37 2023 GMT
+ Subject: CN = cert-manager-webhook-ca
+```
+
+Let us check that the contents of `caBundle` works for connecting to the
+webhook:
+
+```console
+$ kubectl -n cert-manager get secret cert-manager-webhook-ca -ojsonpath='{.data.ca\.crt}' \
+ | base64 -d | openssl x509 -noout -text -in -
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ ee:8f:4f:c8:55:7b:16:76:d8:6a:a2:e5:94:bc:7c:6b
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: CN = cert-manager-webhook-ca
+ Validity
+ Not Before: May 10 16:13:37 2022 GMT
+ Not After : May 10 16:13:37 2023 GMT
+ Subject: CN = cert-manager-webhook-ca
+```
+
+Our final test is to try to connect to the webhook using this trust bundle. Let
+us port-forward to the webhook pod:
+
+```sh
+kubectl -n cert-manager port-forward deploy/cert-manager-webhook 10250
+```
+
+In another shell session, send a `/validate` HTTP request with the following
+command:
+
+```sh
+curl -vsS --resolve cert-manager-webhook.cert-manager.svc:10250:127.0.0.1 \
+ --service-name cert-manager-webhook-ca \
+ --cacert <(kubectl get validatingwebhookconfigurations cert-manager-webhook -ojson | jq '.webhooks[].clientConfig.caBundle' -r | base64 -d) \
+ https://cert-manager-webhook.cert-manager.svc:10250/validate 2>&1 -d@- <<'EOF' | sed '/^* /d; /bytes data]$/d; s/> //; s/< //'
+{"kind":"AdmissionReview","apiVersion":"admission.k8s.io/v1","request":{"requestKind":{"group":"cert-manager.io","version":"v1","kind":"Certificate"},"requestResource":{"group":"cert-manager.io","version":"v1","resource":"certificates"},"name":"foo","namespace":"default","operation":"CREATE","object":{"apiVersion":"cert-manager.io/v1","kind":"Certificate","spec":{"dnsNames":["foo"],"issuerRef":{"group":"cert-manager.io","kind":"Issuer","name":"letsencrypt"},"secretName":"foo","usages":["digital signature"]}}}}
+EOF
+```
+
+You should see a successful HTTP request and response:
+
+```http
+POST /validate HTTP/1.1
+Host: cert-manager-webhook.cert-manager.svc:10250
+User-Agent: curl/7.83.0
+Accept: */*
+Content-Length: 1299
+Content-Type: application/x-www-form-urlencoded
+
+HTTP/1.1 200 OK
+Date: Wed, 08 Jun 2022 16:20:45 GMT
+Content-Length: 2029
+Content-Type: text/plain; charset=utf-8
+
+...
+```
+
+## Error: `cluster scoped resource "mutatingwebhookconfigurations/" is managed and access is denied`
+
+> This message was reported in GitHub issue
+> [3717](https://github.com/cert-manager/cert-manager/issues/3717 "Cannot
+> install on GKE autopilot cluster due to mutatingwebhookconfigurations access
+> denied").
+
+While installing cert-manager on GKE Autopilot, you will see the following
+message:
+
+```text
+Error: rendered manifests contain a resource that already exists. Unable to continue with install:
+ could not get information about the resource:
+ mutatingwebhookconfigurations.admissionregistration.k8s.io "cert-manager-webhook" is forbidden:
+ User "XXXX" cannot get resource "mutatingwebhookconfigurations" in API group "admissionregistration.k8s.io" at the cluster scope:
+ GKEAutopilot authz: cluster scoped resource "mutatingwebhookconfigurations/" is managed and access is denied
+```
+
+This error message will appear when using Kubernetes 1.20 and below with GKE
+Autopilot. It is due to a [restriction on mutating admission webhooks in GKE
+Autopilot](https://github.com/cert-manager/cert-manager/issues/3717).
+
+As of October 2021, the "rapid" Autopilot release channel has rolled out version
+1.21 for Kubernetes masters. Installation via the Helm chart may end in an error
+message but cert-manager is reported to be working by some users. Feedback and
+PRs are welcome.
+
+## Error: `the namespace "kube-system" is managed and the request's verb "create" is denied`
+
+When installing cert-manager on GKE Autopilot with Helm, you will see the
+following error message:
+
+```text
+Not ready: the cert-manager webhook CA bundle is not injected yet
+```
+
+After this failure, you should still see the three pods happily running:
+
+```console
+$ kubectl get pods -n cert-manager
+NAME READY STATUS RESTARTS AGE
+cert-manager-76578c9687-24kmr 1/1 Running 0 47m
+cert-manager-cainjector-b7d47f746-4799n 1/1 Running 0 47m
+cert-manager-webhook-7f788c5b6-mspnt 1/1 Running 0 47m
+```
+
+But looking at either of the logs, you will see the following error message:
+
+```text
+E0425 leaderelection.go:334] error initially creating leader election record:
+ leases.coordination.k8s.io is forbidden: User "system:serviceaccount:cert-manager:cert-manager-webhook"
+ cannot create resource "leases" in API group "coordination.k8s.io" in the namespace "kube-system":
+ GKEAutopilot authz: the namespace "kube-system" is managed and the request's verb "create" is denied
+```
+
+That is due to a limitation of GKE Autopilot. It is not possible to create
+resources in the `kube-system` namespace, and cert-manager uses the well-known
+`kube-system` to manage the leader election. To get around the limitation, you
+can tell Helm to use a different namespace for the leader election:
+
+```sh
+helm install cert-manager jetstack/cert-manager --version 1.8.0 \
+ --namespace cert-manager --create-namespace \
+ --set global.leaderElection.namespace=cert-manager
+```
diff --git a/content/v1.12-docs/tutorials/README.md b/content/v1.12-docs/tutorials/README.md
new file mode 100644
index 0000000000..cc839b6b10
--- /dev/null
+++ b/content/v1.12-docs/tutorials/README.md
@@ -0,0 +1,38 @@
+---
+title: Tutorials
+description: 'cert-manager tutorials: Overview'
+---
+
+Step-by-step tutorials are a great way to get started with cert-manager, and we provide a few
+for you to learn from. Take a look!
+
+- [Securing Ingresses with NGINX-Ingress and cert-manager](./acme/nginx-ingress.md): Tutorial for deploying NGINX into your
+ cluster and securing incoming connections with a certificate from Let's Encrypt.
+- [GKE + Ingress + Let's Encrypt](./getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/README.md):
+ Learn how to deploy cert-manager on Google Kubernetes Engine and how to configure it to get certificates for Ingress, from Let's Encrypt.
+- [AKS + LoadBalancer + Let's Encrypt](getting-started-aks-letsencrypt/README.md):
+ Learn how to deploy cert-manager on Azure Kubernetes Service (AKS) and how to configure it to get certificates for an HTTPS web server, from Let's Encrypt.
+- [Backup and Restore Resources](./backup.md): Backup the cert-manager resources
+ in your cluster and then restore them.
+- [Pomerium Ingress](./acme/pomerium-ingress.md): Tutorial on using the Pomerium Ingress Controller with cert-manager.
+- [Issuing an ACME Certificate using DNS Validation](./acme/dns-validation.md):
+ Tutorial on how to resolve DNS ownership validation using DNS01 challenges.
+- [Issuing an ACME Certificate using HTTP Validation](./acme/http-validation.md):
+ Tutorial on how to resolve DNS ownership validation using HTTP01 challenges.
+- [Migrating from kube-lego](./acme/migrating-from-kube-lego.md): Tutorial on
+ how to migrate from the now deprecated kube-lego project.
+- [Securing an EKS Cluster with Venafi](./venafi/venafi.md): Tutorial for
+ creating an EKS cluster and securing an NGINX deployment with a Venafi issued
+ certificate.
+- [Securing an Istio service mesh with cert-manager](./istio-csr/istio-csr.md): Tutorial for
+ securing an Istio service mesh using a cert-manager issuer.
+- [Syncing Secrets Across Namespaces](./syncing-secrets-across-namespaces.md):
+ Learn how to synchronize Kubernetes Secret resources across namespaces using extensions such as: reflector, kubed and kubernetes-replicator.
+- [Obtaining SSL certificates with the ZeroSSL](./zerossl/zerossl.md): Tutorial describing usage of the ZeroSSL as external ACME server.
+
+### External Tutorials
+
+- A great AWS blog post on using cert-manager for end-to-end encryption in EKS. See [Setting up end-to-end TLS encryption on Amazon EKS](https://aws.amazon.com/blogs/containers/setting-up-end-to-end-tls-encryption-on-amazon-eks-with-the-new-aws-load-balancer-controller/)
+- A full cert-manager installation demo on a GKE Cluster. See [How-To: Automatic SSL Certificate Management for your Kubernetes Application Deployment](https://medium.com/contino-engineering/how-to-automatic-ssl-certificate-management-for-your-kubernetes-application-deployment-94b64dfc9114)
+- cert-manager installation on GKE Cluster using Workload Identity. See [Kubernetes, ingress-nginx, cert-manager & external-dns](https://blog.atomist.com/kubernetes-ingress-nginx-cert-manager-external-dns/)
+- A video tutorial for beginners showing cert-manager in action. See [Free SSL for Kubernetes with cert-manager](https://www.youtube.com/watch?v=hoLUigg4V18)
diff --git a/content/v1.12-docs/tutorials/acme/dns-validation.md b/content/v1.12-docs/tutorials/acme/dns-validation.md
new file mode 100644
index 0000000000..bddf11097b
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/dns-validation.md
@@ -0,0 +1,169 @@
+---
+title: DNS Validation
+description: 'cert-manager turorials: Issuing an ACME certificate using DNS validation'
+---
+
+## Issuing an ACME certificate using DNS validation
+
+cert-manager can be used to obtain certificates from a CA using the
+[ACME](https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment)
+protocol. The ACME protocol supports various challenge mechanisms which are
+used to prove ownership of a domain so that a valid certificate can be issued
+for that domain.
+
+One such challenge mechanism is DNS01. With a DNS01 challenge, you prove
+ownership of a domain by proving you control its DNS records.
+This is done by creating a TXT record with specific content that proves you
+have control of the domains DNS records.
+
+The following Issuer defines the necessary information to enable DNS validation.
+You can read more about the Issuer resource in the [Issuer
+docs](../../configuration/README.md).
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-staging
+ namespace: default
+spec:
+ acme:
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ email: user@example.com
+
+ # Name of a secret used to store the ACME account private key
+ privateKeySecretRef:
+ name: letsencrypt-staging
+
+ # ACME DNS-01 provider configurations
+ solvers:
+ # An empty 'selector' means that this solver matches all domains
+ - selector: {}
+ dns01:
+ cloudDNS:
+ # The ID of the GCP project
+ # reference: https://cert-manager.io/docs/tutorials/acme/dns-validation/
+ project: $PROJECT_ID
+ # This is the secret used to access the service account
+ serviceAccountSecretRef:
+ name: clouddns-dns01-solver-svc-acct
+ key: key.json
+
+ # We only use cloudflare to solve challenges for example.org.
+ # Alternative options such as 'matchLabels' and 'dnsZones' can be specified
+ # as part of a solver's selector too.
+ - selector:
+ dnsNames:
+ - example.org
+ dns01:
+ cloudflare:
+ email: my-cloudflare-acc@example.com
+ # !! Remember to create a k8s secret before
+ # kubectl create secret generic cloudflare-api-key-secret
+ apiKeySecretRef:
+ name: cloudflare-api-key-secret
+ key: api-key
+```
+
+
+We have specified the ACME server URL for Let's Encrypt's [staging
+environment](https://letsencrypt.org/docs/staging-environment/). The staging
+environment will not issue trusted certificates but is used to ensure that the
+verification process is working properly before moving to production. Let's
+Encrypt's production environment imposes much stricter [rate
+limits](https://letsencrypt.org/docs/rate-limits/), so to reduce the chance of
+you hitting those limits it is highly recommended to start by using the staging
+environment. To move to production, simply create a new Issuer with the URL set
+to `https://acme-v02.api.letsencrypt.org/directory`.
+
+The first stage of the ACME protocol is for the client to register with the
+ACME server. This phase includes generating an asymmetric key pair which is
+then associated with the email address specified in the Issuer. Make sure to
+change this email address to a valid one that you own. It is commonly used to
+send expiry notices when your certificates are coming up for renewal. The
+generated private key is stored in a Secret named `letsencrypt-staging`.
+
+The `dns01` stanza contains a list of DNS01 providers that can be used to
+solve DNS challenges. Our Issuer defines two providers. This gives us a choice
+of which one to use when obtaining certificates.
+
+More information about the DNS provider configuration, including a list of
+supported providers, can be found [in the DNS01 reference docs](../../configuration/acme/dns01/README.md).
+
+Once we have created the above Issuer we can use it to obtain a certificate.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com
+ namespace: default
+spec:
+ secretName: example-com-tls
+ issuerRef:
+ name: letsencrypt-staging
+ dnsNames:
+ - '*.example.com'
+ - example.com
+ - example.org
+```
+
+The Certificate resource describes our desired certificate and the possible
+methods that can be used to obtain it. You can obtain certificates for wildcard
+domains just like any other. Make sure to wrap wildcard domains with asterisks
+in your YAML resources, to avoid formatting issues. If you specify both
+`example.com` and `*.example.com` on the same Certificate, it will take slightly
+longer to perform validation as each domain will have to be validated one after
+the other. You can learn more about the Certificate resource in the
+[docs](../../usage/README.md). If the certificate is obtained successfully, the
+resulting key pair will be stored in a secret called `example-com-tls` in the
+same namespace as the Certificate.
+
+The certificate will have a common name of `*.example.com` and the [Subject
+Alternative Names
+(SANs)](https://en.wikipedia.org/wiki/Subject_Alternative_Name) will be
+`*.example.com`, `example.com` and `example.org`.
+
+In our Certificate we have referenced the `letsencrypt-staging` Issuer above.
+The Issuer must be in the same namespace as the Certificate. If you want to
+reference a `ClusterIssuer`, which is a cluster-scoped version of an Issuer, you
+must add `kind: ClusterIssuer` to the `issuerRef` stanza.
+
+For more information on `ClusterIssuers`, read the
+[issuer concepts](../../concepts/issuer.md).
+
+The `acme` stanza defines the configuration for our ACME challenges. Here we
+have defined the configuration for our DNS challenges which will be used to
+verify domain ownership. For each domain mentioned in a `dns01` stanza,
+cert-manager will use the provider's credentials from the referenced Issuer to
+create a TXT record called `_acme-challenge`. This record will then be verified
+by the ACME server in order to issue the certificate. Once domain ownership has
+been verified, any cert-manager affected records will be cleaned up.
+
+> Note: It is your responsibility to ensure the selected provider is
+> authoritative for your domain.
+
+After creating the above Certificate, we can check whether it has been obtained
+successfully using `kubectl describe`:
+
+```bash
+$ kubectl describe certificate example-com
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal CreateOrder 57m cert-manager Created new ACME order, attempting validation...
+ Normal DomainVerified 55m cert-manager Domain "*.example.com" verified with "dns-01" validation
+ Normal DomainVerified 55m cert-manager Domain "example.com" verified with "dns-01" validation
+ Normal DomainVerified 55m cert-manager Domain "example.org" verified with "dns-01" validation
+ Normal IssueCert 55m cert-manager Issuing certificate...
+ Normal CertObtained 55m cert-manager Obtained certificate from ACME server
+ Normal CertIssued 55m cert-manager Certificate issued successfully
+```
+
+You can also check whether issuance was successful with `kubectl get secret
+example-com-tls -o yaml`. You should see a base64 encoded signed TLS key pair.
+
+Once our certificate has been obtained, cert-manager will periodically check its
+validity and attempt to renew it if it gets close to expiry. cert-manager
+considers certificates to be close to expiry when the 'Not After' field on the
+certificate is less than the current time plus 30 days.
\ No newline at end of file
diff --git a/content/v1.12-docs/tutorials/acme/example/deployment.yaml b/content/v1.12-docs/tutorials/acme/example/deployment.yaml
new file mode 100644
index 0000000000..d876c66cf9
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/deployment.yaml
@@ -0,0 +1,20 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: kuard
+spec:
+ selector:
+ matchLabels:
+ app: kuard
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: kuard
+ spec:
+ containers:
+ - image: gcr.io/kuar-demo/kuard-amd64:1
+ imagePullPolicy: Always
+ name: kuard
+ ports:
+ - containerPort: 8080
diff --git a/content/v1.12-docs/tutorials/acme/example/ingress-tls-final.yaml b/content/v1.12-docs/tutorials/acme/example/ingress-tls-final.yaml
new file mode 100644
index 0000000000..5c90402c41
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/ingress-tls-final.yaml
@@ -0,0 +1,24 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: kuard
+ annotations:
+ kubernetes.io/ingress.class: "nginx"
+ cert-manager.io/issuer: "letsencrypt-prod"
+
+spec:
+ tls:
+ - hosts:
+ - example.example.com
+ secretName: quickstart-example-tls
+ rules:
+ - host: example.example.com
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: kuard
+ port:
+ number: 80
diff --git a/content/v1.12-docs/tutorials/acme/example/ingress-tls.yaml b/content/v1.12-docs/tutorials/acme/example/ingress-tls.yaml
new file mode 100644
index 0000000000..f888087d67
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/ingress-tls.yaml
@@ -0,0 +1,24 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: kuard
+ annotations:
+ kubernetes.io/ingress.class: "nginx"
+ cert-manager.io/issuer: "letsencrypt-staging"
+
+spec:
+ tls:
+ - hosts:
+ - example.example.com
+ secretName: quickstart-example-tls
+ rules:
+ - host: example.example.com
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: kuard
+ port:
+ number: 80
diff --git a/content/v1.12-docs/tutorials/acme/example/ingress.yaml b/content/v1.12-docs/tutorials/acme/example/ingress.yaml
new file mode 100644
index 0000000000..a2b8f8c4bd
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/ingress.yaml
@@ -0,0 +1,24 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: kuard
+ annotations:
+ kubernetes.io/ingress.class: "nginx"
+ #cert-manager.io/issuer: "letsencrypt-staging"
+
+spec:
+ tls:
+ - hosts:
+ - example.example.com
+ secretName: quickstart-example-tls
+ rules:
+ - host: example.example.com
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: kuard
+ port:
+ number: 80
diff --git a/content/v1.12-docs/tutorials/acme/example/pomerium-certificates.yaml b/content/v1.12-docs/tutorials/acme/example/pomerium-certificates.yaml
new file mode 100644
index 0000000000..7e07111417
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/pomerium-certificates.yaml
@@ -0,0 +1,36 @@
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: pomerium-cert
+ namespace: pomerium
+spec:
+ secretName: pomerium-tls
+ issuerRef:
+ name: pomerium-issuer
+ kind: Issuer
+ usages:
+ - server auth
+ - client auth
+ dnsNames:
+ - pomerium-proxy.pomerium.svc.cluster.local
+ - pomerium-authorize.pomerium.svc.cluster.local
+ - pomerium-databroker.pomerium.svc.cluster.local
+ - pomerium-authenticate.pomerium.svc.cluster.local
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: pomerium-redis-cert
+ namespace: pomerium
+spec:
+ secretName: pomerium-redis-tls
+ issuerRef:
+ name: pomerium-issuer
+ kind: Issuer
+ usages:
+ - server auth
+ - client auth
+ dnsNames:
+ - pomerium-redis-master.pomerium.svc.cluster.local
+ - pomerium-redis-headless.pomerium.svc.cluster.local
+ - pomerium-redis-replicas.pomerium.svc.cluster.local
diff --git a/content/v1.12-docs/tutorials/acme/example/pomerium-production-issuer.yaml b/content/v1.12-docs/tutorials/acme/example/pomerium-production-issuer.yaml
new file mode 100644
index 0000000000..d802d4d07f
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/pomerium-production-issuer.yaml
@@ -0,0 +1,19 @@
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-prod
+ namespace: pomerium
+spec:
+ acme:
+ # The ACME server URL
+ server: https://acme-v02.api.letsencrypt.org/directory
+ # Email address used for ACME registration
+ email: user@example.com
+ # Name of a secret used to store the ACME account private key
+ privateKeySecretRef:
+ name: letsencrypt-prod
+ # Enable the HTTP-01 challenge provider
+ solvers:
+ - http01:
+ ingress:
+ class: pomerium
\ No newline at end of file
diff --git a/content/v1.12-docs/tutorials/acme/example/pomerium-staging-issuer.yaml b/content/v1.12-docs/tutorials/acme/example/pomerium-staging-issuer.yaml
new file mode 100644
index 0000000000..f7756ed4bb
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/pomerium-staging-issuer.yaml
@@ -0,0 +1,19 @@
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-staging
+ namespace: pomerium
+spec:
+ acme:
+ # The ACME server URL
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ # Email address used for ACME registration
+ email: user@example.com
+ # Name of a secret used to store the ACME account private key
+ privateKeySecretRef:
+ name: letsencrypt-staging
+ # Enable the HTTP-01 challenge provider
+ solvers:
+ - http01:
+ ingress:
+ class: pomerium
\ No newline at end of file
diff --git a/content/v1.12-docs/tutorials/acme/example/pomerium-values.yaml b/content/v1.12-docs/tutorials/acme/example/pomerium-values.yaml
new file mode 100644
index 0000000000..2460377547
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/pomerium-values.yaml
@@ -0,0 +1,39 @@
+authenticate:
+ existingTLSSecret: pomerium-tls
+ idp:
+ provider: "google"
+ clientID: YOUR_CLIENT_ID
+ clientSecret: YOUR_SECRET
+ serviceAccount: YOUR_SERVICE_ACCOUNT
+ ingress:
+ annotations:
+ cert-manager.io/issuer: letsencrypt-staging
+ tls:
+ secretName: authenticate.localhost.pomerium.io-tls
+
+proxy:
+ existingTLSSecret: pomerium-tls
+
+databroker:
+ existingTLSSecret: pomerium-tls
+ storage:
+ clientTLS:
+ existingSecretName: pomerium-redis-tls
+ existingCASecretKey: ca.crt
+
+authorize:
+ existingTLSSecret: pomerium-tls
+
+redis:
+ enabled: true
+ generateTLS: false
+ tls:
+ certificateSecret: pomerium-redis-tls
+
+ingressController:
+ enabled: true
+
+config:
+ rootDomain: localhost.pomerium.io #Change this to your reserved domain space.
+ existingCASecret: pomerium-tls
+ generateTLS: false # On by default, disabled when cert-manager or another solution is in place.
diff --git a/content/v1.12-docs/tutorials/acme/example/production-issuer.yaml b/content/v1.12-docs/tutorials/acme/example/production-issuer.yaml
new file mode 100644
index 0000000000..f7676f2522
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/production-issuer.yaml
@@ -0,0 +1,18 @@
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-prod
+spec:
+ acme:
+ # The ACME server URL
+ server: https://acme-v02.api.letsencrypt.org/directory
+ # Email address used for ACME registration
+ email: user@example.com
+ # Name of a secret used to store the ACME account private key
+ privateKeySecretRef:
+ name: letsencrypt-prod
+ # Enable the HTTP-01 challenge provider
+ solvers:
+ - http01:
+ ingress:
+ class: nginx
diff --git a/content/v1.12-docs/tutorials/acme/example/service.yaml b/content/v1.12-docs/tutorials/acme/example/service.yaml
new file mode 100644
index 0000000000..864b481ccb
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/service.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: kuard
+spec:
+ ports:
+ - port: 80
+ targetPort: 8080
+ protocol: TCP
+ selector:
+ app: kuard
diff --git a/content/v1.12-docs/tutorials/acme/example/staging-issuer.yaml b/content/v1.12-docs/tutorials/acme/example/staging-issuer.yaml
new file mode 100644
index 0000000000..b733952029
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/example/staging-issuer.yaml
@@ -0,0 +1,18 @@
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ # The ACME server URL
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ # Email address used for ACME registration
+ email: user@example.com
+ # Name of a secret used to store the ACME account private key
+ privateKeySecretRef:
+ name: letsencrypt-staging
+ # Enable the HTTP-01 challenge provider
+ solvers:
+ - http01:
+ ingress:
+ class: nginx
diff --git a/content/v1.12-docs/tutorials/acme/http-validation.md b/content/v1.12-docs/tutorials/acme/http-validation.md
new file mode 100644
index 0000000000..d5cda8e658
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/http-validation.md
@@ -0,0 +1,159 @@
+---
+title: HTTP Validation
+description: 'cert-manager tutorials: Issuing an ACME certificate using HTTP validation'
+---
+
+## Issuing an ACME certificate using HTTP validation
+
+cert-manager can be used to obtain certificates from a CA using the
+[ACME](https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment)
+protocol. The ACME protocol supports various challenge mechanisms which are
+used to prove ownership of a domain so that a valid certificate can be issued
+for that domain.
+
+One such challenge mechanism is the HTTP01 challenge. With a HTTP01 challenge,
+you prove ownership of a domain by ensuring that a particular file is present at
+the domain. It is assumed that you control the domain if you are able to
+publish the given file under a given path.
+
+The following Issuer defines the necessary information to enable HTTP
+validation. You can read more about the Issuer resource in the [Issuer
+docs](../../concepts/issuer.md).
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-staging
+ namespace: default
+spec:
+ acme:
+ # The ACME server URL
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ # Email address used for ACME registration
+ email: user@example.com
+ # Name of a secret used to store the ACME account private key
+ privateKeySecretRef:
+ name: letsencrypt-staging
+ # Enable the HTTP-01 challenge provider
+ solvers:
+ # An empty 'selector' means that this solver matches all domains
+ - selector: {}
+ http01:
+ ingress:
+ class: nginx
+```
+
+We have specified the ACME server URL for Let's Encrypt's [staging
+environment](https://letsencrypt.org/docs/staging-environment/). The staging
+environment will not issue trusted certificates but is used to ensure that the
+verification process is working properly before moving to production. Let's
+Encrypt's production environment imposes much stricter [rate
+limits](https://letsencrypt.org/docs/rate-limits/), so to reduce the chance of
+you hitting those limits it is highly recommended to start by using the staging
+environment. To move to production, simply create a new Issuer with the URL set
+to `https://acme-v02.api.letsencrypt.org/directory`.
+
+The first stage of the ACME protocol is for the client to register with the
+ACME server. This phase includes generating an asymmetric key pair which is
+then associated with the email address specified in the Issuer. Make sure to
+change this email address to a valid one that you own. It is commonly used to
+send expiry notices when your certificates are coming up for renewal. The
+generated private key is stored in a Secret named `letsencrypt-staging`.
+
+We must provide one or more Solvers for handling the ACME challenge. In this
+case we want to use HTTP validation so we specify an `http01` Solver. We could
+optionally map different domains to use different Solver configurations.
+
+Once we have created the above Issuer we can use it to obtain a certificate.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com
+ namespace: default
+spec:
+ secretName: example-com-tls
+ issuerRef:
+ name: letsencrypt-staging
+ commonName: example.com
+ dnsNames:
+ - www.example.com
+```
+
+The Certificate resource describes our desired certificate and the possible
+methods that can be used to obtain it. You can learn more about the Certificate
+resource in the [docs](../../concepts/certificate.md). If the certificate is
+obtained successfully, the resulting key pair will be stored in a secret called
+`example-com-tls` in the same namespace as the Certificate.
+
+The certificate will have a common name of `example.com` and the [Subject
+Alternative Names
+(SANs)](https://en.wikipedia.org/wiki/Subject_Alternative_Name) will be
+`example.com` and `www.example.com`. Note that only these SANs will be respected
+by TLS clients.
+
+In our Certificate we have referenced the `letsencrypt-staging` Issuer above.
+The Issuer must be in the same namespace as the Certificate. If you want to
+reference a `ClusterIssuer`, which is a cluster-scoped version of an Issuer, you
+must add `kind: ClusterIssuer` to the `issuerRef` stanza.
+
+For more information on `ClusterIssuers`, read the [`ClusterIssuer`
+docs](../../concepts/issuer.md).
+
+The `acme` stanza defines the configuration for our ACME challenges. Here we
+have defined the configuration for our HTTP01 challenges which will be used to
+verify domain ownership. To verify ownership of each domain mentioned in an
+`http01` stanza, cert-manager will create a Pod, Service and Ingress that
+exposes an HTTP endpoint that satisfies the HTTP01 challenge.
+
+The fields `ingress` and `ingressClass` in the `http01` stanza can be used to
+control how cert-manager interacts with Ingress resources:
+
+- If the `ingress` field is specified, then an Ingress resource with the same
+ name in the same namespace as the Certificate must already exist and it will
+ be modified only to add the appropriate rules to solve the challenge.
+ This field is useful for the Google Cloud Loadbalancer ingress controller,
+ as well as a number of others, that assign a single public IP address for
+ each ingress resource.
+ Without manual intervention, creating a new ingress resource would cause any
+ challenges to fail.
+- If the `ingressClass` field is specified, a new ingress resource with a
+ randomly generated name will be created in order to solve the challenge.
+ This new resource will have an annotation with key `kubernetes.io/ingress.class`
+ and value set to the value of the `ingressClass` field.
+ This works for the likes of the NGINX ingress controller.
+- If neither are specified, new ingress resources will be created with a randomly
+ generated name, but they will not have the ingress class annotation set.
+- If both are specified, then the `ingress` field will take precedence.
+
+Once domain ownership has been verified, any cert-manager affected resources will
+be cleaned up or deleted.
+
+> Note: It is your responsibility to point each domain name at the correct IP
+> address for your ingress controller.
+
+After creating the above Certificate, we can check whether it has been obtained
+successfully using `kubectl describe`:
+
+```bash
+$ kubectl describe certificate example-com
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal CreateOrder 57m cert-manager Created new ACME order, attempting validation...
+ Normal DomainVerified 55m cert-manager Domain "example.com" verified with "http-01" validation
+ Normal DomainVerified 55m cert-manager Domain "www.example.com" verified with "http-01" validation
+ Normal IssueCert 55m cert-manager Issuing certificate...
+ Normal CertObtained 55m cert-manager Obtained certificate from ACME server
+ Normal CertIssued 55m cert-manager Certificate issued successfully
+```
+
+You can also check whether issuance was successful with `kubectl get secret
+example-com-tls -o yaml`. You should see a base64 encoded signed TLS key pair.
+
+Once our certificate has been obtained, cert-manager will periodically check its
+validity and attempt to renew it if it gets close to expiry. cert-manager
+considers certificates to be close to expiry when the 'Not After' field on the
+certificate is less than the current time plus 30 days.
\ No newline at end of file
diff --git a/content/v1.12-docs/tutorials/acme/migrating-from-kube-lego.md b/content/v1.12-docs/tutorials/acme/migrating-from-kube-lego.md
new file mode 100644
index 0000000000..89b3ffebc9
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/migrating-from-kube-lego.md
@@ -0,0 +1,232 @@
+---
+title: Migrating from Kube-LEGO
+description: 'cert-manager tutorials: Migrating from kube-lego'
+---
+
+[kube-lego](https://github.com/jetstack/kube-lego) is an older Jetstack project
+for obtaining TLS certificates from Let's Encrypt (or another ACME server).
+
+Since cert-managers release, kube-lego has been gradually deprecated in favor
+of this project. There are a number of key differences between the two:
+
+| Feature | kube-lego | cert-manager |
+|-------------------------------------------|----------------------------------|------------------------|
+| Configuration | Annotations on Ingress resources | CRDs |
+| CAs | ACME | ACME, signing key pair |
+| Kubernetes | `v1.2` - `v1.8` | `v1.7+` |
+| Debugging | Look at logs | Kubernetes Events API |
+| Multi-tenancy | Not supported | Supported |
+| Distinct issuance sources per Certificate | Not supported | Supported |
+| Ingress controller support (ACME) | GCE, NGINX | All |
+
+This guide will walk through how you can safely migrate your kube-lego
+installation to cert-manager, without service interruption.
+
+By the end of the guide, we should have:
+
+1. Scaled down and removed kube-lego
+
+2. Installed cert-manager
+
+3. Migrated ACME private key to cert-manager
+
+4. Created an ACME `ClusterIssuer` using this private key, to issue certificates
+ throughout your cluster
+
+5. Configured cert-manager's [`ingress-shim`](../../usage/ingress.md) to
+ automatically provision Certificate resources for all Ingress resources with
+ the `kubernetes.io/tls-acme: "true"` annotation, using the `ClusterIssuer` we
+ have created
+
+6. Verified that the cert-manager installation is working
+
+
+## 1. Scale down kube-lego
+
+Before we begin deploying cert-manager, it is best we scale our kube-lego
+deployment down to 0 replicas. This will prevent the two controllers
+potentially 'fighting' each other. If you deployed kube-lego using the official
+deployment YAMLs, a command like so should do:
+
+```bash
+$ kubectl scale deployment kube-lego \
+ --namespace kube-lego \
+ --replicas=0
+```
+
+You can then verify your kube-lego pod is no longer running with:
+
+```bash
+$ kubectl get pods --namespace kube-lego
+```
+
+## 2. Deploy cert-manager
+
+cert-manager should be deployed using Helm, according to our official
+[installation guide](../../installation/README.md). No special steps are
+required here. We will return to this deployment at the end of this guide and
+perform an upgrade of some of the CLI flags we deploy cert-manager with however.
+
+Please take extra care to ensure you have configured RBAC correctly when
+deploying Helm and cert-manager - there are some nuances described in our
+deploying document!
+
+## 3. Obtaining your ACME account private key
+
+In order to continue issuing and renewing certificates on your behalf, we need
+to migrate the user account private key that kube-lego has created for you over
+to cert-manager.
+
+Your ACME user account identity is a private key, stored in a secret resource.
+By default, kube-lego will store this key in a secret named `kube-lego-account`
+in the same namespace as your kube-lego Deployment. You may have overridden this
+value when you deploy kube-lego, in which case the secret name to use will be
+the value of the `LEGO_SECRET_NAME` environment variable.
+
+You should download a copy of this secret resource and save it in your local
+directory:
+
+```bash
+$ kubectl get secret kube-lego-account -o yaml \
+ --namespace kube-lego \
+ --export > kube-lego-account.yaml
+```
+
+Once saved, open up this file and change the `metadata.name` field to something
+more relevant to cert-manager. For the rest of this guide, we'll assume you
+chose `letsencrypt-private-key`.
+
+Once done, we need to create this new resource in the `cert-manager` namespace.
+By default, cert-manager stores supporting resources for `ClusterIssuers` in the
+namespace that it is running in, and we used `cert-manager` when deploying
+cert-manager above. You should change this if you have deployed cert-manager
+into a different namespace.
+
+```bash
+$ kubectl create -f kube-lego-account.yaml \
+ --namespace cert-manager
+```
+
+## 4. Creating an ACME `ClusterIssuer` using your old ACME account
+
+We need to create a `ClusterIssuer` which will hold information about the ACME
+account previously registered via kube-lego. In order to do so, we need two more
+pieces of information from our old kube-lego deployment: the server URL of the
+ACME server, and the email address used to register the account.
+
+Both of these bits of information are stored within the kube-lego `ConfigMap`.
+
+To retrieve them, you should be able to `get` the `ConfigMap` using `kubectl`:
+
+```bash
+$ kubectl get configmap kube-lego -o yaml \
+ --namespace kube-lego \
+ --export
+```
+
+Your email address should be shown under the `.data.lego.email` field, and the
+ACME server URL under `.data.lego.url`.
+
+For the purposes of this guide, we will assume the email is
+`user@example.com` and the URL
+`https://acme-staging-v02.api.letsencrypt.org/directory`.
+
+Now that we have migrated our private key to the new Secret resource, as well as
+obtaining our ACME email address and URL, we can create a `ClusterIssuer`
+resource!
+
+Create a file named `cluster-issuer.yaml`:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ # Adjust the name here accordingly
+ name: letsencrypt-staging
+spec:
+ acme:
+ # The ACME server URL
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ # Email address used for ACME registration
+ email: user@example.com
+ # Name of a secret used to store the ACME account private key from step 3
+ privateKeySecretRef:
+ name: letsencrypt-private-key
+ # Enable the HTTP-01 challenge provider
+ solvers:
+ - http01:
+ ingress:
+ class: nginx
+```
+
+We then submit this file to our Kubernetes cluster:
+
+```bash
+$ kubectl create -f cluster-issuer.yaml
+```
+
+You should be able to verify the ACME account has been verified successfully:
+
+```bash
+$ kubectl describe clusterissuer letsencrypt-staging
+...
+Status:
+ Acme:
+ Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/7571319
+ Conditions:
+ Last Transition Time: 2019-01-30T14:52:03Z
+ Message: The ACME account was registered with the ACME server
+ Reason: ACMEAccountRegistered
+ Status: True
+ Type: Ready
+```
+
+## 5. Configuring ingress-shim to use our new `ClusterIssuer` by default
+
+Now that our `ClusterIssuer` is ready to issue certificates, we have one last
+thing to do: we must reconfigure `ingress-shim` (deployed as part of cert-manager)
+to automatically create Certificate resources for all Ingress resources it finds
+with appropriate annotations.
+
+More information on the role of ingress-shim can be found [in the
+docs](../../usage/ingress.md), but for now we can just run a `helm
+upgrade` in order to add a few additional flags. Assuming you've named your
+`ClusterIssuer` `letsencrypt-staging` (as above), run:
+
+```bash
+$ helm upgrade cert-manager \
+ jetstack/cert-manager \
+ --namespace cert-manager \
+ --set ingressShim.defaultIssuerName=letsencrypt-staging \
+ --set ingressShim.defaultIssuerKind=ClusterIssuer
+```
+
+You should see the cert-manager pod be re-created, and once started it should
+automatically create Certificate resources for all of your ingresses that
+previously had kube-lego enabled.
+
+## 6. Verify each ingress now has a corresponding Certificate
+
+Before we finish, we should make sure there is now a Certificate resource for
+each ingress resource you previously enabled kube-lego on.
+
+You should be able to check this by running:
+
+```bash
+$ kubectl get certificates --all-namespaces
+```
+
+There should be an entry for each ingress in your cluster with the kube-lego
+annotation.
+
+We can also verify that cert-manager has 'adopted' the old TLS certificates by
+viewing the logs for cert-manager:
+
+```bash
+$ kubectl logs -n cert-manager -l app=cert-manager -c cert-manager
+...
+I1025 21:54:02.869269 1 sync.go:206] Certificate my-example-certificate scheduled for renewal in 292 hours
+```
+
+Here we can see cert-manager has verified the existing TLS certificate and
+scheduled it to be renewed in 292 hours time.
\ No newline at end of file
diff --git a/content/v1.12-docs/tutorials/acme/nginx-ingress.md b/content/v1.12-docs/tutorials/acme/nginx-ingress.md
new file mode 100644
index 0000000000..9a334f4810
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/nginx-ingress.md
@@ -0,0 +1,602 @@
+---
+title: Securing NGINX-ingress
+description: 'cert-manager tutorials: Using ingress-nginx to solve an ACME HTTP-01 challenge'
+---
+
+This tutorial will detail how to install and secure ingress to your cluster
+using NGINX.
+
+## Step 1 - Install Helm
+
+> *Skip this section if you have helm installed.*
+
+The easiest way to install `cert-manager` is to use [`Helm`](https://helm.sh), a
+templating and deployment tool for Kubernetes resources.
+
+First, ensure the Helm client is installed following the [Helm installation
+instructions](https://helm.sh/docs/intro/install/).
+
+For example, on MacOS:
+
+```bash
+brew install kubernetes-helm
+```
+
+## Step 2 - Deploy the NGINX Ingress Controller
+
+A [`kubernetes ingress controller`](https://kubernetes.io/docs/concepts/services-networking/ingress) is
+designed to be the access point for HTTP and HTTPS traffic to the software
+running within your cluster. The `ingress-nginx-controller` does this by providing
+an HTTP proxy service supported by your cloud provider's load balancer.
+
+You can get more details about `ingress-nginx` and how it works from the
+[documentation for `ingress-nginx`](https://kubernetes.github.io/ingress-nginx/).
+
+Add the latest helm repository for the ingress-nginx
+
+```bash
+helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
+```
+
+Update the helm repository with the latest charts:
+
+```bash
+$ helm repo update
+Hang tight while we grab the latest from your chart repositories...
+...Skip local chart repository
+...Successfully got an update from the "stable" chart repository
+...Successfully got an update from the "ingress-nginx" chart repository
+...Successfully got an update from the "coreos" chart repository
+Update Complete. ⎈ Happy Helming!⎈
+```
+
+Use `helm` to install an NGINX Ingress controller:
+
+```bash
+$ helm install quickstart ingress-nginx/ingress-nginx
+
+NAME: quickstart
+... lots of output ...
+```
+
+It can take a minute or two for the cloud provider to provide and link a public
+IP address. When it is complete, you can see the external IP address using the
+`kubectl` command:
+
+```bash
+$ kubectl get svc
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+kubernetes ClusterIP 10.0.0.1 443/TCP 13m
+quickstart-ingress-nginx-controller LoadBalancer 10.0.114.241 80:31635/TCP,443:30062/TCP 8m16s
+quickstart-ingress-nginx-controller-admission ClusterIP 10.0.188.24 443/TCP 8m16s
+```
+
+This command shows you all the services in your cluster (in the `default`
+namespace), and any external IP addresses they have. When you first create the
+controller, your cloud provider won't have assigned and allocated an IP address
+through the `LoadBalancer` yet. Until it does, the external IP address for the
+service will be listed as ``.
+
+Your cloud provider may have options for reserving an IP address prior to
+creating the ingress controller and using that IP address rather than assigning
+an IP address from a pool. Read through the documentation from your cloud
+provider on how to arrange that.
+
+## Step 3 - Assign a DNS name
+
+The external IP that is allocated to the ingress-controller is the IP to which
+all incoming traffic should be routed. To enable this, add it to a DNS zone you
+control, for example as `www.example.com`.
+
+This quick-start assumes you know how to assign a DNS entry to an IP address and
+will do so.
+
+## Step 4 - Deploy an Example Service
+
+Your service may have its own chart, or you may be deploying it directly with
+manifests. This quick-start uses manifests to create and expose a sample service.
+The example service uses [`kuard`](https://github.com/kubernetes-up-and-running/kuard),
+a demo application.
+
+The quick-start example uses three manifests for the sample. The first two are a
+sample deployment and an associated service:
+
+```yaml file=./example/deployment.yaml
+```
+
+```yaml file=./example/service.yaml
+```
+
+You can create download and reference these files locally, or you can
+reference them from the GitHub source repository for this documentation.
+To install the example service from the tutorial files straight from GitHub, do
+the following:
+
+```bash
+kubectl apply -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/deployment.yaml
+# expected output: deployment.extensions "kuard" created
+
+kubectl apply -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/service.yaml
+# expected output: service "kuard" created
+```
+
+An [Ingress resource](https://kubernetes.io/docs/concepts/services-networking/ingress/) is
+what Kubernetes uses to expose this example service outside the cluster. You
+will need to download and modify the example manifest to reflect the domain that
+you own or control to complete this example.
+
+A sample ingress you can start with is:
+
+```yaml file=./example/ingress.yaml
+```
+
+You can download the sample manifest from GitHub , edit it, and submit the
+manifest to Kubernetes with the command below. Edit the file in your editor, and once
+it is saved:
+
+```bash
+kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/ingress.yaml
+# expected output: ingress.networking.k8s.io/kuard created
+```
+
+> Note: The ingress example we show above has a `host` definition within it. The
+> `ingress-nginx-controller` will route traffic when the hostname requested
+> matches the definition in the ingress. You *can* deploy an ingress without a
+> `host` definition in the rule, but that pattern isn't usable with a TLS
+> certificate, which expects a fully qualified domain name.
+
+Once it is deployed, you can use the command `kubectl get ingress` to see the status
+ of the ingress:
+
+```text
+NAME HOSTS ADDRESS PORTS AGE
+kuard * 80, 443 17s
+```
+
+It may take a few minutes, depending on your service provider, for the ingress
+to be fully created. When it has been created and linked into place, the
+ingress will show an address as well:
+
+```text
+NAME HOSTS ADDRESS PORTS AGE
+kuard * 203.0.113.2 80 9m
+```
+
+> Note: The IP address on the ingress *may not* match the IP address that the
+> `ingress-nginx-controller` has. This is fine, and is a quirk/implementation detail
+> of the service provider hosting your Kubernetes cluster. Since we are using
+> the `ingress-nginx-controller` instead of any cloud-provider specific ingress
+> backend, use the IP address that was defined and allocated for the
+> `quickstart-ingress-nginx-controller ` `LoadBalancer` resource as the primary access point for
+> your service.
+
+Make sure the service is reachable at the domain name you added above, for
+example `http://www.example.com`. The simplest way is to open a browser
+and enter the name that you set up in DNS, and for which we just added the
+ingress.
+
+You may also use a command line tool like `curl` to check the ingress.
+
+```bash
+$ curl -kivL -H 'Host: www.example.com' 'http://203.0.113.2'
+```
+
+The options on this curl command will provide verbose output, following any
+redirects, show the TLS headers in the output, and not error on insecure
+certificates. With `ingress-nginx-controller`, the service will be available
+with a TLS certificate, but it will be using a self-signed certificate
+provided as a default from the `ingress-nginx-controller`. Browsers will show
+a warning that this is an invalid certificate. This is expected and normal,
+as we have not yet used cert-manager to get a fully trusted certificate
+for our site.
+
+> *Warning*: It is critical to make sure that your ingress is available and
+> responding correctly on the internet. This quick-start example uses Let's
+> Encrypt to provide the certificates, which expects and validates both that the
+> service is available and that during the process of issuing a certificate uses
+> that validation as proof that the request for the domain belongs to someone
+> with sufficient control over the domain.
+
+## Step 5 - Deploy cert-manager
+
+We need to install cert-manager to do the work with Kubernetes to request a
+certificate and respond to the challenge to validate it. We can use Helm or
+plain Kubernetes manifests to install cert-manager.
+
+Since we installed Helm earlier, we'll assume you want to use Helm; follow the
+[Helm guide](../../installation/helm.md). For other methods, read the
+[installation documentation](../../installation/README.md) for cert-manager.
+
+cert-manager mainly uses two different custom Kubernetes resources - known as
+[`CRDs`](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) -
+to configure and control how it operates, as well as to store state. These
+resources are Issuers and Certificates.
+
+### Issuers
+
+An Issuer defines _how_ cert-manager will request TLS certificates. Issuers are
+specific to a single namespace in Kubernetes, but there's also a `ClusterIssuer`
+which is meant to be a cluster-wide version.
+
+Take care to ensure that your Issuers are created in the same namespace as the
+certificates you want to create. You might need to add `-n my-namespace` to your
+`kubectl create` commands.
+
+Your other option is to replace your `Issuers` with `ClusterIssuers`;
+`ClusterIssuer` resources apply across all Ingress resources in your cluster.
+If using a `ClusterIssuer`, remember to update the Ingress annotation `cert-manager.io/issuer` to
+`cert-manager.io/cluster-issuer`.
+
+If you see issues with issuers, follow the [Troubleshooting Issuing ACME Certificates](../../troubleshooting/acme.md) guide.
+
+More information on the differences between `Issuers` and `ClusterIssuers` - including
+when you might choose to use each can be found on [Issuer concepts](../../concepts/issuer.md#namespaces).
+
+### Certificates
+
+Certificates resources allow you to specify the details of the certificate you
+want to request. They reference an issuer to define _how_ they'll be issued.
+
+For more information, see [Certificate concepts](../../concepts/certificate.md).
+
+## Step 6 - Configure a Let's Encrypt Issuer
+
+We'll set up two issuers for Let's Encrypt in this example: staging and production.
+
+The Let's Encrypt production issuer has [very strict rate limits](https://letsencrypt.org/docs/rate-limits/).
+When you're experimenting and learning, it can be very easy to hit those limits. Because of that risk,
+we'll start with the Let's Encrypt staging issuer, and once we're happy that it's working
+we'll switch to the production issuer.
+
+Note that you'll see a warning about untrusted certificates from the staging issuer, but that's totally expected.
+
+Create this definition locally and update the email address to your own. This
+email is required by Let's Encrypt and used to notify you of certificate
+expiration and updates.
+
+```yaml file=./example/staging-issuer.yaml
+```
+
+Once edited, apply the custom resource:
+
+```bash
+kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/staging-issuer.yaml
+# expected output: issuer.cert-manager.io "letsencrypt-staging" created
+```
+
+Also create a production issuer and deploy it. As with the staging issuer, you
+will need to update this example and add in your own email address.
+
+```yaml file=./example/production-issuer.yaml
+```
+
+```bash
+kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/production-issuer.yaml
+# expected output: issuer.cert-manager.io "letsencrypt-prod" created
+```
+
+Both of these issuers are configured to use the [`HTTP01`](../../configuration/acme/http01/README.md) challenge provider.
+
+Check on the status of the issuer after you create it:
+
+```bash
+$ kubectl describe issuer letsencrypt-staging
+Name: letsencrypt-staging
+Namespace: default
+Labels:
+Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"cert-manager.io/v1","kind":"Issuer","metadata":{"annotations":{},"name":"letsencrypt-staging","namespace":"default"},(...)}
+API Version: cert-manager.io/v1
+Kind: Issuer
+Metadata:
+ Cluster Name:
+ Creation Timestamp: 2018-11-17T18:03:54Z
+ Generation: 0
+ Resource Version: 9092
+ Self Link: /apis/cert-manager.io/v1/namespaces/default/issuers/letsencrypt-staging
+ UID: 25b7ae77-ea93-11e8-82f8-42010a8a00b5
+Spec:
+ Acme:
+ Email: email@example.com
+ Private Key Secret Ref:
+ Key:
+ Name: letsencrypt-staging
+ Server: https://acme-staging-v02.api.letsencrypt.org/directory
+ Solvers:
+ Http 01:
+ Ingress:
+ Class: nginx
+Status:
+ Acme:
+ Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/7374163
+ Conditions:
+ Last Transition Time: 2018-11-17T18:04:00Z
+ Message: The ACME account was registered with the ACME server
+ Reason: ACMEAccountRegistered
+ Status: True
+ Type: Ready
+Events:
+```
+
+You should see the issuer listed with a registered account.
+
+## Step 7 - Deploy a TLS Ingress Resource
+
+With all the prerequisite configuration in place, we can now do the pieces to
+request the TLS certificate. There are two primary ways to do this: using
+annotations on the ingress with [`ingress-shim`](../../usage/ingress.md) or
+directly creating a certificate resource.
+
+In this example, we will add annotations to the ingress, and take advantage
+of ingress-shim to have it create the certificate resource on our behalf.
+After creating a certificate, the cert-manager will update or create a ingress
+resource and use that to validate the domain. Once verified and issued,
+cert-manager will create or update the secret defined in the certificate.
+
+> Note: The secret that is used in the ingress should match the secret defined
+> in the certificate. There isn't any explicit checking, so a typo will result
+> in the `ingress-nginx-controller` falling back to its self-signed certificate.
+> In our example, we are using annotations on the ingress (and ingress-shim)
+> which will create the correct secrets on your behalf.
+
+Edit the ingress add the annotations that were commented out in our earlier
+example:
+
+```yaml file=./example/ingress-tls.yaml
+```
+
+and apply it:
+
+```bash
+kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/ingress-tls.yaml
+# expected output: ingress.networking.k8s.io/kuard configured
+```
+
+Cert-manager will read these annotations and use them to create a certificate,
+which you can request and see:
+
+```bash
+$ kubectl get certificate
+NAME READY SECRET AGE
+quickstart-example-tls True quickstart-example-tls 16m
+```
+
+cert-manager reflects the state of the process for every request in the
+certificate object. You can view this information using the
+`kubectl describe` command:
+
+```bash
+$ kubectl describe certificate quickstart-example-tls
+Name: quickstart-example-tls
+Namespace: default
+Labels:
+Annotations:
+API Version: cert-manager.io/v1
+Kind: Certificate
+Metadata:
+ Cluster Name:
+ Creation Timestamp: 2018-11-17T17:58:37Z
+ Generation: 0
+ Owner References:
+ API Version: networking.k8s.io/v1
+ Block Owner Deletion: true
+ Controller: true
+ Kind: Ingress
+ Name: kuard
+ UID: a3e9f935-ea87-11e8-82f8-42010a8a00b5
+ Resource Version: 9295
+ Self Link: /apis/cert-manager.io/v1/namespaces/default/certificates/quickstart-example-tls
+ UID: 68d43400-ea92-11e8-82f8-42010a8a00b5
+Spec:
+ Dns Names:
+ www.example.com
+ Issuer Ref:
+ Kind: Issuer
+ Name: letsencrypt-staging
+ Secret Name: quickstart-example-tls
+Status:
+ Acme:
+ Order:
+ URL: https://acme-staging-v02.api.letsencrypt.org/acme/order/7374163/13665676
+ Conditions:
+ Last Transition Time: 2018-11-17T18:05:57Z
+ Message: Certificate issued successfully
+ Reason: CertIssued
+ Status: True
+ Type: Ready
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal CreateOrder 9m cert-manager Created new ACME order, attempting validation...
+ Normal DomainVerified 8m cert-manager Domain "www.example.com" verified with "http-01" validation
+ Normal IssueCert 8m cert-manager Issuing certificate...
+ Normal CertObtained 7m cert-manager Obtained certificate from ACME server
+ Normal CertIssued 7m cert-manager Certificate issued Successfully
+```
+
+The events associated with this resource and listed at the bottom
+of the `describe` results show the state of the request. In the above
+example the certificate was validated and issued within a couple of minutes.
+
+Once complete, cert-manager will have created a secret with the details of
+the certificate based on the secret used in the ingress resource. You can
+use the describe command as well to see some details:
+
+```bash
+$ kubectl describe secret quickstart-example-tls
+Name: quickstart-example-tls
+Namespace: default
+Labels: cert-manager.io/certificate-name=quickstart-example-tls
+Annotations: cert-manager.io/alt-names=www.example.com
+ cert-manager.io/common-name=www.example.com
+ cert-manager.io/issuer-kind=Issuer
+ cert-manager.io/issuer-name=letsencrypt-staging
+
+Type: kubernetes.io/tls
+
+Data
+====
+tls.crt: 3566 bytes
+tls.key: 1675 bytes
+```
+
+Now that we have confidence that everything is configured correctly, you
+can update the annotations in the ingress to specify the production issuer:
+
+```yaml file=./example/ingress-tls-final.yaml
+```
+
+```bash
+$ kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/ingress-tls-final.yaml
+ingress.networking.k8s.io/kuard configured
+```
+
+You will also need to delete the existing secret, which cert-manager is watching
+and will cause it to reprocess the request with the updated issuer.
+
+```bash
+$ kubectl delete secret quickstart-example-tls
+secret "quickstart-example-tls" deleted
+```
+
+This will start the process to get a new certificate, and using describe
+you can see the status. Once the production certificate has been updated,
+you should see the example KUARD running at your domain with a signed TLS
+certificate.
+
+```bash
+$ kubectl describe certificate quickstart-example-tls
+Name: quickstart-example-tls
+Namespace: default
+Labels:
+Annotations:
+API Version: cert-manager.io/v1
+Kind: Certificate
+Metadata:
+ Cluster Name:
+ Creation Timestamp: 2018-11-17T18:36:48Z
+ Generation: 0
+ Owner References:
+ API Version: networking.k8s.io/v1
+ Block Owner Deletion: true
+ Controller: true
+ Kind: Ingress
+ Name: kuard
+ UID: a3e9f935-ea87-11e8-82f8-42010a8a00b5
+ Resource Version: 283686
+ Self Link: /apis/cert-manager.io/v1/namespaces/default/certificates/quickstart-example-tls
+ UID: bdd93b32-ea97-11e8-82f8-42010a8a00b5
+Spec:
+ Dns Names:
+ www.example.com
+ Issuer Ref:
+ Kind: Issuer
+ Name: letsencrypt-prod
+ Secret Name: quickstart-example-tls
+Status:
+ Conditions:
+ Last Transition Time: 2019-01-09T13:52:05Z
+ Message: Certificate does not exist
+ Reason: NotFound
+ Status: False
+ Type: Ready
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Generated 18s cert-manager Generated new private key
+ Normal OrderCreated 18s cert-manager Created Order resource "quickstart-example-tls-889745041"
+```
+
+You can see the current state of the ACME Order by running `kubectl describe`
+on the Order resource that cert-manager has created for your Certificate:
+
+```bash
+$ kubectl describe order quickstart-example-tls-889745041
+...
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Created 90s cert-manager Created Challenge resource "quickstart-example-tls-889745041-0" for domain "www.example.com"
+```
+
+Here, we can see that cert-manager has created 1 'Challenge' resource to fulfill
+the Order. You can dig into the state of the current ACME challenge by running
+`kubectl describe` on the automatically created Challenge resource:
+
+```bash
+$ kubectl describe challenge quickstart-example-tls-889745041-0
+...
+Status:
+ Presented: true
+ Processing: true
+ Reason: Waiting for http-01 challenge propagation
+ State: pending
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Started 15s cert-manager Challenge scheduled for processing
+ Normal Presented 14s cert-manager Presented challenge using http-01 challenge mechanism
+```
+
+From above, we can see that the challenge has been 'presented' and cert-manager
+is waiting for the challenge record to propagate to the ingress controller.
+You should keep an eye out for new events on the challenge resource, as a
+'success' event should be printed after a minute or so (depending on how fast
+your ingress controller is at updating rules):
+
+```bash
+$ kubectl describe challenge quickstart-example-tls-889745041-0
+...
+Status:
+ Presented: false
+ Processing: false
+ Reason: Successfully authorized domain
+ State: valid
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Started 71s cert-manager Challenge scheduled for processing
+ Normal Presented 70s cert-manager Presented challenge using http-01 challenge mechanism
+ Normal DomainVerified 2s cert-manager Domain "www.example.com" verified with "http-01" validation
+```
+
+> Note: If your challenges are not becoming 'valid' and remain in the 'pending'
+> state (or enter into a 'failed' state), it is likely there is some kind of
+> configuration error. Read the [Challenge resource reference
+> docs](../../reference/api-docs.md#acme.cert-manager.io/v1.Challenge) for more
+> information on debugging failing challenges.
+
+Once the challenge(s) have been completed, their corresponding challenge
+resources will be *deleted*, and the 'Order' will be updated to reflect the
+new state of the Order:
+
+```bash
+$ kubectl describe order quickstart-example-tls-889745041
+...
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Created 90s cert-manager Created Challenge resource "quickstart-example-tls-889745041-0" for domain "www.example.com"
+ Normal OrderValid 16s cert-manager Order completed successfully
+```
+
+Finally, the 'Certificate' resource will be updated to reflect the state of the
+issuance process. If all is well, you should be able to 'describe' the Certificate
+and see something like the below:
+
+```bash
+$ kubectl describe certificate quickstart-example-tls
+Status:
+ Conditions:
+ Last Transition Time: 2019-01-09T13:57:52Z
+ Message: Certificate is up to date and has not expired
+ Reason: Ready
+ Status: True
+ Type: Ready
+ Not After: 2019-04-09T12:57:50Z
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Generated 11m cert-manager Generated new private key
+ Normal OrderCreated 11m cert-manager Created Order resource "quickstart-example-tls-889745041"
+ Normal OrderComplete 10m cert-manager Order "quickstart-example-tls-889745041" completed successfully
+```
diff --git a/content/v1.12-docs/tutorials/acme/pomerium-ingress.md b/content/v1.12-docs/tutorials/acme/pomerium-ingress.md
new file mode 100644
index 0000000000..90447f66af
--- /dev/null
+++ b/content/v1.12-docs/tutorials/acme/pomerium-ingress.md
@@ -0,0 +1,191 @@
+---
+title: Pomerium Ingress
+description: 'cert-manager tutorials: Solving ACME HTTP-01 challenges using Pomerium ingress'
+---
+
+This tutorial covers installing the [Pomerium Ingress Controller](https://pomerium.com/docs/k8s/ingress.html) and securing it with cert-manager. [Pomerium](https://pomerium.com) is an identity-aware proxy that can also provide a custom ingress controller for your Kubernetes services.
+
+## Prerequisites
+
+1. Install [Kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) and set the context to the cluster you'll be working with.
+
+1. Pomerium connects to an identity provider (**IdP**) to authenticate users. See one of their [guides](https://www.pomerium.com/docs/identity-providers/) to learn how to set up your IdP of choice to provide oauth2 validation.
+
+1. This tutorial assumes you have a domain space reserved for this cluster (such as `*.example.com`). You will need access to DNS for this domain to assign A and CNAME records as needed.
+
+## Install The Pomerium Ingress Controller
+
+1. Install Pomerium to your cluster:
+
+ ```sh
+ kubectl apply -f https://raw.githubusercontent.com/pomerium/ingress-controller/main/deployment.yaml
+ ```
+
+ Define a Secret with your IdP configuration. See Pomerium's [Identity Providers](https://www.pomerium.com/docs/identity-providers) pages for more information specific to your IdP:
+
+ ```yaml
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ name: idp
+ namespace: pomerium
+ type: Opaque
+ stringData:
+ client_id: ${IDP_PROVIDED_CLIENT_ID}
+ client_secret: ${IDP_PROVIDED_CLIENT_SECRET}
+ ```
+
+ Add the secret to the cluster with `kubectl apply -f`.
+
+1. Define the global settings for Pomerium:
+
+ ```yaml
+ apiVersion: ingress.pomerium.io/v1
+ kind: Pomerium
+ metadata:
+ name: global
+ namespace: pomerium
+ spec:
+ secrets: pomerium/bootstrap
+ authenticate:
+ url: https://authenticate.example.com
+ identityProvider:
+ provider: ${YOUR_IdP}
+ secret: pomerium/idp
+ # certificates:
+ # - pomerium/pomerium-proxy-tls
+ ```
+
+ Replace `${YOUR_IdP}` with your identity provider. Apply with `kubectl -f`.
+
+ Note that the last two lines are commented out. They reference a TLS certificate we will create further in the process.
+
+## Install cert-manager
+
+Install cert-manager using any of the methods documented in the [Installation](https://cert-manager.io/docs/installation/) section of the cert-manager docs. The simplest method is to download and apply the provided manifest:
+
+```sh
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.10.1/cert-manager.yaml
+```
+
+## Configure Let's Encrypt Issuer
+
+For communication between the Ingresses and the internet, we'll want to use certificates signed by a trusted certificate authority like Let's Encrypt. This example creates two Let's Encrypt issuers, one for staging and one for production.
+
+The Let's Encrypt production issuer has [strict rate limits](https://letsencrypt.org/docs/rate-limits/). Before your configuration is finalized you may have to recreate services several times, hitting those limits. It's easy to confuse rate limiting with errors in configuration or operation while building your stack.
+
+Because of this, we will start with the Let's Encrypt staging issuer. Once your configuration is all but finalized, we will switch to a production issuer. Both of these issuers are configured to use the [`HTTP01`](../../configuration/acme/http01/README.md) challenge provider.
+
+1. The following YAML defines a staging certificate issuer. You must update the email address to your own. The `email` field is required by Let's Encrypt and used to notify you of certificate expiration and updates.
+
+ ```yaml file=./example/pomerium-staging-issuer.yaml
+ ```
+
+ You can download and edit the example and apply it with `kubectl apply -f`, or edit, and apply the custom resource in one command:
+
+ ```bash
+ kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/pomerium-staging-issuer.yaml
+ ```
+
+1. Create a production issuer and deploy it. As with the staging issuer, update this example with your own email address:
+
+ ```yaml file=./example/pomerium-production-issuer.yaml
+ ```
+
+ ```bash
+ kubectl create --edit -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/pomerium-production-issuer.yaml
+ ```
+
+1. You can confirm on the status of the issuers after you create them:
+
+ ```bash
+ kubectl describe issuer -n pomerium letsencrypt-staging
+ kubectl describe issuer -n pomerium letsencrypt-prod
+ ```
+
+ You should see the issuer listed with a registered account.
+
+1. Define a certificate for the Pomerium Proxy service. This should be the only certificate you need to manually define:
+
+ ```yaml
+ apiVersion: cert-manager.io/v1
+ kind: Certificate
+ metadata:
+ name: pomerium-proxy-tls
+ namespace: pomerium
+ spec:
+ dnsNames:
+ - 'authenticate.example.com'
+ issuerRef:
+ kind: Issuer
+ name: letsencrypt-staging
+ secretName: pomerium-proxy-tls
+ ```
+
+ Adjust the `dnsNames` value to match your domain space. The subdomain (`authenticate` in our example) must match the domain used for the callback URL in your IdP configuration. Add the certificate with `kubectl -f`.
+
+1. Uncomment the last two lines of the Pomerium global configuration that reference your newly created certificate, and re-apply to the cluster.
+
+Pomerium should now be installed and running in your cluster. You can verify by going to `https://authenticate.example.com` in your browser. Use `kubectl describe pomerium` to review the status of the Pomerium deployment and see recent events.
+
+## Define a Test Service
+
+To test our new Ingress Controller, we will add the [kuard](https://github.com/kubernetes-up-and-running/kuard) app to our cluster and define an Ingress for it.
+
+1. Define the kuard deployment and associated service:
+
+ ```yaml file=./example/deployment.yaml
+ ```
+
+ ```yaml file=./example/service.yaml
+ ```
+
+ You can download and reference these files locally, or you can reference them from the GitHub source repository for this documentation.
+
+ To install the example service from the tutorial files straight from GitHub:
+
+ ```bash
+ kubectl apply -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/deployment.yaml
+ kubectl apply -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/service.yaml
+ ```
+
+1. Create a new Ingress manifest (`example-ingress.yaml`) for our test service:
+
+ ```yaml
+ apiVersion: networking.k8s.io/v1
+ kind: Ingress
+ metadata:
+ name: kuard
+ annotations:
+ cert-manager.io/issuer: letsencrypt-staging
+ ingress.pomerium.io/policy: '[{"allow":{"and":[{"domain":{"is":"example.com"}}]}}]'
+ spec:
+ ingressClassName: pomerium
+ rules:
+ - host: kuard.example.com
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: kuard
+ port:
+ number: 80
+ tls:
+ - hosts:
+ - kuard.example.com
+ secretName: kuard.example.com-tls
+ ```
+
+ Again, change the references to `example.com` to match your domain space.
+
+1. Apply the Ingress manifest to the cluster:
+
+ ```bash
+ kubectl apply -f example-ingress.yaml
+ ```
+
+The Pomerium Ingress Controller will use cert-manager to automatically provision a certificate from the `letsencrypt-staging` issuer for the route to `kuard.example.com`.
+
+Once you've configured all your application services correctly in the cluster, adjust the issuer for your Ingresses (including the Authenticate service) to use `letsencrypt-prod`.
diff --git a/content/docs/tutorials/backup.md b/content/v1.12-docs/tutorials/backup.md
similarity index 100%
rename from content/docs/tutorials/backup.md
rename to content/v1.12-docs/tutorials/backup.md
diff --git a/content/v1.12-docs/tutorials/getting-started-aks-letsencrypt/README.md b/content/v1.12-docs/tutorials/getting-started-aks-letsencrypt/README.md
new file mode 100644
index 0000000000..f712fa6b7a
--- /dev/null
+++ b/content/v1.12-docs/tutorials/getting-started-aks-letsencrypt/README.md
@@ -0,0 +1,687 @@
+---
+title: Deploy cert-manager on Azure Kubernetes Service (AKS) and use Let's Encrypt to sign a certificate for an HTTPS website
+description: |
+ Learn how to deploy cert-manager on Azure Kubernetes Service (AKS)
+ and configure it to get a signed certificate from Let's Encrypt for an HTTPS web server,
+ using the DNS-01 protocol and Azure DNS with workload identity federation.
+---
+
+*Last Verified: 10 January 2023*
+
+In this tutorial you will learn how to deploy and configure cert-manager on Azure Kubernetes Service (AKS)
+and how to deploy an HTTPS web server and make it available on the Internet.
+You will learn how to configure cert-manager to get a signed certificate from Let's Encrypt,
+which will allow clients to connect to your HTTPS website securely.
+You will configure cert-manager to use the [Let's Encrypt DNS-01 challenge protocol](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) with Azure DNS,
+using workload identity federation to authenticate to Azure.
+
+> **Microsoft Azure**: A suite of cloud computing services by Microsoft.
+> **Kubernetes**: Runs on your servers. Automates the deployment, scaling, and management of containerized applications.
+> **cert-manager**: Runs in Kubernetes. Obtains TLS / SSL certificates and ensures the certificates are valid and up-to-date.
+> **Let’s Encrypt**: An Internet service. Allows you to generate free short-lived SSL certificates.
+
+# Part 1
+
+In the first part of this tutorial you will learn the basics required to deploy an HTTPS website on an Azure Kubernetes cluster using cert-manager to create the SSL certificate for the web server.
+You will create a DNS domain for your website, create an Azure Kubernetes cluster, install cert-manager, create an SSL certificate and then deploy a web server which responds to HTTPS requests from clients on the Internet.
+But the SSL certificate in part 1 is only for testing purposes.
+
+In part 2 you will learn how to configure cert-manager to use Let's Encrypt and Azure DNS to create a trusted SSL certificate which you can use in production.
+
+## Configure the Azure CLI (`az`)
+
+If your have not already done so, [download and install the Azure CLI (`az`)](https://learn.microsoft.com/en-us/cli/azure/).
+
+Set up the `az` command for interactive use:
+
+```bash
+az init
+```
+
+Log in, if you have not already done so:
+
+```bash
+az login
+```
+
+Set the default resource group and location:
+
+```bash
+export AZURE_DEFAULTS_GROUP=your-resource-group # ❗ Your Azure resource group
+export AZURE_DEFAULTS_LOCATION=eastus2 # ❗ Your Azure location.
+```
+
+> ℹ️ You will need an `az` version `>=2.40.0`. Run `az version` to print the current version.
+>
+> ℹ️ When you run `az init`, choose "Optimize for interaction" when prompted.
+>
+> ℹ️ When you run `az login`, a web browser will be opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize.
+> Continue the login in the web browser and then return to your terminal.
+>>
+> 📖 Read the [Azure Command-Line Interface (CLI) documentation](https://learn.microsoft.com/en-us/cli/azure/).
+>
+> 📖 Read [CLI configuration values and environment variables](https://learn.microsoft.com/en-us/cli/azure/azure-cli-configuration?source=recommendations#cli-configuration-values-and-environment-variables) for more ways to configure the `az` defaults.
+
+## Create a public domain name
+
+In this tutorial you will deploy an HTTPS website with a publicly accessible domain name, so you will need to register a domain unless you already have one.
+You could use any [domain name registrar](https://www.cloudflare.com/en-gb/learning/dns/glossary/what-is-a-domain-name-registrar/) to register a domain name for your site.
+Here we will use a registrar called `Gandi` and register a cheap domain name for the purposes of this tutorial.
+We will use the domain name: `cert-manager-tutorial-22.site` but you should choose your own.
+
+Now that you know your domain name, save it in an environment variable:
+
+```bash
+export DOMAIN_NAME=cert-manager-tutorial-22.site # ❗ Replace this with your own DNS domain name
+```
+
+And add it to Azure DNS as a zone:
+
+```bash
+az network dns zone create --name $DOMAIN_NAME
+```
+
+Log in to the control panel for your domain registrar and set the NS records for your domain to match the DNS names of the Azure [authoritative DNS servers](https://www.cloudflare.com/en-gb/learning/dns/dns-server-types/).
+You can find these by looking for the NS records of your Azure hosted DNS zone:
+
+```bash
+az network dns zone show --name $DOMAIN_NAME --output yaml
+```
+
+You can check that the NS records have been updated using `dig` to "trace" the hierarchy of NS records,
+rather than using your local DNS resolver:
+
+```bash
+dig $DOMAIN_NAME ns +trace +nodnssec
+```
+
+> ⏲ It **may** take more than 1 hour for the NS records to be updated in the parent zone,
+> and it may take some time for the old NS records to be replaced in the caches of DNS resolver servers,
+> if you looked up the DNS name before updating the NS records.
+>
+> 📖 Read [How do I Update My DNS Records?](https://docs.gandi.net/en/domain_names/common_operations/dns_records.html) in the `Gandi.net` docs,
+> or seek the equivalent documentation for your own domain name registrar.
+
+## Create a Kubernetes cluster
+
+To get started, let's create a Kubernetes cluster in Microsoft Azure.
+You will need to pick a name for your cluster.
+Here, we will go with "test-cluster-1".
+Save it in an environment variable:
+
+```bash
+export CLUSTER=test-cluster-1
+```
+
+Now, create the cluster using the following command:
+
+```bash
+az aks create \
+ --name ${CLUSTER} \
+ --node-count 1 \
+ --node-vm-size "Standard_B2s" \
+ --load-balancer-sku basic
+```
+
+Update your `kubectl` config file with the credentials for your new cluster:
+
+```bash
+az aks get-credentials --admin --name "$CLUSTER"
+```
+
+Now check that you can connect to the cluster:
+
+```bash
+kubectl get nodes -o wide
+```
+
+> ⏲ It will take 4-5 minutes to create the cluster.
+>
+> 💵 To minimize your cloud bill, this command creates a 1-node cluster using a
+> low cost virtual machine and load balancer.
+>
+> ⚠️ This cluster is only suitable for learning purposes it is not suitable for production use.
+>
+> 📖 Read [Run Kubernetes in Azure the Cheap Way](https://trstringer.com/cheap-kubernetes-in-azure/) for more cost saving tips.
+>
+
+## Install cert-manager
+
+Now you can install and configure cert-manager.
+
+Install cert-manager using `helm` as follows:
+
+```bash
+helm repo add jetstack https://charts.jetstack.io
+helm repo update
+helm upgrade cert-manager jetstack/cert-manager \
+ --install \
+ --create-namespace \
+ --wait \
+ --namespace cert-manager \
+ --set installCRDs=true
+```
+
+This will create three Deployments and some Services and Pods in a new namespace called `cert-manager`.
+It also installs various cluster scoped supporting resources such as RBAC roles and Custom Resource Definitions.
+
+You can view some of the resources that have been installed as follows:
+
+```bash
+kubectl -n cert-manager get all
+```
+
+And you can explore the Custom Resource Definitions (cert-manager's API) using `kubectl explain`, as follows:
+
+```bash
+kubectl explain Certificate
+kubectl explain CertificateRequest
+kubectl explain Issuer
+```
+
+> 📖 Read about [other ways to install cert-manager](../../installation/README.md).
+>
+> 📖 Read more about [Certificates and Issuers](../../concepts/README.md).
+
+## Create a test ClusterIssuer and a Certificate
+
+Now everything is ready for you to create your first certificate.
+This will be a self-signed certificate but later we'll replace it with a Let's Encrypt signed certificate.
+
+```yaml file=../../../../public/docs/tutorials/getting-started-aks-letsencrypt/clusterissuer-selfsigned.yaml
+```
+🔗 `clusterissuer-selfsigned.yaml`
+
+```bash
+kubectl apply -f clusterissuer-selfsigned.yaml
+```
+
+Then use `envsubst` to substitute your chosen domain name into the following Certificate template:
+
+```yaml file=../../../../public/docs/tutorials/getting-started-aks-letsencrypt/certificate.yaml
+```
+🔗 `certificate.yaml`
+
+```bash
+envsubst < certificate.yaml | kubectl apply -f -
+```
+
+> 🔗 If you don't already have `envsubst` installed you can [download and install a Go implementation of `envsubst`](https://github.com/a8m/envsubst).
+
+Use `cmctl status certificate` to check the status of the Certificate:
+
+```bash
+cmctl status certificate www
+```
+
+If successful, the private key and the signed certificate will be stored in a Secret called `www-tls`.
+You can use `cmctl inspect secret www-tls` to decode the base64 encoded X.509 content of the Secret:
+
+```terminal
+$ cmctl inspect secret www-tls
+...
+Valid for:
+ DNS Names:
+ - www.cert-manager-tutorial-22.site
+ URIs:
+ IP Addresses:
+ Email Addresses:
+ Usages:
+ - digital signature
+ - key encipherment
+ - server auth
+...
+```
+
+## Deploy a sample web server
+
+Now deploy a simple web server which responds to HTTPS requests with "hello world!".
+The SSL / TLS key and certificate are supplied to the web server by using the `www-tls` Secret as a volume
+and by mounting its contents into the file system of the `hello-app` container in the Pod:
+
+```yaml file=../../../../public/docs/tutorials/getting-started-aks-letsencrypt/deployment.yaml
+```
+🔗 `deployment.yaml`
+
+```bash
+kubectl apply -f deployment.yaml
+```
+
+You also need to create a Kubernetes LoadBalancer Service, so that connections from the Internet can be routed to the web server Pod.
+When you create the following Kubernetes Service, an Azure load balancer with an ephemeral public IP address will also be created:
+
+```yaml file=../../../../public/docs/tutorials/getting-started-aks-letsencrypt/service.yaml
+```
+🔗 `service.yaml`
+
+Create a unique DNS name for the LoadBalancer Service and then apply it:
+```bash
+export AZURE_LOADBALANCER_DNS_LABEL_NAME=lb-$(uuidgen) # ❗ The label must start with a lowercase ASCII letter
+envsubst < service.yaml | kubectl apply -f -
+```
+
+Within 2-3 minutes, a load balancer should have been provisioned with a public IP.
+
+```bash
+kubectl get service helloweb
+```
+
+Sample output
+
+```terminal
+$ kubectl get service helloweb
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+helloweb LoadBalancer 10.0.141.1 20.114.151.62 443:30394/TCP 7m15s
+```
+
+The `EXTERNAL-IP` will be different for you and it may be different each time you re-create the LoadBalancer service,
+but it will have a stable DNS host name associated with it
+because you annotated the Service with `azure-dns-label-name`.
+This stable DNS hostname can be used as an alias for your chosen `$DOMAIN_NAME` by creating a [DNS CNAME record](https://www.cloudflare.com/en-gb/learning/dns/dns-records/dns-cname-record/):
+
+```bash
+az network dns record-set cname set-record \
+ --zone-name $DOMAIN_NAME \
+ --cname $AZURE_LOADBALANCER_DNS_LABEL_NAME.$AZURE_DEFAULTS_LOCATION.cloudapp.azure.com \
+ --record-set-name www
+```
+
+Check that `www.$DOMAIN_NAME` now resolves to the ephemeral public IP address of the load balancer:
+
+```terminal
+$ dig www.$DOMAIN_NAME A
+...
+;; QUESTION SECTION:
+;www.cert-manager-tutorial-22.site. IN A
+...
+;; ANSWER SECTION:
+www.cert-manager-tutorial-22.site. 3600 IN CNAME lb-ec8776e1-d067-4d4c-8cce-fdf07ce48260.eastus2.cloudapp.azure.com.
+lb-ec8776e1-d067-4d4c-8cce-fdf07ce48260.eastus2.cloudapp.azure.com. 10 IN A 20.122.27.189
+...
+```
+
+If the DNS is correct and the load balancer is working and the hello world web server is running,
+you should now be able to connect to it using curl or using your web browser:
+
+```bash
+curl --insecure -v https://www.$DOMAIN_NAME
+```
+
+> ⚠️ We used curl's `--insecure` option because it rejects self-signed certificates by default.
+> Later you will learn how to create a trusted certificate signed by Let's Encrypt.
+
+You should see that the certificate has the expected DNS names and that it is self-signed:
+
+```terminal
+...
+* Server certificate:
+* subject: CN=www.cert-manager-tutorial-22.site
+* start date: Jan 4 15:28:30 2023 GMT
+* expire date: Apr 4 15:28:30 2023 GMT
+* issuer: CN=www.cert-manager-tutorial-22.site
+* SSL certificate verify result: self-signed certificate (18), continuing anyway.
+...
+Hello, world!
+Protocol: HTTP/2.0!
+Hostname: helloweb-55cb4cd887-tjlvh
+```
+
+> 📖 Read more about [Using a Service to Expose Your App](https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/expose-intro/).
+>
+> 📖 Read more about [Using a public IP address and DNS label with the Azure Kubernetes Service (AKS) load balancer](https://learn.microsoft.com/en-us/azure/aks/static-ip).
+
+# Part 2
+
+In part 1 you created a test certificate.
+Now you will learn how to configure cert-manager to use Let's Encrypt and Azure DNS to create a trusted certificate which you can use in production.
+You need to prove to Let's Encrypt that you own the domain name of the certificate and one way to do this is to create a special DNS record in that domain.
+This is known as the [DNS-01 challenge type](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge).
+
+cert-manager can create that DNS record for you in by using the Azure DNS API but it needs to authenticate to Azure first,
+and currently the most secure method of authentication is to use [workload identity federation](https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview).
+The advantages of this method are that cert-manager will use an ephemeral Kubernetes ServiceAccount Token to authenticate to Azure and the token need not be stored in a Kubernetes Secret.
+
+> ℹ️ cert-manager `>= v1.11.0` supports workload identity federation for ACME (Let's Encrypt) DNS-01 with Azure DNS.
+> Older versions of cert-manager support other authentication mechanisms which are not covered in this tutorial.
+>
+> 📖 Read about [other ways to configure the ACME issuer with Azure DNS](../../configuration/acme/dns01/azuredns.md).
+
+## Install the Azure workload identity features
+
+The workload identity features in Azure AKS are relatively new (at time of writing) and they require some non-default features to be enabled.
+
+Install the [Azure CLI AKS Preview Extension](https://github.com/Azure/azure-cli-extensions/tree/main/src/aks-preview),
+which you will need to configure some advanced workload identity federation features on your AKS cluster.
+
+```bash
+az extension add --name aks-preview
+```
+
+Register the `EnableWorkloadIdentityPreview` feature flag which is required for the AKS cluster in this demo.
+
+```bash
+az feature register --namespace "Microsoft.ContainerService" --name "EnableWorkloadIdentityPreview"
+
+# It takes a few minutes for the status to show Registered. Verify the registration status by using the az feature list command:
+az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/EnableWorkloadIdentityPreview')].{Name:name,State:properties.state}"
+
+# When ready, refresh the registration of the Microsoft.ContainerService resource provider by using the az provider register command:
+az provider register --namespace Microsoft.ContainerService
+```
+
+> 📖 Read more about [Registering the `EnableWorkloadIdentityPreview` feature flag](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster).
+
+## Reconfigure the cluster
+
+Next enable the workload identity federation features on the cluster that you created earlier:
+
+```bash
+az aks update \
+ --name ${CLUSTER} \
+ --enable-oidc-issuer \
+ --enable-workload-identity # ℹ️ This option is currently only available when using the aks-preview extension.
+```
+
+> 📖 Read [Deploy and configure workload identity on an Azure Kubernetes Service (AKS) cluster](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster) for more information about the `--enable-workload-identity` feature.
+
+## Reconfigure cert-manager
+
+We will label the cert-manager controller Pod and ServiceAccount for the attention of the Azure Workload Identity webhook,
+which will result in the cert-manager controller Pod having an extra volume containing a Kubernetes ServiceAccount token which it will use to authenticate with Azure.
+
+The labels can be configured using the Helm values file below:
+
+```yaml file=../../../../public/docs/tutorials/getting-started-aks-letsencrypt/values.yaml
+```
+🔗 `values.yaml`
+
+```bash
+helm upgrade cert-manager jetstack/cert-manager \
+ --namespace cert-manager \
+ --reuse-values \
+ --values values.yaml
+```
+
+The newly rolled out cert-manager Pod will have some new environment variables set,
+and the Azure workload-identity ServiceAccount token as a projected volume:
+
+```bash
+kubectl describe pod -n cert-manager -l app.kubernetes.io/component=controller
+```
+
+```terminal
+Containers:
+ ...
+ cert-manager-controller:
+ ...
+ Environment:
+ ...
+ AZURE_CLIENT_ID:
+ AZURE_TENANT_ID: f99bd6a4-665c-41cf-aff1-87a89d5c62d4
+ AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/azure/tokens/azure-identity-token
+ AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/
+ Mounts:
+ /var/run/secrets/azure/tokens from azure-identity-token (ro)
+Volumes:
+ ...
+ azure-identity-token:
+ Type: Projected (a volume that contains injected data from multiple sources)
+ TokenExpirationSeconds: 3600
+```
+
+> 📖 Read about [the role of the Mutating Admission Webhook](https://azure.github.io/azure-workload-identity/docs/installation/mutating-admission-webhook.html) in Azure AD Workload Identity for Kubernetes.
+>
+> 📖 Read about [other values that can be customized in the cert-manager Helm chart](https://artifacthub.io/packages/helm/cert-manager/cert-manager?modal=values).
+
+## Create an Azure Managed Identity
+
+When cert-manager creates a certificate using Let's Encrypt
+it can use DNS records to prove that it controls the DNS domain names in the certificate.
+In order for cert-manager to use the Azure API and manipulate the records in the Azure DNS zone,
+it needs an Azure account and the best type of account to use is called a "Managed Identity".
+This account does not come with a password or an API key and it is designed for use by machines rather than humans.
+
+Choose a managed identity name:
+
+```bash
+export USER_ASSIGNED_IDENTITY_NAME=cert-manager-tutorials-1 # ❗ Replace with your preferred managed identity name
+```
+
+Create the Managed Identity:
+
+```bash
+az identity create --name "${USER_ASSIGNED_IDENTITY_NAME}"
+```
+
+Grant it permission to modify the DNS zone records:
+
+```bash
+export USER_ASSIGNED_IDENTITY_CLIENT_ID=$(az identity show --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -o tsv)
+az role assignment create \
+ --role "DNS Zone Contributor" \
+ --assignee $USER_ASSIGNED_IDENTITY_CLIENT_ID \
+ --scope $(az network dns zone show --name $DOMAIN_NAME -o tsv --query id)
+```
+
+> 📖 Read [What are managed identities for Azure resources?](https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview)
+> for an overview of managed identities and their uses.
+>
+> 📖 Read [Azure built-in roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles) to learn about the "DNS Zone Contributor" role.
+
+## Add a federated identity
+
+Now we will configure Azure to trust certain Kubernetes ServiceAccount tokens,
+in particular, the service account tokens from our specific Kubernetes cluster,
+and only tokens which are associated with the cert-manager ServiceAccount.
+cert-manager will authenticate to Azure using an short lived Kubernetes ServiceAccount token,
+and it will be able to impersonate the managed identity that you created in the previous step.
+
+First export the following environment variables containing the name and namespace of the Kubernetes ServiceAccount used by the cert-manager controller:
+
+```bash
+export SERVICE_ACCOUNT_NAME=cert-manager # ℹ️ This is the default Kubernetes ServiceAccount used by the cert-manager controller.
+export SERVICE_ACCOUNT_NAMESPACE=cert-manager # ℹ️ This is the default namespace for cert-manager.
+```
+
+Then configure the managed identity to trust the cert-manager Kubernetes ServiceAccount,
+by supplying its "subject" (the distinguishing name of the Kubernetes ServiceAccount)
+and its "issuer" (a URL at which the JWT signing certificate and other metadata can be downloaded):
+
+```bash
+export SERVICE_ACCOUNT_ISSUER=$(az aks show --resource-group $AZURE_DEFAULTS_GROUP --name $CLUSTER --query "oidcIssuerProfile.issuerUrl" -o tsv)
+az identity federated-credential create \
+ --name "cert-manager" \
+ --identity-name "${USER_ASSIGNED_IDENTITY_NAME}" \
+ --issuer "${SERVICE_ACCOUNT_ISSUER}" \
+ --subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}"
+```
+
+> 📖 Read about [Workload identity federation](https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation) in the Microsoft identity platform documentation.
+
+
+## Create a ClusterIssuer for Let's Encrypt Staging
+
+A ClusterIssuer is a custom resource which tells cert-manager how to sign a Certificate.
+In this case the ClusterIssuer will be configured to connect to the Let's Encrypt staging server,
+which allows us to test everything without using up our Let's Encrypt certificate quota for the domain name.
+
+Save the following content to a file called `clusterissuer-lets-encrypt-staging.yaml`, change the `email` field to use your email address and apply it:
+
+```yaml file=../../../../public/docs/tutorials/getting-started-aks-letsencrypt/clusterissuer-lets-encrypt-staging.yaml
+```
+🔗 `clusterissuer-lets-encrypt-staging.yaml`
+
+
+As you can see there are some variables in the `clusterissuer-lets-encrypt-staging.yaml` which need to be filled in before we apply it;
+most have been defined earlier in this tutorial but you need to set the following:
+
+```bash
+export EMAIL_ADDRESS= # ❗ Replace this with your email address
+export AZURE_SUBSCRIPTION= # ❗ Replace this with your Azure account name
+```
+
+Now use `envsubst` to fill in the variables and pipe it into `kubectl apply`, as follows:
+
+```bash
+export AZURE_SUBSCRIPTION_ID=$(az account show --name $AZURE_SUBSCRIPTION --query 'id' -o tsv)
+envsubst < clusterissuer-lets-encrypt-staging.yaml | kubectl apply -f -
+```
+
+You can check the status of the ClusterIssuer:
+
+```bash
+kubectl describe clusterissuer letsencrypt-staging
+```
+
+Example output
+
+```console
+Status:
+ Acme:
+ Last Registered Email: firstname.lastname@example.com
+ Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/77882854
+ Conditions:
+ Last Transition Time: 2022-11-29T13:05:33Z
+ Message: The ACME account was registered with the ACME server
+ Observed Generation: 1
+ Reason: ACMEAccountRegistered
+ Status: True
+ Type: Ready
+```
+
+> ℹ️ Let's Encrypt uses the Automatic Certificate Management Environment (ACME) protocol
+> which is why the configuration above is under a key called `acme`.
+>
+> ℹ️ The email address is only used by Let's Encrypt to remind you to renew the certificate after 30 days before expiry. You will only receive this email if something goes wrong when renewing the certificate with cert-manager.
+>
+> ℹ️ The Let's Encrypt production issuer has [very strict rate limits](https://letsencrypt.org/docs/rate-limits/).
+> When you're experimenting and learning, it can be very easy to hit those limits. Because of that risk,
+> we'll start with the Let's Encrypt staging issuer, and once we're happy that it's working
+> we'll switch to the production issuer.
+>
+> 📖 Read more about [configuring the ACME Issuer](../../configuration/acme/README.md).
+>
+
+
+## Re-issue the Certificate using Let's Encrypt
+
+Patch the Certificate to use the staging ClusterIssuer:
+
+```bash
+kubectl patch certificate www --type merge -p '{"spec":{"issuerRef":{"name":"letsencrypt-staging"}}}'
+```
+
+That should trigger cert-manager to renew the certificate:
+Use `cmctl` to check:
+
+```bash
+cmctl status certificate www
+cmctl inspect secret www-tls
+```
+
+And finally, when the new certificate has been issued, you must restart the web server to use it:
+
+```bash
+kubectl rollout restart deployment helloweb
+```
+
+You should once again be able to connect to the website, but this time you will see the Let's Encrypt staging certificate:
+
+```terminal
+$ curl -v --insecure https://www.$DOMAIN_NAME
+...
+* Server certificate:
+* subject: CN=www.cert-manager-tutorial-22.site
+* start date: Jan 5 12:41:14 2023 GMT
+* expire date: Apr 5 12:41:13 2023 GMT
+* issuer: C=US; O=(STAGING) Let's Encrypt; CN=(STAGING) Artificial Apricot R3
+* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
+...
+Hello, world!
+Protocol: HTTP/2.0!
+Hostname: helloweb-9b8bcdd56-6rxm8
+```
+
+> ⚠️ We used curl's `--insecure` option again here because the Let's Encrypt staging issuer creates untrusted certificates.
+> Next you will learn how to create a trusted certificate signed by the Let's Encrypt production issuer.
+
+## Create a production ready certificate
+
+Now that everything is working with the Let's Encrypt staging server, we can switch to the production server and get a trusted certificate.
+
+Create a Let's Encrypt production Issuer by copying the staging ClusterIssuer YAML and modifying the server URL and the names,
+then apply it:
+
+```yaml file=../../../../public/docs/tutorials/getting-started-aks-letsencrypt/clusterissuer-lets-encrypt-production.yaml
+```
+🔗 `clusterissuer-lets-encrypt-production.yaml`
+
+
+```bash
+envsubst < clusterissuer-lets-encrypt-production.yaml | kubectl apply -f -
+```
+
+Check the status of the ClusterIssuer:
+
+```bash
+kubectl describe clusterissuer letsencrypt-production
+```
+
+Patch the Certificate to use the production ClusterIssuer:
+
+```bash
+kubectl patch certificate www --type merge -p '{"spec":{"issuerRef":{"name":"letsencrypt-production"}}}'
+```
+
+That should trigger cert-manager to renew the certificate:
+Use `cmctl` to check:
+
+```bash
+cmctl status certificate www
+cmctl inspect secret www-tls
+```
+
+And finally, when the new certificate has been issued, you must restart the web server to use it:
+
+```bash
+kubectl rollout restart deployment helloweb
+```
+
+Now you should be able to connect to the web server securely, without the `--insecure` flag,
+and if you visit the site in your web browser, it should show a padlock (🔒) symbol next to the URL.
+
+```bash
+curl -v https://www.$DOMAIN_NAME
+```
+
+```terminal
+...
+* Server certificate:
+* subject: CN=cert-manager-tutorial-22.site
+* start date: Nov 30 15:41:40 2022 GMT
+* expire date: Feb 28 15:41:39 2023 GMT
+* subjectAltName: host "www.cert-manager-tutorial-22.site" matched cert's "www.cert-manager-tutorial-22.site"
+* issuer: C=US; O=Let's Encrypt; CN=R3
+* SSL certificate verify ok.
+...
+```
+
+That concludes this tutorial.
+You have learned how to deploy cert-manager on Azure AKS and how to configure it to issue Let's Encrypt signed certificates using the DNS-01 protocol with Azure DNS.
+You have learned about workload identity federation in Azure and learned how to configure cert-manager to authenticate to Azure using a Kubernetes ServiceAccount Token.
+
+## Cleanup
+
+After completing the tutorial you can clean up by deleting the cluster, the domain name and the managed identity, as follows:
+
+```
+az aks delete --name $CLUSTER
+az network dns zone delete --name $DOMAIN_NAME
+az identity delete --name $USER_ASSIGNED_IDENTITY_NAME
+```
+
+## Next Steps
+
+> 📖 Read other [cert-manager tutorials](../README.md) and [getting started guides](../../getting-started/README.md).
+>
+> 📖 Read more about [configuring the cert-manager ACME issuer with Azure DNS](../../configuration/acme/dns01/azuredns.md).
diff --git a/content/v1.12-docs/tutorials/getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/README.md b/content/v1.12-docs/tutorials/getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/README.md
new file mode 100644
index 0000000000..80f233aee7
--- /dev/null
+++ b/content/v1.12-docs/tutorials/getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/README.md
@@ -0,0 +1,779 @@
+---
+title: Deploy cert-manager on Google Kubernetes Engine (GKE) and create SSL certificates for Ingress using Let's Encrypt
+description: Learn how to deploy cert-manager on Google Kubernetes (GKE) Engine and then configure it to sign SSL certificates using Let's Encrypt
+---
+
+*Last Verified: 15 July 2022*
+
+In this tutorial you will learn how to deploy and configure cert-manager on Google Kubernetes Engine (GKE).
+You will learn how to configure cert-manager to get a signed SSL certificate from Let's Encrypt,
+using an [HTTP-01 challenge](https://letsencrypt.org/docs/challenge-types/#http-01-challenge).
+Finally you will learn how the certificate can be used to serve an HTTPS website with a public domain name.
+
+> **Google Cloud**: A suite of cloud computing services by Google.
+> **Kubernetes**: Runs on your servers. Automates the deployment, scaling, and management of containerized applications.
+> **cert-manager**: Runs in Kubernetes. Obtains TLS / SSL certificates and ensures the certificates are valid and up-to-date.
+> **Let’s Encrypt**: An Internet service. Allows you to generate free short-lived SSL certificates.
+
+First you will create a Kubernetes (GKE) cluster and deploy a sample web server.
+You will then create a public IP address and a public domain name for your website.
+You'll set up Ingress and Google Cloud load balancers so that Internet clients can connect to the web server using HTTP.
+Finally you will use cert-manager to get an SSL certificate from Let's Encrypt
+and configure the load balancer to use that certificate.
+By the end of this tutorial you will be able to connect to your website from the Internet using an `https://` URL.
+
+## Prerequisites
+
+**💻 Google Cloud account**
+
+You will need a Google Cloud account.
+Registration requires a credit card or bank account details.
+Visit the [Get started with Google Cloud](https://cloud.google.com/docs/get-started) page and follow the instructions.
+
+> 💵 If you have never used Google Cloud before, you may be eligible for the
+> [Google Cloud Free
+> Program](https://cloud.google.com/free/docs/gcp-free-tier/#free-trial), which
+> gives you a 90 day trial period that includes $300 in free Cloud Billing
+> credits to explore and evaluate Google Cloud.
+
+**💻 Domain Name**
+
+You will need a domain name and the ability to create DNS records in that domain. We will be getting a $12 domain name from Google Domains. Google Domains is one of the many possible "domain name registrars". NameCheap and GoDaddy are two other well-known registrars.
+
+> 💵 If you prefer not purchasing a domain name, it is also possible to adapt this tutorial to use the IP address to serve your website and for the SSL certificate.
+
+**💻 Software**
+
+
+You will also need to install the following software on your laptop:
+
+1. [gcloud](https://cloud.google.com/sdk/docs/install): A set of tools to create and manage Google Cloud resources.
+2. [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl): The Kubernetes command-line tool which allows you to configure Kubernetes clusters.
+3. [curl](https://everything.curl.dev/get): A command-line tool for connecting to a web server using HTTP and HTTPS.
+
+> ℹ️ Try running `gcloud components install kubectl` to quickly install `kubectl`.
+
+## 0. Configure `gcloud` with a Google Cloud project
+
+If you don't have a Google Cloud account, the command below will create one for you:
+
+```bash
+gcloud init
+```
+
+You will need to answer "yes" to the following question:
+
+```text
+Do you want to configure a default Compute Region and Zone? (Y/n)? Y
+```
+
+After running the command, you will shown the project name, default region, and default zone.
+
+Example output:
+
+```text
+* Commands that require authentication will use firstname.lastname@example.com by default
+* Commands will reference project `your-project` by default
+* Compute Engine commands will use region `europe-west1` by default
+* Compute Engine commands will use zone `europe-west1-b` by default
+```
+
+In this tutorial, we will refer to the name of the project that was selected while running `gcloud init` with the variable `PROJECT`. Where ever you see `$PROJECT` in a command, you need to either (1) replace the variable manually before you execute the command,
+or (2) export the variable in your shell session. This applies to all environment variables that you will encounter in the commands listed in this tutorial.
+
+We will go with option (2), so we need to export the environment variables before continuing using the information that was printed by `gcloud init`:
+
+```bash
+export PROJECT=your-project # Your Google Cloud project ID.
+export REGION=europe-west1 # Your Google Cloud region.
+```
+
+## 1. Create a Kubernetes Cluster
+
+To get started, let's create a Kubernetes cluster in Google Cloud. You will need to pick a name for your cluster. Here, we will go with "test-cluster-1". Let us save it in an environment variable:
+
+```bash
+export CLUSTER=test-cluster-1
+```
+
+Now, create the cluster using the following command:
+
+```bash
+gcloud container clusters create $CLUSTER --preemptible --num-nodes=1
+```
+
+Set up the [Google Kubernetes Engine auth plugin for kubectl](https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke):
+
+```bash
+gcloud components install gke-gcloud-auth-plugin
+export USE_GKE_GCLOUD_AUTH_PLUGIN=True
+gcloud container clusters get-credentials $CLUSTER
+```
+
+Now check that you can connect to the cluster:
+
+```bash
+kubectl get nodes -o wide
+```
+
+> ⏲ It will take 4-5 minutes to create the cluster.
+>
+> 💵 To minimize your cloud bill, this command creates a 1-node cluster using a
+> [preemptible virtual
+> machine](https://cloud.google.com/kubernetes-engine/docs/how-to/preemptible-vms)
+> which is cheaper than a normal virtual machine.
+
+## 2. Deploy a sample web server
+
+We will deploy a very simple web server which responds to HTTP requests with "hello world!".
+
+```bash
+kubectl create deployment web --image=gcr.io/google-samples/hello-app:1.0
+```
+
+We also need to create a Kubernetes Service, so that connections can be routed to the web server Pods:
+
+```bash
+kubectl expose deployment web --port=8080
+```
+
+> ℹ️ These [kubectl imperative commands](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/imperative-command/) are used for readability and brevity.
+> Feel free to use YAML manifests and `kubectl apply -f` instead.
+>
+> ℹ️ The Service created by `kubectl expose` will be of type `ClusterIP` (the default) and this is only reachable by components within the cluster. Later we will create an Ingress which is how we make the service available to clients outside the cluster.
+>
+> 🔰 Read more about [Using a Service to Expose Your App](https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/expose-intro/).
+
+## 3. Create a static external IP address
+
+This tutorial is about creating a public facing HTTPS website with a Let's Encrypt SSL certificate using the HTTP01 challenge mechanism,
+so we need a public IP address so that both Let's Encrypt and other Internet clients can connect to your website.
+
+It is easy to create a public IP address in Google Cloud and later we will associate it with your website domain name and with a Google Cloud load balancer, which will accept HTTP(S) connections from Internet clients and proxy the requests to the web servers running in your cluster.
+
+Create a global static IP address as follows:
+
+```bash
+gcloud compute addresses create web-ip --global
+```
+
+You should see the new IP address listed:
+
+```bash
+gcloud compute addresses list
+```
+
+> ⚠️ You MUST create a `global` IP address because that is a prerequisite of the [External HTTP(S) Load Balancer](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress-xlb) which we will be using in this tutorial.
+>
+> 💵 Global static IP addresses are only available in the Premium network service tier and are more expensive than ephemeral and standard public IP addresses.
+>
+> 🔰 Read more about [Network service tiers in Google Cloud](https://cloud.google.com/network-tiers).
+>
+> 🔰 Read more about [Reserving a static external IP address in Google Cloud](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address).
+
+Finally, we will save the IP address into an environment variable for later use. Display the IP address with the following command:
+
+```bash
+gcloud compute addresses describe web-ip --format='value(address)' --global
+```
+
+Then, copy the output and save it into an environment variable:
+
+```bash
+export IP_ADDRESS=198.51.100.1 # Replace with your IP address
+```
+
+## 4. Create a domain name for your website
+
+You will need a domain name for your website and Let's Encrypt checks your domain before it signs your SSL certificate,
+so the domain name needs to be reachable from the Internet.
+
+We will purchase a cheap domain name using a credit card. Go to https://domains.google.com, and type something in the search box. For the example, we searched for `hello-app.com` because the example container that we will be deploying is called `hello-app`. Most importantly, we make sure to sort the domain names by price:
+
+![](/images/getting-started/screenshot_google-domains_get-a-new-domain.png)
+
+We don't pick `hello-app.com` because it costs $2,800; instead, we go with the one at the top: `heyapp.net`. It looks good! We then click the cart button. On the next screen, you will want to disable the auto-renewal, since we don't want to pay for this domain every year:
+
+![](/images/getting-started/screenshot_google-domains_your-cart.png)
+
+Now that you know your domain name, save it in an environment variable:
+
+```bash
+export DOMAIN_NAME=heyapp.net
+```
+
+Next, you will need to create a new `A` record pointing at the IP address that we created above. Head back to https://domains.google.com/registrar, open your domain (here, `heyapp.net`) and click "DNS" on the left menu. You will see "Custom records". You want to add a new record of type `A` and put the IP address from the previous step into "data". You must leave "Host name" empty because we are configuring the top-level domain name:
+
+![](/images/getting-started/screenshot_google-domains_resource-records.png)
+
+> 🔰 Learn more about [What is a DNS A record? from the Cloudflare DNS tutorial](https://www.cloudflare.com/learning/dns/dns-records/dns-a-record/).
+
+> ℹ️ It is not strictly necessary to create a domain name for your website. You can connect to it using the IP address and later you can create an SSL certificate for the IP address instead of a domain name. If for some reason you can't create a domain name, then feel free to skip this section and adapt the instructions below to use an IP address instead.
+>
+> ℹ️ Every Google Cloud address has an automatically generated reverse DNS name like `51.159.120.34.bc.googleusercontent.com`,
+> but the parent domain `googleusercontent.com` has a CAA record which prevents
+> Let's Encrypt from signing certificates for the sub-domains.
+> See [Certificate Authority Authorization (CAA)](https://letsencrypt.org/docs/caa/) in the Let's Encrypt documentation.
+
+## 5. Create an Ingress
+
+You won't be able to reach your website yet.
+Your web server is running inside your Kubernetes cluster but there is no route or proxy through which Internet clients can connect to it, yet!
+Now we will create a Kubernetes Ingress object and in Google Cloud this will trigger the creation of a various services which together allow Internet clients to reach your web server running inside your Kubernetes cluster.
+
+Initially we are going to create an HTTP (not an HTTPS) Ingress so that we can test the basic connectivity before adding the SSL layer.
+
+Copy the following YAML into a file called `ingress.yaml` and apply it:
+
+```yaml
+# ingress.yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: web-ingress
+ annotations:
+ # This tells Google Cloud to create an External Load Balancer to realize this Ingress
+ kubernetes.io/ingress.class: gce
+ # This enables HTTP connections from Internet clients
+ kubernetes.io/ingress.allow-http: "true"
+ # This tells Google Cloud to associate the External Load Balancer with the static IP which we created earlier
+ kubernetes.io/ingress.global-static-ip-name: web-ip
+spec:
+ defaultBackend:
+ service:
+ name: web
+ port:
+ number: 8080
+```
+
+```bash
+kubectl apply -f ingress.yaml
+```
+
+This will trigger the creation of a Google HTTP(S) loadbalancer associated with the IP address that you created earlier.
+You can watch the progress and the resources that are being created:
+
+```bash
+kubectl describe ingress web-ingress
+```
+
+Within 4-5 minutes all the load balancer components should be ready and you should be able to connect to the DNS name and see the response from the hello-world web server that we deployed earlier:
+
+```
+curl http://$DOMAIN_NAME
+```
+
+Example output:
+
+```console
+Hello, world!
+Version: 1.0.0
+Hostname: web-79d88c97d6-t8hj2
+```
+
+At this point we have a Google load balancer which is forwarding HTTP traffic to the hello-world web server running in a Pod in our cluster.
+
+> ⏲ It may take 4-5 minutes for the load balancer components to be created and
+> configured and for Internet clients to be routed to your web server.
+> Refer to the [Troubleshooting](#troubleshooting) section if it takes longer.
+>
+> 🔰 Read about how to [Use a static IP addresses for HTTP(S) load balancers via Ingress annotation](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress-xlb#static_ip_addresses_for_https_load_balancers).
+>
+> 🔰 Read a [Summary of external Ingress annotations for GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/load-balance-ingress#summary_of_external_ingress_annotations).
+>
+> 🔰 Read about [Troubleshooting Ingress with External HTTP(S) Load Balancing on GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/load-balance-ingress#testing_the).
+>
+> ℹ️ There are two Ingress classes available for GKE Ingress. The `gce` class deploys an external load balancer and the `gce-internal` class deploys an internal load balancer. Ingress resources without a class specified default to `gce`.
+>
+> ⚠️ Contrary to the Kubernetes Ingress documentation, you MUST use the `kubernetes.io/ingress.class` annotation rather than the `Ingress.Spec.IngressClassName` field.
+> See [ingress-gce #1301](https://github.com/kubernetes/ingress-gce/issues/1301#issuecomment-1133356812) and [ingress-gce #1337](https://github.com/kubernetes/ingress-gce/pull/1337).
+
+
+## 6. Install cert-manager
+
+So finally we are ready to start creating an SSL certificate for our website.
+The first thing you need to do is install cert-manager, and we'll install it the easy using `kubectl` as follows:
+
+```
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.2/cert-manager.yaml
+```
+
+This will create three Deployments, and a bunch of Services and Pods in a new namespace called `cert-manager`.
+It also installs various cluster scoped supporting resources such as RBAC roles and Custom Resource Definitions.
+
+You can view some of the resources that have been installed as follows:
+
+```bash
+kubectl -n cert-manager get all
+```
+
+And you can explore the Custom Resource Definitions (cert-manager's API) using `kubectl explain`, as follows:
+
+```bash
+kubectl explain Certificate
+kubectl explain CertificateRequest
+kubectl explain Issuer
+```
+
+> 🔰 Read about [other ways to install cert-manager](../../installation).
+>
+> 🔰 Read more about [Certificates and Issuers](../../concepts).
+
+## 7. Create an Issuer for Let's Encrypt Staging
+
+An Issuer is a custom resource which tells cert-manager how to sign a Certificate.
+In this case the Issuer will be configured to connect to the Let's Encrypt staging server,
+which allows us to test everything without using up our Let's Encrypt certificate quota for the domain name.
+
+> ℹ️ Let's Encrypt uses the Automatic Certificate Management Environment (ACME) protocol
+> which is why the configuration below is under a key called `acme`.
+
+Save the following content to a file called `issuer-lets-encrypt-staging.yaml`, change the `email` field to use your email address and apply it:
+
+```yaml
+# issuer-lets-encrypt-staging.yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ email: # ❗ Replace this with your email address
+ privateKeySecretRef:
+ name: letsencrypt-staging
+ solvers:
+ - http01:
+ ingress:
+ name: web-ingress
+```
+
+```bash
+kubectl apply -f issuer-lets-encrypt-staging.yaml
+```
+
+> ℹ️ The email address is only used by Let's Encrypt to remind you to renew the certificate after 30 days before expiry. You will only receive this email if something goes wrong when renewing the certificate with cert-manager.
+
+You can check the status of the Issuer:
+
+```bash
+kubectl describe issuers.cert-manager.io letsencrypt-staging
+```
+
+Example output
+
+```console
+Status:
+ Acme:
+ Last Registered Email: firstname.lastname@example.com
+ Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/60706744
+ Conditions:
+ Last Transition Time: 2022-07-13T16:13:25Z
+ Message: The ACME account was registered with the ACME server
+ Observed Generation: 1
+ Reason: ACMEAccountRegistered
+ Status: True
+ Type: Ready
+```
+
+> ℹ️ The Let's Encrypt production issuer has [very strict rate limits](https://letsencrypt.org/docs/rate-limits/).
+> When you're experimenting and learning, it can be very easy to hit those limits. Because of that risk,
+> we'll start with the Let's Encrypt staging issuer, and once we're happy that it's working
+> we'll switch to the production issuer.
+>
+> ⚠️ In the next step you will see a warning about untrusted certificates because
+> we start with the staging issuer, but that's totally expected.
+>
+> 🔰 Read more about [configuring the ACME Issuer](../../configuration/acme).
+
+## 8. Re-configure the Ingress for SSL
+
+Earlier we created an Ingress and saw that we could connect to our web server using HTTP.
+Now we will reconfigure that Ingress for HTTPS.
+
+First a quick hack, to work around a problem with the Google Cloud ingress controller.
+Create an empty Secret for your SSL certificate **before reconfiguring the Ingress** and apply it:
+
+```yaml
+# secret.yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: web-ssl
+type: kubernetes.io/tls
+stringData:
+ tls.key: ""
+ tls.crt: ""
+```
+
+```bash
+kubectl apply -f secret.yaml
+```
+
+> ℹ️ This is a work around for a chicken-and-egg problem, where the ingress-gce
+> controller won't update its forwarding rules unless it can first find the
+> Secret that will eventually contain the SSL certificate. But Let's Encrypt
+> won't sign the SSL certificate until it can get the special
+> `.../.well-known/acme-challenge/...` URL which cert-manager adds to the
+> Ingress and which must then be translated into Google Cloud forwarding rules,
+> by the ingress-gce controller.
+>
+> 🔰 Read more about [Kubernetes Secrets and how to use them](https://kubernetes.io/docs/concepts/configuration/secret/).
+
+Now make the following changes to the Ingress and apply them:
+
+```diff
+--- a/ingress.yaml
++++ b/ingress.yaml
+@@ -7,7 +7,12 @@ metadata:
+ kubernetes.io/ingress.class: gce
+ kubernetes.io/ingress.allow-http: "true"
+ kubernetes.io/ingress.global-static-ip-name: web-ip
++ cert-manager.io/issuer: letsencrypt-staging
+ spec:
++ tls:
++ - secretName: web-ssl
++ hosts:
++ - $DOMAIN_NAME
+ defaultBackend:
+ service:
+ name: web
+```
+
+```
+kubectl apply -f ingress.yaml
+```
+
+This triggers a complex set of operations which may take many minutes to eventually complete.
+Some of these steps take 2-3 minutes and some will initially fail.
+They should all eventually succeed because cert-manager and ingress-gce (the Google Cloud ingress controller) will periodically re-reconcile.
+
+Eventually, When all the pieces are in place, you should be able to
+use curl to check the HTTPS connection to your website:
+
+```bash
+curl -v --insecure https://$DOMAIN_NAME
+```
+
+You should see that the HTTPS connection is established but that the SSL certificate is not trusted;
+that's why you use the `--insecure` flag at this stage
+
+Example output:
+```console
+* Server certificate:
+* subject: CN=www.example.com
+* start date: Jul 14 08:52:29 2022 GMT
+* expire date: Oct 12 08:52:28 2022 GMT
+* issuer: C=US; O=(STAGING) Let's Encrypt; CN=(STAGING) Artificial Apricot R3
+* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
+```
+
+> ⏲ You will have to wait 5-10 minutes for the SSL certificate to be signed and then loaded by the Google Cloud load balancer.
+> Refer to the [Troubleshooting](#troubleshooting) section if it takes longer.
+>
+> ℹ️ Adding the annotation `cert-manager.io/issuer: letsencrypt-staging` marks the Ingress for the attention of the cert-manager `ingress-shim`
+> and causes it to create a new Certificate with a reference to the Issuer that we created earlier.
+>
+> 🔰 Read [Securing Ingress Resources](../../usage/ingress.md) to learn more.
+>
+> 🔰 Read about how to [Specify certificates for your Ingress in GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-multi-ssl#specifying_certificates_for_your_ingress).
+
+## 9. Create a production ready SSL certificate
+
+Now that everything is working with the Let's Encrypt staging server, we can switch to the production server and get a trusted SSL certificate.
+
+Create a Let's Encrypt production Issuer and apply it:
+
+```yaml
+# issuer-lets-encrypt-production.yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-production
+spec:
+ acme:
+ server: https://acme-v02.api.letsencrypt.org/directory
+ email: # ❗ Replace this with your email address
+ privateKeySecretRef:
+ name: letsencrypt-production
+ solvers:
+ - http01:
+ ingress:
+ name: web-ingress
+```
+
+```bash
+kubectl apply -f issuer-lets-encrypt-production.yaml
+```
+
+Then update the Ingress annotation to use the production Issuer:
+
+```bash
+kubectl annotate ingress web-ingress cert-manager.io/issuer=letsencrypt-production --overwrite
+```
+
+This will trigger cert-manager to get a new SSL certificate signed by the Let's Encrypt production CA and store it to the `web-ssl` Secret.
+Within about 10 minutes, this new certificate will be synced to the Google Cloud load balancer and you will be able to connect to the website using secure HTTPS:
+
+```bash
+curl -v https://$DOMAIN_NAME
+```
+
+Example output:
+```console
+...
+* Server certificate:
+* subject: CN=www.example.com
+* start date: Jul 14 09:44:29 2022 GMT
+* expire date: Oct 12 09:44:28 2022 GMT
+* subjectAltName: host "www.example.com" matched cert's "www.example.com"
+* issuer: C=US; O=Let's Encrypt; CN=R3
+* SSL certificate verify ok.
+...
+Hello, world!
+Version: 1.0.0
+Hostname: web-79d88c97d6-t8hj2
+```
+
+It should also be possible to visit `https://$DOMAIN_NAME` in your web browser, without any errors or warnings.
+
+That concludes the tutorial.
+You now understand how cert-manager integrates with Kubernetes Ingress and cloud Ingress controllers.
+You have learned how to use cert-manager to get free Let's Encrypt SSL certificates.
+And you have seen how the certificates can be used by a cloud based load balancer to terminate SSL connections from Internet clients
+and forward HTTPS requests to a web server running in your Kubernetes cluster.
+
+> 💵 Read the [Clean up](#clean-up) section to learn how to delete all the resources that you created in this tutorial and reduce your cloud bill.
+>
+> 🔰 Read the [Troubleshooting](#troubleshooting) section if you encounter difficulties with the steps described in this tutorial.
+
+## Clean up
+
+After completing the tutorial you can clean up by deleting the cluster and the domain name and the static IP as follows:
+
+```bash
+# Delete the cluster and all the Google Cloud resources related to the Ingress that it contains
+gcloud container clusters delete $CLUSTER
+
+# Delete the domain name
+gcloud dns record-sets delete $DOMAIN_NAME --zone $ZONE --type A
+
+# Delete the static IP address
+gcloud compute addresses delete web-ip --global
+```
+
+## Troubleshooting
+
+When you create or update the Ingress object in this tutorial it triggers a complex set of operations which may take many minutes to eventually complete.
+Some of these steps take 2-3 minutes and some will initially fail but then subsequently succeed when either cert-manager or the Google ingress controller re-reconciles.
+In short, you should allow 5-10 minutes after you create or change the Ingress and you should expect to see some errors and warnings when you run `kubectl describe ingress web-ingress`.
+
+Here's a brief summary of the operations performed by cert-manager and ingress-gce (the Google Cloud Ingress controller):
+
+* cert-manager connects to Let's Encrypt and sends an SSL certificate signing request.
+* Let's Encrypt responds with a "challenge", which is a unique token that cert-manager must make available at a well-known location on the target web site. This proves that you are an administrator of that web site and domain name.
+* cert-manager deploys a Pod containing a temporary web server that serves the Let's Encrypt challenge token.
+* cert-manager reconfigures the Ingress, adding a `rule` to route requests for from Let's Encrypt to that temporary web server.
+* Google Cloud ingress controller reconfigures the external HTTP load balancer with that new rule.
+* Let's Encrypt now connects and receives the expected challenge token and the signs the SSL certificate and returns it to cert-manager.
+* cert-manager stores the signed SSL certificate in the Kubernetes Secret called `web-ssl`.
+* Google Cloud ingress controller uploads the signed certificate and associated private key to a Google Cloud certificate.
+* Google Cloud ingress controller reconfigures the external load balancer to serve the uploaded SSL certificate.
+
+### Check Ingress and associated events
+
+Use `kubectl describe` to view the Ingress configuration and all the associated Events.
+Check that the IP address is correct and that the TLS and Host entries match the domain name that you chose for your website.
+Notice that `ingress-gce` creates an Event for each of the Google Cloud components that it manages.
+And notice that it adds annotations with references to the ID of each of those components.
+cert-manager also creates Events when it reconciles the Ingress object, including details of the Certificate object that it creates for the Ingress.
+
+```console
+$ kubectl describe ingress web-ingress
+Name: web-ingress
+Labels:
+Namespace: default
+Address: 34.120.159.51
+Ingress Class:
+Default backend: web:8080 (10.52.0.13:8080)
+TLS:
+ web-ssl terminates www.example.com
+Rules:
+ Host Path Backends
+ ---- ---- --------
+ * * web:8080 (10.52.0.13:8080)
+Annotations: cert-manager.io/issuer: letsencrypt-staging
+ ingress.kubernetes.io/backends: {"k8s1-01784147-default-web-8080-1647ccd2":"HEALTHY"}
+ ingress.kubernetes.io/forwarding-rule: k8s2-fr-1lt9dzcy-default-web-ingress-yteotwe4
+ ingress.kubernetes.io/https-forwarding-rule: k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4
+ ingress.kubernetes.io/https-target-proxy: k8s2-ts-1lt9dzcy-default-web-ingress-yteotwe4
+ ingress.kubernetes.io/ssl-cert: k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-a257650b5fefd174
+ ingress.kubernetes.io/target-proxy: k8s2-tp-1lt9dzcy-default-web-ingress-yteotwe4
+ ingress.kubernetes.io/url-map: k8s2-um-1lt9dzcy-default-web-ingress-yteotwe4
+ kubernetes.io/ingress.allow-http: true
+ kubernetes.io/ingress.class: gce
+ kubernetes.io/ingress.global-static-ip-name: web-ip
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal CreateCertificate 28m cert-manager-ingress-shim Successfully created Certificate "web-ssl"
+ Normal Sync 28m loadbalancer-controller UrlMap "k8s2-um-1lt9dzcy-default-web-ingress-yteotwe4" updated
+ Warning Sync 24m (x16 over 28m) loadbalancer-controller Error syncing to GCP: error running load balancer syncing routine: loadbalancer 1lt9dzcy-default-web-ingress-yteotwe4 does not exist: googleapi: Error 404: The resource 'projects/your-project/global/sslCertificates/k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-e3b0c44298fc1c14' was not found, notFound
+ Normal Sync 34s (x16 over 65m) loadbalancer-controller Scheduled for sync
+```
+
+### Use cmctl to show the state of a Certificate and its associated resources
+
+> ℹ️ [Install `cmctl`](../../reference/cmctl.md) if you have not already done so.
+
+When you create a Certificate, cert-manager will create a collection of temporary resources
+which each contain information about the status of certificate signing process.
+You can read more about these in the [Certificate Lifecycle](../../concepts/certificate.md#certificate-lifecycle) section.
+Use the `cmctl status` command to view details of all these resources and all the associated Events and error messages.
+
+You may see some temporary errors, like:
+
+```console
+$ cmctl status certificate web-ssl
+Name: web-ssl
+Namespace: default
+Created at: 2022-07-14T17:30:06+01:00
+Conditions:
+ Ready: False, Reason: MissingData, Message: Issuing certificate as Secret does not contain a private key
+ Issuing: True, Reason: MissingData, Message: Issuing certificate as Secret does not contain a private key
+DNS Names:
+- www.example.com
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Issuing 4m37s cert-manager-certificates-trigger Issuing certificate as Secret does not contain a private key
+ Normal Generated 4m37s cert-manager-certificates-key-manager Stored new private key in temporary Secret resource "web-ssl-8gsqc"
+ Normal Requested 4m37s cert-manager-certificates-request-manager Created new CertificateRequest resource "web-ssl-dblrj"
+Issuer:
+ Name: letsencrypt-staging
+ Kind: Issuer
+ Conditions:
+ Ready: True, Reason: ACMEAccountRegistered, Message: The ACME account was registered with the ACME server
+ Events:
+error: 'tls.crt' of Secret "web-ssl" is not set
+Not Before:
+Not After:
+Renewal Time:
+CertificateRequest:
+ Name: web-ssl-dblrj
+ Namespace: default
+ Conditions:
+ Approved: True, Reason: cert-manager.io, Message: Certificate request has been approved by cert-manager.io
+ Ready: False, Reason: Pending, Message: Waiting on certificate issuance from order default/web-ssl-dblrj-327645514: "pending"
+ Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal cert-manager.io 4m37s cert-manager-certificaterequests-approver Certificate request has been approved by cert-manager.io
+ Normal OrderCreated 4m37s cert-manager-certificaterequests-issuer-acme Created Order resource default/web-ssl-dblrj-327645514
+ Normal OrderPending 4m37s cert-manager-certificaterequests-issuer-acme Waiting on certificate issuance from order default/web-ssl-dblrj-327645514: ""
+Order:
+ Name: web-ssl-dblrj-327645514
+ State: pending, Reason:
+ Authorizations:
+ URL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3008789144, Identifier: www.example.com, Initial State: pending, Wildcard: false
+Challenges:
+- Name: web-ssl-dblrj-327645514-2671694319, Type: HTTP-01, Token: TKspp86xMjQzTvMVXWkezEA2sE2GSWjnld5Lt4X13ro, Key: TKspp86xMjQzTvMVXWkezEA2sE2GSWjnld5Lt4X13ro.f4bppCOm-jXasFGMKjpBE5aQlhiQBeTPIs0Lx822xao, State: pending, Reason: Waiting for HTTP-01 challenge propagation: did not get expected response when querying endpoint, expected "TKspp86xMjQzTvMVXWkezEA2sE2GSWjnld5Lt4X13ro.f4bppCOm-jXasFGMKjpBE5aQlhiQBeTPIs0Lx822xao" but got: Hello, world!
+Version: 1... (truncated), Processing: true, Presented: true
+```
+
+This is because cert-manager is performing a preflight check to see if the temporary challenge web server is reachable at the expected URL.
+Initially it will not be reachable, because cert-manager takes some time to deploy the temporary web server and the Ingress controller takes time to set up the new HTTP routing rules.
+Eventually you will see that the Certificate is Ready and signed:
+
+```console
+$ cmctl status certificate web-ssl
+Name: web-ssl
+Namespace: default
+Created at: 2022-07-14T17:30:06+01:00
+Conditions:
+ Ready: True, Reason: Ready, Message: Certificate is up to date and has not expired
+DNS Names:
+- www.example.com
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Issuing 31m cert-manager-certificates-trigger Issuing certificate as Secret does not contain a private key
+ Normal Generated 31m cert-manager-certificates-key-manager Stored new private key in temporary Secret resource "web-ssl-8gsqc"
+ Normal Requested 31m cert-manager-certificates-request-manager Created new CertificateRequest resource "web-ssl-dblrj"
+ Normal Issuing 26m cert-manager-certificates-issuing The certificate has been successfully issued
+Issuer:
+ Name: letsencrypt-staging
+ Kind: Issuer
+ Conditions:
+ Ready: True, Reason: ACMEAccountRegistered, Message: The ACME account was registered with the ACME server
+ Events:
+Secret:
+ Name: web-ssl
+ Issuer Country: US
+ Issuer Organisation: (STAGING) Let's Encrypt
+ Issuer Common Name: (STAGING) Artificial Apricot R3
+ Key Usage: Digital Signature, Key Encipherment
+ Extended Key Usages: Server Authentication, Client Authentication
+ Public Key Algorithm: RSA
+ Signature Algorithm: SHA256-RSA
+ Subject Key ID: a51e3621f5c1138947810f27dce425b33c88cb16
+ Authority Key ID: de727a48df31c3a650df9f8523df57374b5d2e65
+ Serial Number: fa8bb0b603ca2cdbfdfb2872d05ee52cda10
+ Events:
+Not Before: 2022-07-14T16:34:52+01:00
+Not After: 2022-10-12T16:34:51+01:00
+Renewal Time: 2022-09-12T16:34:51+01:00
+```
+
+### Check that the SSL certificate has been copied to Google Cloud
+
+After cert-manager receives the signed Certificate it stores in the `web-ssl` Secret,
+and this in turn triggers the Google Cloud ingress controller to copy that SSL certificate to Google Cloud.
+You can see the certificate using the `gcloud` command, as follows:
+
+```console
+$ gcloud compute ssl-certificates list
+NAME TYPE CREATION_TIMESTAMP EXPIRE_TIME MANAGED_STATUS
+k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-a257650b5fefd174 SELF_MANAGED 2022-07-14T09:37:06.920-07:00 2022-10-12T08:34:51.000-07:00
+```
+
+And you can view its contents and check its attributes as follows:
+
+```console
+$ gcloud compute ssl-certificates describe k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-a257650b5fefd174 --format='value(certificate)' \
+ | openssl x509 -in - -noout -text
+...
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 04:9f:47:f1:cb:25:37:9b:86:a3:ef:bf:2e:77:3b:45:fc:1a
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = Let's Encrypt, CN = R3
+ Validity
+ Not Before: Jul 14 17:11:15 2022 GMT
+ Not After : Oct 12 17:11:14 2022 GMT
+ Subject: CN = www.example.com
+```
+
+### Check the Google Cloud forwarding-rules
+
+After you add the TLS stanza to the Ingress object, you should eventually see a forwarding-rule for the SSL connection:
+
+```console
+$ gcloud compute forwarding-rules describe k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4 --global
+IPAddress: 34.120.159.51
+IPProtocol: TCP
+creationTimestamp: '2022-07-14T09:37:12.362-07:00'
+description: '{"kubernetes.io/ingress-name": "default/web-ingress"}'
+fingerprint: oBTg7dRaIqI=
+id: '2303318464959215831'
+kind: compute#forwardingRule
+labelFingerprint: 42WmSpB8rSM=
+loadBalancingScheme: EXTERNAL
+name: k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4
+networkTier: PREMIUM
+portRange: 443-443
+selfLink: https://www.googleapis.com/compute/v1/projects/your-project/global/forwardingRules/k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4
+target: https://www.googleapis.com/compute/v1/projects/your-project/global/targetHttpsProxies/k8s2-ts-1lt9dzcy-default-web-ingress-yteotwe4
+```
diff --git a/content/v1.12-docs/tutorials/istio-csr/example/example-cluster-issuer.yaml b/content/v1.12-docs/tutorials/istio-csr/example/example-cluster-issuer.yaml
new file mode 100644
index 0000000000..cb387c29d7
--- /dev/null
+++ b/content/v1.12-docs/tutorials/istio-csr/example/example-cluster-issuer.yaml
@@ -0,0 +1,46 @@
+# NB: We generally recommend using Issuers rather than ClusterIssuers with istio-csr.
+# Issuers are easier to scope, and therefore easier to reason about in terms of security.
+
+# SelfSigned issuers are useful for creating root certificates
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: selfsigned
+spec:
+ selfSigned: {}
+---
+# Request a self-signed certificate from our ClusterIssuer; this will function as our
+# issuing root certificate when we pass it into a CA ClusterIssuer.
+
+# It's generally fine to issue root certificates like this one with long lifespans;
+# the certificates which istio-csr issues will be much shorter lived.
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: istio-ca
+ namespace: cert-manager
+spec:
+ isCA: true
+ duration: 87600h # 10 years
+ secretName: istio-ca
+ commonName: istio-ca
+ privateKey:
+ algorithm: ECDSA
+ size: 256
+ subject:
+ organizations:
+ - cluster.local
+ - cert-manager
+ issuerRef:
+ name: selfsigned
+ kind: ClusterIssuer
+ group: cert-manager.io
+---
+# Create a CA issuer using our root. This will be the ClusterIssuer which istio-csr will use.
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: istio-ca
+spec:
+ ca:
+ secretName: istio-ca
diff --git a/content/v1.12-docs/tutorials/istio-csr/example/example-issuer.yaml b/content/v1.12-docs/tutorials/istio-csr/example/example-issuer.yaml
new file mode 100644
index 0000000000..4dd383dbcb
--- /dev/null
+++ b/content/v1.12-docs/tutorials/istio-csr/example/example-issuer.yaml
@@ -0,0 +1,45 @@
+# SelfSigned issuers are useful for creating root certificates
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: selfsigned
+ namespace: istio-system
+spec:
+ selfSigned: {}
+---
+# Request a self-signed certificate from our Issuer; this will function as our
+# issuing root certificate when we pass it into a CA Issuer.
+
+# It's generally fine to issue root certificates like this one with long lifespans;
+# the certificates which istio-csr issues will be much shorter lived.
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: istio-ca
+ namespace: istio-system
+spec:
+ isCA: true
+ duration: 87600h # 10 years
+ secretName: istio-ca
+ commonName: istio-ca
+ privateKey:
+ algorithm: ECDSA
+ size: 256
+ subject:
+ organizations:
+ - cluster.local
+ - cert-manager
+ issuerRef:
+ name: selfsigned
+ kind: Issuer
+ group: cert-manager.io
+---
+# Create a CA issuer using our root. This will be the Issuer which istio-csr will use.
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: istio-ca
+ namespace: istio-system
+spec:
+ ca:
+ secretName: istio-ca
diff --git a/content/v1.12-docs/tutorials/istio-csr/example/istio-config-getting-started.yaml b/content/v1.12-docs/tutorials/istio-csr/example/istio-config-getting-started.yaml
new file mode 100644
index 0000000000..b0b6e1ca4c
--- /dev/null
+++ b/content/v1.12-docs/tutorials/istio-csr/example/istio-config-getting-started.yaml
@@ -0,0 +1,57 @@
+apiVersion: install.istio.io/v1alpha1
+kind: IstioOperator
+metadata:
+ namespace: istio-system
+spec:
+ profile: "demo"
+ hub: gcr.io/istio-release
+ meshConfig:
+ # Change the following line to configure the trust domain of the Istio cluster.
+ trustDomain: cluster.local
+ values:
+ global:
+ # Change certificate provider to cert-manager istio agent for istio agent
+ caAddress: cert-manager-istio-csr.cert-manager.svc:443
+ components:
+ pilot:
+ k8s:
+ env:
+ # Disable istiod CA Sever functionality
+ - name: ENABLE_CA_SERVER
+ value: "false"
+ overlays:
+ - apiVersion: apps/v1
+ kind: Deployment
+ name: istiod
+ patches:
+
+ # Mount istiod serving and webhook certificate from Secret mount
+ - path: spec.template.spec.containers.[name:discovery].args[-1]
+ value: "--tlsCertFile=/etc/cert-manager/tls/tls.crt"
+ - path: spec.template.spec.containers.[name:discovery].args[-1]
+ value: "--tlsKeyFile=/etc/cert-manager/tls/tls.key"
+ - path: spec.template.spec.containers.[name:discovery].args[-1]
+ value: "--caCertFile=/etc/cert-manager/ca/root-cert.pem"
+
+ - path: spec.template.spec.containers.[name:discovery].volumeMounts[-1]
+ value:
+ name: cert-manager
+ mountPath: "/etc/cert-manager/tls"
+ readOnly: true
+ - path: spec.template.spec.containers.[name:discovery].volumeMounts[-1]
+ value:
+ name: ca-root-cert
+ mountPath: "/etc/cert-manager/ca"
+ readOnly: true
+
+ - path: spec.template.spec.volumes[-1]
+ value:
+ name: cert-manager
+ secret:
+ secretName: istiod-tls
+ - path: spec.template.spec.volumes[-1]
+ value:
+ name: ca-root-cert
+ configMap:
+ defaultMode: 420
+ name: istio-ca-root-cert
diff --git a/content/v1.12-docs/tutorials/istio-csr/istio-csr.md b/content/v1.12-docs/tutorials/istio-csr/istio-csr.md
new file mode 100644
index 0000000000..32c5c1ae3e
--- /dev/null
+++ b/content/v1.12-docs/tutorials/istio-csr/istio-csr.md
@@ -0,0 +1,276 @@
+---
+title: Securing the istio Service Mesh using cert-manager
+description: 'cert-manager tutorials: Securing the istio Service Mesh using cert-manager'
+---
+
+This guide will run through installing and using istio-csr from scratch. We'll use [kind](https://kind.sigs.k8s.io/) to create a new cluster locally in Docker, but this guide should work on any cluster as long as the relevant Istio [Platform Setup](https://istio.io/latest/docs/setup/platform-setup/) has been performed.
+
+Note that if you're following the Platform Setup guide for OpenShift, do not run the `istioctl install` command listed in that guide; we'll run our own command later.
+
+## Initial Setup
+
+You'll need the following tools installed on your machine:
+
+- [istioctl](https://github.com/istio/istio/releases/latest)
+- [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) and [docker](https://docs.docker.com/get-docker/) (if you're using kind)
+- [helm](https://helm.sh/docs/intro/install/)
+- [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl)
+- [jq](https://stedolan.github.io/jq/download/)
+
+In addition, Istio must not already be installed in your cluster. Installing istio-csr _after_ Istio is not supported.
+
+## Creating the Cluster and Installing cert-manager
+
+Kind will automatically set up kubectl to point to the newly created cluster.
+
+We install cert-manager [using helm](https://cert-manager.io/docs/installation/helm/) here, but if you've got a preferred method you can install in any way.
+
+```console
+kind create cluster --image=docker.io/kindest/node:v1.22.4
+
+# Helm setup
+helm repo add jetstack https://charts.jetstack.io
+helm repo update
+
+# install cert-manager CRDs
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.crds.yaml
+
+# install cert-manager; this might take a little time
+helm install cert-manager jetstack/cert-manager \
+ --namespace cert-manager \
+ --create-namespace \
+ --version v1.8.0
+
+# We need this namespace to exist since our cert will be placed there
+kubectl create namespace istio-system
+```
+
+## Create a cert-manager Issuer and Issuing Certificate
+
+An Issuer tells cert-manager how to issue certificates; we'll create a self-signed root CA in our cluster because it's really simple to configure.
+
+The approach of using a locally generated root certificate would work in a production deployment too, but there are also several [other issuers](https://cert-manager.io/docs/configuration/) in cert-manager which could be used. Note that the ACME issuer **will not work**, since it can't add the required fields to issued certificates.
+
+There are also some comments on the [example-issuer](https://github.com/cert-manager/website/blob/master/content/docs/tutorials/istio-csr/example/example-issuer.yaml) providing a little more detail. Note also that this guide only uses `Issuer`s and not `ClusterIssuer`s - using a `ClusterIssuer` isn't a drop-in replacement, and in any case we recommend that production deployments use Issuers for easier access controls and scoping.
+
+```console
+kubectl apply -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/istio-csr/example/example-issuer.yaml
+```
+
+## Export the Root CA to a Local File
+
+While it's possible to configure Istio such that it can automatically "discover" the root CA, this can be dangerous in
+some specific scenarios involving other security holes, enabling [signer hijacking attacks](https://github.com/cert-manager/istio-csr/issues/103#issuecomment-923882792).
+
+As such, we'll export our Root CA and configure Istio later using that static cert.
+
+```console
+# Export our cert from the secret it's stored in, and base64 decode to get the PEM data.
+kubectl get -n istio-system secret istio-ca -ogo-template='{{index .data "tls.crt"}}' | base64 -d > ca.pem
+
+# Out of interest, we can check out what our CA looks like
+openssl x509 -in ca.pem -noout -text
+
+# Add our CA to a secret
+kubectl create secret generic -n cert-manager istio-root-ca --from-file=ca.pem=ca.pem
+```
+
+## Installing istio-csr
+
+istio-csr is best installed via Helm, and it should be simple and quick to install. There
+are a bunch of other configuration options for the helm chart, which you can check out [here](../../projects/istio-csr.md).
+
+```console
+helm repo add jetstack https://charts.jetstack.io
+helm repo update
+
+# We set a few helm template values so we can point at our static root CA
+helm install -n cert-manager cert-manager-istio-csr jetstack/cert-manager-istio-csr \
+ --set "app.tls.rootCAFile=/var/run/secrets/istio-csr/ca.pem" \
+ --set "volumeMounts[0].name=root-ca" \
+ --set "volumeMounts[0].mountPath=/var/run/secrets/istio-csr" \
+ --set "volumes[0].name=root-ca" \
+ --set "volumes[0].secret.secretName=istio-root-ca"
+
+# Check to see that the istio-csr pod is running and ready
+kubectl get pods -n cert-manager
+NAME READY STATUS RESTARTS AGE
+cert-manager-aaaaaaaaaa-11111 1/1 Running 0 9m46s
+cert-manager-cainjector-aaaaaaaaaa-22222 1/1 Running 0 9m46s
+cert-manager-istio-csr-bbbbbbbbbb-00000 1/1 Running 0 63s
+cert-manager-webhook-aaaaaaaaa-33333 1/1 Running 0 9m46s
+```
+
+## Installing Istio
+
+If you're not running on kind, you may need to do some additional [setup tasks](https://istio.io/latest/docs/setup/platform-setup/) before installing Istio.
+
+We use the `istioctl` CLI to install Istio, configured using a custom IstioOperator manifest.
+
+The custom manifest does the following:
+
+- Disables the CA server in istiod,
+- Ensures that Istio workloads request certificates from istio-csr,
+- Ensures that the istiod certificates and keys are mounted from the Certificate created when installing istio-csr.
+
+First we download our demo manifest and then we apply it.
+
+```console
+curl -sSL https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/istio-csr/example/istio-config-getting-started.yaml > istio-install-config.yaml
+```
+
+You may wish to inspect and tweak `istio-install-config.yaml` if you know what you're doing,
+but this manifest should work for example purposes as-is.
+
+If you set a custom `app.tls.trustDomain` when installing istio-csr via helm earlier, you'll need to ensure that
+value is repeated in `istio-install-config.yaml`.
+
+This final command will install Istio; the exact command you need might vary on different platforms,
+and will certainly vary on OpenShift.
+
+```console
+# This takes a little time to complete
+istioctl install -f istio-install-config.yaml
+
+# If you're on OpenShift, you need a different profile:
+# istioctl install --set profile=openshift -f istio-install-config.yaml
+```
+
+You will be prompted for input to confirm your choice of Istio profile:
+
+```console
+This will install the Istio 1.14.1 demo profile with ["Istio core" "Istiod" "Ingress gateways" "Egress gateways"] components into the cluster. Proceed? (y/N)
+```
+
+Confirm your selection by entering `y` into the console to proceed with installation.
+
+## Validating Install
+
+The following steps are option but can be followed to validate everything is hooked correctly:
+
+1. Deploy a sample application & watch for `certificaterequests.cert-manager.io` resources
+2. Verify `cert-manager` logs for new `certificaterequests` and responses
+3. Verify the CA Endpoint being used in a `istio-proxy` sidecar container
+4. Using `istioctl` to fetch the certificate info for the `istio-proxy` container
+
+To see this all in action, lets deploy a very simple sample application from the
+[Istio samples](https://github.com/istio/istio/tree/master/samples/httpbin).
+
+First set some environment variables whose values could be changed if needed:
+
+```shell
+# Set namespace for sample application
+export NAMESPACE=default
+# Set env var for the value of the app label in manifests
+export APP=httpbin
+# Grab the installed version of istio
+export ISTIO_VERSION=$(istioctl version -o json | jq -r '.meshVersion[0].Info.version')
+```
+
+We use the `default` namespace for simplicity, so let's label the namespace for Istio injection:
+
+```shell
+kubectl label namespace $NAMESPACE istio-injection=enabled --overwrite
+```
+
+In a separate terminal you should now follow the logs for `cert-manager`:
+
+```shell
+kubectl logs -n cert-manager $(kubectl get pods -n cert-manager -o jsonpath='{.items..metadata.name}' --selector app=cert-manager) --since 2m -f
+```
+
+In another separate terminal, lets watch the `istio-system` namespace for `certificaterequests`:
+
+```shell
+kubectl get certificaterequests.cert-manager.io -n istio-system -w
+```
+
+Now deploy the sample application `httpbin` in the labeled namespace. Note the use of a
+variable to match the manifest version to your installed Istio version:
+
+```shell
+kubectl apply -n $NAMESPACE -f https://raw.githubusercontent.com/istio/istio/$ISTIO_VERSION/samples/httpbin/httpbin.yaml
+```
+
+You should see something similar to the output here for `certificaterequests`:
+
+```
+NAME APPROVED DENIED READY ISSUER REQUESTOR AGE
+istio-ca-74bnl True True selfsigned system:serviceaccount:cert-manager:cert-manager 2d2h
+istiod-w9zh6 True True istio-ca system:serviceaccount:cert-manager:cert-manager 27m
+istio-csr-8ddcs istio-ca system:serviceaccount:cert-manager:cert-manager-istio-csr 0s
+istio-csr-8ddcs True istio-ca system:serviceaccount:cert-manager:cert-manager-istio-csr 0s
+istio-csr-8ddcs True True istio-ca system:serviceaccount:cert-manager:cert-manager-istio-csr 0s
+istio-csr-8ddcs True True istio-ca system:serviceaccount:cert-manager:cert-manager-istio-csr 0s
+```
+
+The key request being `istio-csr-8ddcs` in our example output. You should then check your
+`cert-manager` log output for two log lines with this request being "Approved" and "Ready":
+
+```
+I0113 16:51:59.186482 1 conditions.go:261] Setting lastTransitionTime for CertificateRequest "istio-csr-8ddcs" condition "Approved" to 2022-01-13 16:51:59.186455713 +0000 UTC m=+3507.098466775
+I0113 16:51:59.258876 1 conditions.go:261] Setting lastTransitionTime for CertificateRequest "istio-csr-8ddcs" condition "Ready" to 2022-01-13 16:51:59.258837897 +0000 UTC m=+3507.170859959
+```
+
+You should now see the application is running with both the application container and the sidecar:
+
+```shell
+~ kubectl get pods -n $NAMESPACE
+NAME READY STATUS RESTARTS AGE
+httpbin-74fb669cc6-559cg 2/2 Running 0 4m
+```
+
+To validate that the `istio-proxy` sidecar container has requested the certificate from the correct
+service, check the container logs:
+
+```shell
+kubectl logs $(kubectl get pod -n $NAMESPACE -o jsonpath="{.items...metadata.name}" --selector app=$APP) -c istio-proxy
+```
+
+You should see some early logs similar to this example:
+
+Istio v1.12 and earlier versions:
+
+```
+2022-01-13T16:51:58.495493Z info CA Endpoint cert-manager-istio-csr.cert-manager.svc:443, provider Citadel
+2022-01-13T16:51:58.495817Z info Using CA cert-manager-istio-csr.cert-manager.svc:443 cert with certs: var/run/secrets/istio/root-cert.pem
+2022-01-13T16:51:58.495941Z info citadelclient Citadel client using custom root cert: cert-manager-istio-csr.cert-manager.svc:443
+```
+
+Istio v1.13+
+
+```
+2022-01-13T16:51:58.495493Z info CA Endpoint cert-manager-istio-csr.cert-manager.svc:443, provider Citadel
+2022-01-13T16:51:58.495817Z info Using CA cert-manager-istio-csr.cert-manager.svc:443 cert with certs: var/run/secrets/istio/root-cert.pem
+2022-01-13T16:51:58.495941Z info citadelclient Citadel client using custom root cert: var/run/secrets/istio/root-cert.pem
+```
+
+Finally we can inspect the certificate being used in memory by Envoy. This one liner should return you the certificate being used:
+
+```shell
+istioctl proxy-config secret $(kubectl get pods -n $NAMESPACE -o jsonpath='{.items..metadata.name}' --selector app=$APP) -o json | jq -r '.dynamicActiveSecrets[0].secret.tlsCertificate.certificateChain.inlineBytes' | base64 --decode | openssl x509 -text -noout
+```
+
+In particular look for the following sections:
+
+```
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: O=cert-manager, O=cluster.local, CN=istio-ca
+ Validity
+ Not Before: Jan 13 16:51:59 2022 GMT
+ Not After : Jan 13 17:51:59 2022 GMT
+...
+ X509v3 Subject Alternative Name:
+ URI:spiffe://cluster.local/ns/default/sa/httpbin
+```
+
+You should see the relevant Trust Domain inside the Issuer. In the default case, it should be:
+`cluster.local` as above. Note that the SPIFFE URI may be different if you used a different
+namespace or application.
+
+## Clean up
+
+Assuming your running inside kind, you can simply remove the cluster:
+
+```shell
+kind delete cluster
diff --git a/content/v1.12-docs/tutorials/syncing-secrets-across-namespaces.md b/content/v1.12-docs/tutorials/syncing-secrets-across-namespaces.md
new file mode 100644
index 0000000000..95e8a6a5fa
--- /dev/null
+++ b/content/v1.12-docs/tutorials/syncing-secrets-across-namespaces.md
@@ -0,0 +1,143 @@
+---
+title: Syncing Secrets Across Namespaces
+description: |
+ Learn how to synchronize Kubernetes Secret resources across namespaces
+ using extensions such as: reflector, kubed and kubernetes-replicator.
+---
+
+It may be required for multiple components across namespaces to consume the same
+`Secret` that has been created by a single `Certificate`. The recommended way to
+do this is to use extensions such as:
+ - [reflector](https://github.com/emberstack/kubernetes-reflector) with support
+ for auto secret reflection
+ - [kubed](https://github.com/appscode/kubed) with its
+ [secret syncing feature](https://appscode.com/products/kubed/v0.11.0/guides/config-syncer/intra-cluster/)
+ - [kubernetes-replicator](https://github.com/mittwald/kubernetes-replicator) secret replication
+
+## Serving a wildcard to ingress resources in different namespaces (default SSL certificate)
+
+Most ingress controllers, including [ingress-nginx](https://kubernetes.github.io/ingress-nginx/user-guide/tls/#default-ssl-certificate), [Traefik](https://docs.traefik.io/https/tls/#default-certificate), and [Kong](https://docs.konghq.com/2.0.x/configuration/#ssl_cert) support specifying a _single_ certificate to be used for ingress resources which request TLS but do not specify `tls.[].secretName`. This is often referred to as a "default SSL certificate". As long as this is correctly configured, ingress resources in any namespace will be able to use a single wildcard certificate. Wildcard certificates are not supported with HTTP01 validation and require DNS01.
+
+Sample ingress snippet:
+
+```
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+#[...]
+spec:
+ rules:
+ - host: service.example.com
+ #[...]
+ tls:
+ - hosts:
+ - service.example.com
+ #secretName omitted to use default wildcard certificate
+```
+
+
+## Syncing arbitrary secrets across namespaces using extensions
+
+In order for the target Secret to be synced, you can use the `secretTemplate` field
+for annotating the generated secret with the extension specific annotation (See [CertificateSecretTemplate]).
+
+
+### Using `reflector`
+ The example below shows syncing a certificate's secret from the `cert-manager` namespace to multiple namespaces (i.e. `dev`, `staging`, `prod`).
+ Reflector will ensure that any namespace (existing or new) matching the allowed condition (with regex support) will get a copy of the certificate's secret and will keep it up to date.
+ You can also sync other secrets (different name) using `reflector` (consult the extension's [README](https://github.com/emberstack/kubernetes-reflector/blob/main/README.md))
+
+```yaml
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: source
+ namespace: cert-manager
+spec:
+ secretName: source-tls
+ commonName: source
+ issuerRef:
+ name: source-ca
+ kind: Issuer
+ group: cert-manager.io
+ secretTemplate:
+ annotations:
+ reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
+ reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "dev,staging,prod" # Control destination namespaces
+ reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true" # Auto create reflection for matching namespaces
+ reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "dev,staging,prod" # Control auto-reflection namespaces
+```
+
+
+### Using `kubed`
+ The example below shows syncing
+a certificate belonging to the `sandbox` Certificate from the `cert-manager`
+namespace, into the `sandbox` namespace.
+
+```yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: sandbox
+ labels:
+ cert-manager-tls: sandbox # Define namespace label for kubed
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: sandbox
+ namespace: cert-manager
+spec:
+ secretName: sandbox-tls
+ commonName: sandbox
+ issuerRef:
+ name: sandbox-ca
+ kind: Issuer
+ group: cert-manager.io
+ secretTemplate:
+ annotations:
+ kubed.appscode.com/sync: "cert-manager-tls=sandbox" # Sync certificate to matching namespaces
+```
+
+
+### Using `kubernetes-replicator`
+Replicator supports both push- and pull-based replication. Push-based
+replication will "push out" the TLS secret into namespaces when new ones are
+created, or when the secret changes. Pull-based replication makes it possible
+to create an empty TLS secret in the destination namespace and select a
+"source" resource from which the data is replicated from. The following example
+shows the pull-based approach:
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: source
+ namespace: cert-manager
+spec:
+ secretName: source-tls
+ commonName: source
+ issuerRef:
+ name: source-ca
+ kind: Issuer
+ secretTemplate:
+ annotations:
+ replicator.v1.mittwald.de/replication-allowed: "true" # permit replication
+ replicator.v1.mittwald.de/replication-allowed-namespaces: "dev,test,prod-[0-9]*" # comma separated list of namespaces or regular expressions
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: tls-secret-replica
+ namespace: prod-1
+ annotations:
+ replicator.v1.mittwald.de/replicate-from: cert-manager/source-tls
+type: kubernetes.io/tls
+# Normally, we'd create an empty destination secret, but secrets of type
+# 'kubernetes.io/tls' are treated in a special way and need to have properties
+# data["tls.crt"] and data["tls.key"] to begin with, though they may be empty.
+data:
+ tls.key: ""
+ tls.crt: ""
+```
+
+[CertificateSecretTemplate]: ../reference/api-docs.md#cert-manager.io/v1.CertificateSecretTemplate
diff --git a/content/v1.12-docs/tutorials/venafi/venafi.md b/content/v1.12-docs/tutorials/venafi/venafi.md
new file mode 100644
index 0000000000..505276f626
--- /dev/null
+++ b/content/v1.12-docs/tutorials/venafi/venafi.md
@@ -0,0 +1,586 @@
+---
+title: Securing Ingresses with Venafi
+description: 'cert-manager tutorials: Securing Ingress using Venafi Issuers'
+---
+
+This guide walks you through how to secure a Kubernetes
+[`Ingress`](https://kubernetes.io/docs/concepts/services-networking/ingress/)
+resource using the Venafi Issuer type.
+
+Whilst stepping through, you will learn how to:
+
+- Create an EKS cluster using [`eksctl`](https://github.com/weaveworks/eksctl)
+- Install cert-manager into the EKS cluster
+- Deploy [`nginx-ingress`](https://github.com/kubernetes/ingress-nginx) to
+ expose applications running in the cluster
+- Configure a Venafi Cloud issuer
+- Configure cert-manager to secure your application traffic
+
+While this guide focuses on EKS as a Kubernetes provisioner and Venafi
+as a Certificate issuer, the steps here should be generally re-usable for other
+Issuer types.
+
+## Prerequisites
+
+- An AWS account
+- `kubectl` installed
+- Access to a publicly registered DNS zone
+- A Venafi Cloud account and API credentials
+
+## Create an EKS cluster
+
+If you already have a running EKS cluster you can skip this step and move onto
+deploying cert-manager.
+
+[`eksctl`](https://eksctl.io/introduction/installation/) is a tool that makes it
+easier to deploy and manage an EKS cluster.
+
+Installation instructions for various platforms can be found in the
+[`eksctl` installation
+instructions](https://eksctl.io/introduction/installation/).
+
+Once installed, you can create a basic cluster by running:
+
+```
+$ eksctl create cluster
+```
+
+This process may take up to 20 minutes to complete. Complete instructions on
+using `eksctl` can be found in the [`eksctl` usage
+section](https://eksctl.io/usage/creating-and-managing-clusters/).
+
+Once your cluster has been created, you should verify that your cluster is
+running correctly by running the following command:
+
+```
+$ kubectl get pods --all-namespaces
+NAME READY STATUS RESTARTS AGE
+aws-node-8xpkp 1/1 Running 0 115s
+aws-node-tflxs 1/1 Running 0 118s
+coredns-694d9447b-66vlp 1/1 Running 0 23s
+coredns-694d9447b-w5bg8 1/1 Running 0 23s
+kube-proxy-4dvpj 1/1 Running 0 115s
+kube-proxy-tpvht 1/1 Running 0 118s
+```
+
+You should see output similar to the above, with all pods in a Running state.
+
+## Installing cert-manager
+
+There are no special requirements to note when installing cert-manager on EKS,
+so the regular [running on
+Kubernetes](../../installation/README.md) guides
+can be used to install cert-manager.
+
+Please walk through the installation guide and return to this step once you
+have validated cert-manager is deployed correctly.
+
+## Installing `ingress-nginx`
+
+A [Kubernetes ingress
+controller](https://eksctl.io/usage/creating-and-managing-clusters/) is designed
+to be the access point for HTTP and HTTPS traffic to the software running within
+your cluster. The [`ingress-nginx`](https://github.com/kubernetes/ingress-nginx)
+controller does this by providing an HTTP proxy service supported by your cloud
+provider's load balancer (in this case, a [Network Load Balancer
+(NLB)](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html).
+
+You can get more details about `ingress-nginx` and how it works from the
+[documentation for `ingress-nginx`](https://kubernetes.github.io/ingress-nginx/).
+
+To deploy `ingress-nginx` using an ELB to expose the service, run the following:
+
+Deploy the AWS specific prerequisite manifest
+```bash
+$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.4.0/deploy/static/provider/aws/deploy.yaml
+```
+
+Deploy the 'generic' `ingress-nginx` manifest
+```bash
+$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml
+```
+
+You may have to wait up to 5 minutes for all the required components in your
+cluster and AWS account to become ready.
+
+You can run the following command to determine the address that Amazon has
+assigned to your NLB:
+
+```bash
+$ kubectl get service -n ingress-nginx
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+ingress-nginx LoadBalancer 10.100.52.175 a8c2870a5a8a311e9a9a10a2e7af57d7-6c2ec8ede48726ab.elb.eu-west-1.amazonaws.com 80:31649/TCP,443:30567/TCP 4m10s
+```
+
+The *EXTERNAL-IP* field may say `` for a while. This indicates the NLB
+is still being created. Retry the command until an *EXTERNAL-IP* has been
+provisioned.
+
+Once the *EXTERNAL-IP* is available, you should run the following command to
+verify that traffic is being correctly routed to `ingress-nginx`:
+
+```
+$ curl http://a8c2870a5a8a311e9a9a10a2e7af57d7-6c2ec8ede48726ab.elb.eu-west-1.amazonaws.com/
+
+404 Not Found
+
+
404 Not Found
+
openresty/1.15.8.1
+
+
+```
+
+Whilst the above message would normally indicate an error (the page not being
+found), in this instance it indicates that traffic is being correctly routed to
+the `ingress-nginx` service.
+
+> Note: Although the AWS Application Load Balancer (ALB) is a modern load
+> balancer offered by AWS that can can be provisioned from within EKS, at the
+> time of writing, the
+> [`alb-ingress-controller`](https://github.com/kubernetes-sigs/aws-alb-ingress-controller>)
+> is only capable of serving sites using certificates stored in AWS Certificate
+> Manager (ACM). Version 1.15 of Kubernetes should address multiple bug fixes
+> for this controller and allow for TLS termination support.
+
+## Configure your DNS records
+
+Now that our NLB has been provisioned, we should point our application's DNS
+records at the NLBs address.
+
+Go into your DNS provider's console and set a CNAME record pointing to your
+NLB.
+
+For the purposes of demonstration, we will assume in this guide you have created
+the following DNS entry:
+
+```
+example.com CNAME a8c2870a5a8a311e9a9a10a2e7af57d7-6c2ec8ede48726ab.elb.eu-west-1.amazonaws.com
+```
+
+As you progress through the rest of this tutorial, please replace `example.com`
+with your own registered domain.
+
+## Deploying a demo application
+
+For the purposes of this demo, we provide an example deployment which is a
+simple "hello world" website.
+
+First, create a new namespace that will contain your application:
+
+```bash
+$ kubectl create namespace demo
+namespace/demo created
+```
+
+Save the following YAML into a file named `demo-deployment.yaml`:
+
+```yaml
+apiVersion: v1
+kind: Service
+metadata:
+ name: hello-kubernetes
+ namespace: demo
+spec:
+ type: ClusterIP
+ ports:
+ - port: 80
+ targetPort: 8080
+ selector:
+ app: hello-kubernetes
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: hello-kubernetes
+ namespace: demo
+spec:
+ replicas: 2
+ selector:
+ matchLabels:
+ app: hello-kubernetes
+ template:
+ metadata:
+ labels:
+ app: hello-kubernetes
+ spec:
+ containers:
+ - name: hello-kubernetes
+ image: paulbouwer/hello-kubernetes:1.5
+ resources:
+ requests:
+ cpu: 100m
+ memory: 100Mi
+ ports:
+ - containerPort: 8080
+```
+
+Then run:
+
+```bash
+kubectl apply -n demo -f demo-deployment.yaml
+```
+
+Note that the Service resource we deploy is of type `ClusterIP` and not
+`LoadBalancer`, as we will expose and secure traffic for this service using
+`ingress-nginx` that we deployed earlier.
+
+You should be able to see two Pods and one Service in the `demo` namespace:
+
+```bash
+kubectl get po,svc -n demo
+NAME READY STATUS RESTARTS AGE
+hello-kubernetes-66d45d6dff-m2lnr 1/1 Running 0 7s
+hello-kubernetes-66d45d6dff-qt2kb 1/1 Running 0 7s
+
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+service/hello-kubernetes ClusterIP 10.100.164.58 80/TCP 7s
+```
+
+Note that we have not yet exposed this application to be accessible over the
+internet. We will expose the demo application to the internet in later steps.
+
+## Creating a Venafi Issuer resource
+
+cert-manager supports both Venafi TPP and Venafi Cloud.
+
+Please only follow one of the below sections according to where you want to
+retrieve your Certificates from.
+
+### Venafi TPP
+
+Assuming you already have a Venafi TPP server set up properly, you can create
+a Venafi Issuer resource that can be used to issue certificates.
+
+To do this, you need to make sure you have your TPP *username* and *password*.
+
+In order for cert-manager to be able to authenticate with your Venafi TPP
+server and set up an Issuer resource, you'll need to create a Kubernetes
+Secret containing your username and password:
+
+```bash
+$ kubectl create secret generic \
+ venafi-tpp-secret \
+ --namespace=demo \
+ --from-literal=username='YOUR_TPP_USERNAME_HERE' \
+ --from-literal=password='YOUR_TPP_PASSWORD_HERE'
+```
+
+We must then create a Venafi Issuer resource, which represents a certificate
+authority within Kubernetes.
+
+Save the following YAML into a file named `venafi-issuer.yaml`:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: venafi-issuer
+ namespace: demo
+spec:
+ venafi:
+ zone: "Default" # Set this to the Venafi policy zone you want to use
+ tpp:
+ url: https://venafi-tpp.example.com/vedsdk # Change this to the URL of your TPP instance
+ caBundle:
+ credentialsRef:
+ name: venafi-tpp-secret
+```
+
+Then run:
+
+```bash
+$ kubectl apply -n demo -f venafi-issuer.yaml
+```
+
+When you run the following command, you should see that the Status stanza of
+the output shows that the Issuer is Ready (i.e. has successfully validated
+itself with the Venafi TPP server).
+
+```bash
+$ kubectl describe issuer -n demo venafi-issuer
+
+ Status:
+ Conditions:
+ Last Transition Time: 2019-07-17T15:46:00Z
+ Message: Venafi issuer started
+ Reason: Venafi issuer started
+ Status: True
+ Type: Ready
+ Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Ready 14s cert-manager Verified issuer with Venafi server
+```
+
+### Venafi Cloud
+
+You can sign up for a Venafi Cloud account by visiting the [enrollment
+page](https://www.venafi.com/cloud).
+
+Once registered, you should fetch your API key by clicking your name in the top
+right of the control panel interface.
+
+In order for cert-manager to be able to authenticate with your Venafi Cloud
+account and set up an Issuer resource, you'll need to create a Kubernetes
+Secret containing your API key:
+
+```bash
+$ kubectl create secret generic \
+ venafi-cloud-secret \
+ --namespace=demo \
+ --from-literal=apikey=
+```
+
+We must then create a Venafi Issuer resource, which represents a certificate
+authority within Kubernetes.
+
+Save the following YAML into a file named `venafi-issuer.yaml`:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: venafi-issuer
+ namespace: demo
+spec:
+ venafi:
+ zone: "Default" # Set this to the Venafi policy zone you want to use
+ cloud:
+ apiTokenSecretRef:
+ name: venafi-cloud-secret
+ key: apikey
+```
+
+Then run:
+
+```bash
+$ kubectl apply -n demo -f venafi-issuer.yaml
+```
+
+When you run the following command, you should see that the Status stanza of
+the output shows that the Issuer is Ready (i.e. has successfully validated
+itself with the Venafi Cloud service).
+
+```bash
+$ kubectl describe issuer -n demo venafi-issuer
+...
+Status:
+ Conditions:
+ Last Transition Time: 2019-07-17T15:46:00Z
+ Message: Venafi issuer started
+ Reason: Venafi issuer started
+ Status: True
+ Type: Ready
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Ready 14s cert-manager Verified issuer with Venafi server
+```
+
+## Request a Certificate
+
+Now that the Issuer is configured and we have confirmed it has been set up
+correctly, we can begin requesting certificates which can be used by Kubernetes
+applications.
+
+Full information on how to specify and request Certificate resources can be
+found in the [Issuing certificates](../../usage/certificate.md) guide.
+
+For now, we will create a basic X.509 Certificate that is valid for our domain,
+`example.com`:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com-tls
+ namespace: demo
+spec:
+ secretName: example-com-tls
+ dnsNames:
+ - example.com
+ commonName: example.com
+ issuerRef:
+ name: venafi-issuer
+```
+
+Save this YAML into a file named `example-com-tls.yaml` and run:
+
+```bash
+$ kubectl apply -n demo -f example-com-tls.yaml
+```
+
+As long as you've ensured that the zone of your Venafi Cloud account (in our
+example, we use the "Default" zone) has been configured with a CA or contains a
+custom certificate, cert-manager can now take steps to populate the
+`example-com-tls` Secret with a certificate. It does this by identifying itself
+with Venafi Cloud using the API key, then requesting a certificate to match the
+specifications of the Certificate resource that we've created.
+
+You can run `kubectl describe` to check the progress of your Certificate:
+
+```bash
+$ kubectl describe certificate -n demo example-com-tls
+...
+Status:
+ Conditions:
+ Last Transition Time: 2019-07-17T17:43:01Z
+ Message: Certificate is up to date and has not expired
+ Reason: Ready
+ Status: True
+ Type: Ready
+ Not After: 2019-10-15T12:00:00Z
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Issuing 33s cert-manager Requesting new certificate...
+ Normal GenerateKey 33s cert-manager Generated new private key
+ Normal Validate 33s cert-manager Validated certificate request against Venafi zone policy
+ Normal Requesting 33s cert-manager Requesting certificate from Venafi server...
+ Normal Retrieve 15s cert-manager Retrieved certificate from Venafi server
+ Normal CertIssued 15s cert-manager Certificate issued successfully
+```
+
+Once the Certificate has been issued, you should see events similar to above.
+
+You should then be able to see the certificate has been successfully stored in
+the Secret resource:
+
+```bash
+$ kubectl get secret -n demo example-com-tls
+NAME TYPE DATA AGE
+example-com-tls kubernetes.io/tls 3 2m47s
+
+$ kubectl get secret example-com-tls -o 'go-template={{index .data "tls.crt"}}' | \
+ base64 --decode | \
+ openssl x509 -noout -text
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0d:ce:bf:89:04:d4:41:83:f4:4c:32:66:64:fb:60:14
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=US, O=DigiCert Inc, CN=DigiCert Test SHA2 Intermediate CA-1
+ Validity
+ Not Before: Jul 17 00:00:00 2019 GMT
+ Not After : Oct 15 12:00:00 2019 GMT
+ Subject: C=US, ST=California, L=Palo Alto, O=Venafi Cloud, OU=SerialNumber, CN=example.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ad:2e:66:02:20:c9:b1:6a:00:63:70:4e:22:3c:
+ 45:63:6e:e7:fd:4c:94:7d:75:50:22:a2:01:72:99:
+ 9c:23:04:90:51:85:4d:47:32:e4:8b:ee:b1:ea:09:
+ 1a:de:97:5d:31:05:a2:73:73:4f:06:a3:b2:59:ee:
+ bc:30:f7:26:85:3d:b3:56:e4:c2:97:34:b6:ac:6d:
+ 65:7e:a2:4e:b4:ce:f2:0a:0a:4c:d7:32:d7:5a:18:
+ e8:69:c6:34:28:26:36:ef:c5:bc:ae:ba:ca:d2:46:
+ 3f:d4:61:39:66:8f:19:cc:d6:d6:10:77:af:51:93:
+ 1b:4d:f8:d1:10:19:ab:ac:b3:7b:0b:98:58:29:e6:
+ a9:ac:9f:7a:dc:63:0d:51:f5:bd:9f:f3:03:2e:b3:
+ 2d:2f:00:87:f4:e1:cd:5a:32:c6:d8:fb:49:c4:e7:
+ da:3f:0f:8f:bb:66:94:28:5d:99:fe:7c:f0:17:1b:
+ fd:3e:ed:dd:36:bf:8e:62:60:0c:85:7f:76:74:4b:
+ 37:d9:c2:e8:74:49:04:bf:f1:83:81:cc:4f:9b:f3:
+ 40:97:d4:dc:b6:d3:2d:dc:73:18:93:48:a5:8f:6c:
+ 57:7f:ec:62:c0:bc:c2:b0:e9:0a:51:2d:c4:b6:87:
+ 68:96:87:f8:9a:86:3c:6a:f1:01:ca:57:c4:07:e7:
+ b0:51
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:D6:4D:F9:39:60:6C:73:C3:22:F5:AD:30:0C:2F:A0:D5:CA:75:4A:2A
+
+ X509v3 Subject Key Identifier:
+ A3:B3:47:2C:41:5E:9C:B2:27:97:57:14:A4:2E:BA:8C:93:E7:01:65
+ X509v3 Subject Alternative Name:
+ DNS:example.com
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl3.digicert.com/DigiCertTestSHA2IntermediateCA1.crl
+
+ Full Name:
+ URI:http://crl4.digicert.com/DigiCertTestSHA2IntermediateCA1.crl
+
+ X509v3 Certificate Policies:
+ Policy: 2.16.840.1.114412.1.1
+ CPS: https://www.digicert.com/CPS
+
+ Authority Information Access:
+ OCSP - URI:http://ocsp.digicert.com
+ CA Issuers - URI:http://cacerts.test.digicert.com/DigiCertTestSHA2IntermediateCA1.crt
+
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ Signature Algorithm: sha256WithRSAEncryption
+ ae:d4:9c:8a:66:19:9e:7d:12:b7:05:c2:b6:33:b3:9c:a5:40:
+ 47:ab:34:8d:1b:0f:51:96:de:e9:46:5a:e4:16:10:43:56:bf:
+ fa:f8:64:f4:cb:53:39:5b:45:ca:7f:15:d9:59:25:21:23:c4:
+ 4d:dc:a7:f7:83:21:d2:3f:a8:0a:26:f4:ef:fa:1b:2b:7d:97:
+ 7e:28:f3:ca:cd:b2:c4:92:f3:92:27:7f:e0:f1:ac:d6:db:4c:
+ 10:8a:f8:6f:09:bb:b3:4f:19:06:aa:bb:74:1c:e0:51:42:f6:
+ 8c:7d:77:f7:80:a4:03:ab:a9:ae:ae:2b:89:17:af:2f:eb:f7:
+ 3d:61:7c:dd:e1:5d:d2:5a:c5:6a:f6:c8:92:4c:0a:b5:75:d1:
+ dd:39:f2:a7:a2:10:8c:6d:bf:ca:08:ad:b9:a9:df:e3:59:8f:
+ 64:16:3c:7e:8a:6e:27:fc:49:d7:06:f0:bd:94:15:f2:fd:0f:
+ 94:8a:b8:73:67:73:53:22:df:9d:36:e9:34:f9:2a:68:00:59:
+ 78:6d:2d:8f:a0:0f:13:af:bd:b3:aa:8c:37:c4:22:cf:23:fb:
+ 56:bc:4e:55:ae:3a:0a:e6:3e:b1:1a:22:71:7b:08:b8:00:41:
+ 14:26:f6:9b:9b:72:3f:eb:dc:dd:1b:db:a8:20:fd:54:75:ae:
+ 25:7f:80:e6
+```
+
+In the next step, we'll configure your application to actually use this new
+Certificate resource.
+
+## Exposing and securing your application
+
+Now that we have issued a Certificate, we can expose our application using a
+Kubernetes Ingress resource.
+
+Create a file named `application-ingress.yaml` and save the following in it,
+replacing `example.com` with your own domain name:
+
+```yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: frontend-ingress
+ namespace: demo
+ annotations:
+ kubernetes.io/ingress.class: "nginx"
+spec:
+ tls:
+ - hosts:
+ - example.com
+ secretName: example-com-tls
+ rules:
+ - host: example.com
+ http:
+ paths:
+ - path: /
+ pathType: Exact
+ backend:
+ service:
+ name: kuard
+ port:
+ number: 80
+```
+
+You can then apply this resource with:
+
+```bash
+$ kubectl apply -n demo -f application-ingress.yaml
+```
+
+Once this has been created, you should be able to visit your application at the
+configured URL, here `example.com`!
+
+Navigate to the address in your web browser and you should see the certificate
+obtained via Venafi being used to secure application traffic.
diff --git a/content/v1.12-docs/tutorials/zerossl/zerossl.md b/content/v1.12-docs/tutorials/zerossl/zerossl.md
new file mode 100644
index 0000000000..e10d997ec9
--- /dev/null
+++ b/content/v1.12-docs/tutorials/zerossl/zerossl.md
@@ -0,0 +1,180 @@
+---
+title: "Securing Ingresses with ZeroSSL"
+linkTitle: "Securing Ingresses with ZeroSSL"
+---
+
+# The ZeroSSL
+
+This guide walks you through how to secure a Kubernetes [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) resource using the ZeroSSL Issuer type.
+
+The ZeroSSL just like Let's Encrypt and its competitors allows to create free 90 days certificates. All is need is to create account at https://zerossl.com/. After that go to developer section and generate `EAB Credentials for ACME Clients`. You will need it later.
+
+
+`Please note!` \
+EAB credentials are not stored in your account, please make sure to note them somewhere. Each click on "Generate" will create a new set of credentials. Even if you create multiple credentials, all of them will remain functional.
+
+
+
+# Prerequisites
+
+- An AWS account
+- kubectl installed
+- Access to a publicly registered DNS zone
+- Kubernetes cluster, you can use AWS EKS
+- [ingress-nginx](https://kubernetes.github.io/ingress-nginx/) deployed and working inside cluster
+
+
+# Tutorial scenario:
+
+## Installing cert-manager
+
+Make sure you use cert-manager `1.8.2+`/`1.7.3+`. See [link](https://github.com/cert-manager/cert-manager/pull/5226) for more details.
+
+Please walk through the installation guide and return to this step once you
+have validated cert-manager is deployed correctly. Follow steps under [running on
+Kubernetes](../../installation/helm.md) to install in k8s.
+
+In order to automatically switch to the ZeroSSL we recommend setting default shim by adding the following configuration to values file.
+
+```yaml
+ingressShim:
+ defaultIssuerName: "zerossl-production"
+ defaultIssuerKind: "ClusterIssuer"
+
+installCRDs: true
+```
+
+Install it using helm:
+```
+helm upgrade --install --namespace cert-manager --version v1.8.2 cert-manager jetstack/cert-manager -f values.yaml
+```
+
+## Configure your DNS records
+
+The best way to manage DNS using AWS is by using Route53. Create AWS account with permissions to modify Route53 rules.
+
+## EAB secret
+Once you will get your credentials first step is to create seed with secrets. They are responsible for authenticating with your ZeroSSL account.
+
+```bash
+$ kubectl create secret generic \
+ zero-ssl-eabsecret \
+ --namespace=cert-manager \
+ --from-literal=secret='YOUR_ZEROSSL_EAB_HMAC_KEY'
+```
+
+### Another way of creating secret.
+
+Encode it in base64 first.
+```bash
+echo -n "YOUR_ZEROSSL_EAB_HMAC_KEY" | base64 -w 0
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: zero-ssl-eabsecret
+data:
+ secret: YOUR_ENCODED_ZEROSSL_EAB_HMAC_KEY
+```
+```bash
+kubectl apply -f zero-ssl-eabsecret.yaml -n cert-manager
+```
+
+## Cluster issuer
+Then we must create the `ZeroSSL` `ClusterIssuer`, let's call it `zerossl-production`. In our case we are using AWS. See pre-conditions to provision all required elements.
+
+```yaml
+apiVersion: cert-manager.io/v1alpha2
+kind: ClusterIssuer
+metadata:
+ name: zerossl-production
+spec:
+ acme:
+ # ZeroSSL ACME server
+ server: https://acme.zerossl.com/v2/DV90
+ email: dummy-email@yopmail.com
+
+ # name of a secret used to store the ACME account private key
+ privateKeySecretRef:
+ name: zerossl-prod
+
+ # for each cert-manager new EAB credencials are required
+ externalAccountBinding:
+ keyID: YOUR_ZEROSSL_EAB_KEY_ID
+ keySecretRef:
+ name: zero-ssl-eabsecret
+ key: secret
+ keyAlgorithm: HS256
+
+ # ACME DNS-01 provider configurations to verify domain
+ solvers:
+ - selector: {}
+ dns01:
+ route53:
+ region: us-west-2
+ # optional if ambient credentials are available; see ambient credentials documentation
+ # see Route53 for >0 issue "letsencrypt.org" and change to >0 issue "sectigo.com"
+ accessKeyID: ACCESS_KEY_ID
+ secretAccessKeySecretRef:
+ name: route53-credentials-secret
+ key: secret-access-key
+
+```
+
+### Then run:
+
+```bash
+$ kubectl apply -n cert-manager -f zerossl-production.yaml
+```
+
+```bash
+$ kubectl describe Clusterissuer zerossl-prod
+
+Status:
+ Acme:
+ Last Registered Email: dummy-email@yopmail.com
+ Uri: https://acme.zerossl.com/v2/DV90/account/tXXX_NwSv15rlS_XXXX
+ Conditions:
+ Last Transition Time: 2021-09-09T17:03:26Z
+ Message: The ACME account was registered with the ACME server
+ Reason: ACMEAccountRegistered
+ Status: True
+ Type: Ready
+```
+
+### Please note!
+If this step failed and the ACME account is not registered please check if secrets in `zero-ssl-eabsecret` are correct.
+
+## Request a ingress certificate
+
+
+```yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: test-ingress
+ namespace: default
+spec:
+ rules:
+ - host: test.example.com
+ tls:
+ - secretName: secret-tls
+
+```
+
+Apply test-ingress:
+
+```bash
+kubectl apply -f ingress.yaml
+```
+
+You are set! Check your ingress.
+```bash
+kubectl describe ingress test-ingress -n default
+# check if tls is terminated using secret-tls
+
+openssl s_client -showcerts -connect test.example.com:443
+# verify server certificate and its chain
+```
diff --git a/content/v1.12-docs/usage/README.md b/content/v1.12-docs/usage/README.md
new file mode 100644
index 0000000000..451db2ed9d
--- /dev/null
+++ b/content/v1.12-docs/usage/README.md
@@ -0,0 +1,31 @@
+---
+title: Issuing Certificates
+description: 'cert-manager usage: Overview'
+---
+
+Once an [`Issuer`](../configuration/README.md) has been configured, you're ready to issue your first certificate!
+
+There are several use cases and methods for requesting certificates through cert-manager:
+
+- [Certificate Resources](./certificate.md): The simplest and most common method for
+ requesting signed certificates.
+- [Securing Ingress Resources](./ingress.md): A method to secure ingress resources
+ in your cluster.
+- [Securing OpenFaaS functions](https://docs.openfaas.com/reference/ssl/kubernetes-with-cert-manager/):
+ Secure your OpenFaaS services using cert-manager.
+- [Integration with Garden](https://docs.garden.io/guides/cert-manager-integration): Garden is a
+ developer tool for developing Kubernetes applications which has first class
+ support for integrating cert-manager.
+- [Securing Knative](https://knative.dev/docs/serving/encryption/enabling-automatic-tls-certificate-provisioning/): Secure
+ your Knative services with trusted HTTPS certificates.
+- [Enable mTLS on Pods with CSI](./csi.md): Using the cert-manager CSI
+ driver to provide unique keys and certificates that share the lifecycle of
+ pods.
+- [Securing Istio Gateway](https://istio.io/docs/tasks/traffic-management/ingress/ingress-certmgr/):
+ Secure your Istio Gateway in Kubernetes using cert-manager.
+- [Securing Istio Service Mesh](./istio.md): Using the cert-manager
+ [Istio](https://istio.io) integration, secure the mTLS PKI for each pod
+ through cert-manager managed certificates.
+- [Policy for cert-manager certificates](./approver-policy.md): Manage
+ what cert-manager certificates are able to be signed or rejected through
+ custom resource defined policy.
diff --git a/content/docs/usage/approver-policy.md b/content/v1.12-docs/usage/approver-policy.md
similarity index 86%
rename from content/docs/usage/approver-policy.md
rename to content/v1.12-docs/usage/approver-policy.md
index 09d5768f3d..b712d04b7f 100644
--- a/content/docs/usage/approver-policy.md
+++ b/content/v1.12-docs/usage/approver-policy.md
@@ -10,5 +10,5 @@ API](../concepts/certificaterequest.md#approval).
cert-manager project that enables you to write policy to automatically manage
this approval mechanism.
-Please read the [project page](../projects/approver-policy.md) for more
+Please read the [project page](../projects/approver-policy/README.md) for more
information on how to install and use approver-policy.
diff --git a/content/v1.12-docs/usage/certificate.md b/content/v1.12-docs/usage/certificate.md
new file mode 100644
index 0000000000..17792853bf
--- /dev/null
+++ b/content/v1.12-docs/usage/certificate.md
@@ -0,0 +1,368 @@
+---
+title: Certificate Resources
+description: 'cert-manager usage: Certificates'
+---
+
+In cert-manager, the [`Certificate`](../concepts/certificate.md) resource
+represents a human readable definition of a certificate request that is to be
+honored by an issuer which is to be kept up-to-date. This is the usual way that
+you will interact with cert-manager to request signed certificates.
+
+In order to issue any certificates, you'll need to configure an
+[`Issuer`](../configuration/README.md) or [`ClusterIssuer`](../configuration/README.md)
+resource first.
+
+## Creating Certificate Resources
+
+A `Certificate` resource specifies fields that are used to generate certificate
+signing requests which are then fulfilled by the issuer type you have
+referenced. `Certificates` specify which issuer they want to obtain the
+certificate from by specifying the `certificate.spec.issuerRef` field.
+
+A `Certificate` resource, for the `example.com` and `www.example.com` DNS names,
+`spiffe://cluster.local/ns/sandbox/sa/example` URI Subject Alternative Name,
+that is valid for 90 days and renews 15 days before expiry is below. It contains
+an exhaustive list of all options a `Certificate` resource may have however only
+a subset of fields are required as labelled.
+
+```yaml
+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
+
+ duration: 2160h # 90d
+ renewBefore: 360h # 15d
+ subject:
+ organizations:
+ - jetstack
+ # The use of the common name field has been deprecated since 2000 and is
+ # discouraged from being used.
+ commonName: example.com
+ isCA: false
+ privateKey:
+ algorithm: RSA
+ encoding: PKCS1
+ size: 2048
+ usages:
+ - server auth
+ - client auth
+ # At least one of a DNS Name, URI, or IP address is required.
+ dnsNames:
+ - example.com
+ - www.example.com
+ uris:
+ - spiffe://cluster.local/ns/sandbox/sa/example
+ ipAddresses:
+ - 192.168.0.5
+ # 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
+```
+
+The signed certificate will be stored in a `Secret` resource named
+`example-com-tls` in the same namespace as the `Certificate` once the issuer has
+successfully issued the requested certificate.
+
+If `secretTemplate` is present, annotations and labels set in this property
+will be copied over to `example-com-tls` secret. Both properties are optional.
+
+The `Certificate` will be issued using the issuer named `ca-issuer` in the
+`sandbox` namespace (the same namespace as the `Certificate` resource).
+
+> Note: If you want to create an `Issuer` that can be referenced by
+> `Certificate` resources in _all_ namespaces, you should create a
+> [`ClusterIssuer`](../concepts/issuer.md#namespaces) resource and set the
+> `certificate.spec.issuerRef.kind` field to `ClusterIssuer`.
+
+> Note: The `renewBefore` and `duration` fields must be specified using a [Go
+> `time.Duration`](https://golang.org/pkg/time/#ParseDuration) string format,
+> which does not allow the `d` (days) suffix. You must specify these values
+> using `s`, `m`, and `h` suffixes instead. Failing to do so without installing
+> the [`webhook component`](../concepts/webhook.md) can prevent cert-manager
+> from functioning correctly
+> [`#1269`](https://github.com/cert-manager/cert-manager/issues/1269).
+
+> Note: Take care when setting the `renewBefore` field to be very close to the
+> `duration` as this can lead to a renewal loop, where the `Certificate` is always
+> in the renewal period. Some `Issuers` set the `notBefore` field on their
+> issued X.509 certificates before the issue time to fix clock-skew issues,
+> leading to the working duration of a certificate to be less than the full
+> duration of the certificate. For example, Let's Encrypt sets it to be one hour
+> before issue time, so the actual _working duration_ of the certificate is 89
+> days, 23 hours (the _full duration_ remains 90 days).
+
+A full list of the fields supported on the Certificate resource can be found in
+the [API reference documentation](../reference/api-docs.md#cert-manager.io/v1.CertificateSpec).
+
+
X.509 key usages and extended key usages
+
+cert-manager supports requesting certificates that have a number of [custom key
+usages](https://tools.ietf.org/html/rfc5280#section-4.2.1.3) and [extended key
+usages](https://tools.ietf.org/html/rfc5280#section-4.2.1.12). Although
+cert-manager will attempt to honor this request, some issuers will remove, add
+defaults, or otherwise completely ignore the request.
+The `CA` and `SelfSigned` `Issuer` will always return certificates matching the usages you have requested.
+
+Unless any number of usages has been set, cert-manager will set the default
+requested usages of `digital signature`, `key encipherment`, and `server auth`.
+cert-manager will not attempt to request a new certificate if the current
+certificate does not match the current key usage set.
+
+An exhaustive list of supported key usages can be found in the [API reference
+documentation](../reference/api-docs.md#cert-manager.io/v1.KeyUsage).
+
+
Temporary Certificates while Issuing
+
+When requesting certificates [using the ingress-shim](./ingress.md), the
+component `ingress-gce`, if used, requires that a temporary certificate is
+present while waiting for the issuance of a signed certificate when serving. To
+facilitate this, if the following annotation:
+
+ ```yaml
+ cert-manager.io/issue-temporary-certificate: "true"
+ ```
+
+is present on the certificate, a self-signed temporary certificate will be
+present on the `Secret` until it is overwritten once the signed certificate has
+been issued.
+
+Adding the following annotation on an ingress will automatically set "issue-temporary-certificate" on the certificate:
+
+ ```yaml
+ acme.cert-manager.io/http01-edit-in-place: "true"
+ ```
+
+
Rotation of the private key
+
+By default, the private key won't be rotated automatically. Using the setting
+`rotationPolicy: Always`, the private key Secret associated with a Certificate
+object can be configured to be rotated as soon as an action triggers the
+reissuance of the Certificate object (see
+[Actions that will trigger a rotation of the private key](#actions-triggering-private-key-rotation) below).
+
+With `rotationPolicy: Always`, cert-manager waits until the Certificate
+object is correctly signed before overwriting the `tls.key` file in the
+Secret.
+
+With this setting, you can expect **no downtime** if your application can detect
+changes to the mounted `tls.crt` and `tls.key` and reload them gracefully or
+automatically restart.
+
+If your application only loads the private key and signed certificate once
+at start up, the new certificate won't immediately be served by your
+application, and you will want to either manually restart your pod with
+`kubectl rollout restart`, or automate the action by running
+[wave](https://github.com/wave-k8s/wave). Wave is a Secret controller that
+makes sure deployments get restarted whenever a mounted Secret changes.
+
+
+
+Re-use of private keys
+
+Some issuers, like the built-in [Venafi
+issuer](../configuration/venafi.md), may disallow re-using private keys.
+If this is the case, you must explicitly configure the `rotationPolicy:
+Always` setting for each of your Certificate objects accordingly.
+
+
+
+In the following example, the certificate has been set with
+`rotationPolicy: Always`:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+spec:
+ secretName: my-cert-tls
+ privateKey:
+ rotationPolicy: Always # 🔰 Here.
+```
+
+
Actions that will trigger a rotation of the private key
+
+Setting the `rotationPolicy: Always` won't rotate the private key immediately.
+In order to rotate the private key, the certificate objects must be reissued. A
+certificate object is reissued under the following circumstances:
+
+- when the X.509 certificate is nearing expiry, which is when the Certificate's
+ `status.renewalTime` is reached;
+- when a change is made to one of the following fields on the Certificate's
+ spec: `commonName`, `dnsNames`, `ipAddresses`, `uris`, `emailAddresses`,
+ `subject`, `isCA`, `usages`, `duration` or `issuerRef`;
+- when a reissuance is manually triggered with the following:
+ ```sh
+ cmctl renew cert-1
+ ```
+ Note that the above command requires [cmctl](../reference/cmctl.md#renew).
+
+
+
+**❌** Deleting the Secret resource associated with a Certificate resource is
+**not a recommended solution** for manually rotating the private key. The
+recommended way to manually rotate the private key is to trigger the reissuance
+of the Certificate resource with the following command (requires
+[`cmctl`](../reference/cmctl.md#renew)):
+
+```sh
+cmctl renew cert-1
+```
+
+
+
+### The `rotationPolicy` setting
+
+The possible values for `rotationPolicy` are:
+
+| Value | Description |
+| ---------------------- | ------------------------------------------------------------- |
+| `Never` (default) | cert-manager reuses the existing private key on each issuance |
+| `Always` (recommended) | cert-manager regenerates a new private key on each issuance |
+
+With `rotationPolicy: Never`, a private key is only generated if one does not
+already exist in the target Secret resource (using the `tls.key` key). All
+further issuances will re-use this private key. This is the default in order to
+maintain compatibility with previous releases.
+
+With `rotationPolicy: Always`, a new private key will be generated each time an
+action triggers the reissuance of the certificate object (see [Actions that will
+trigger a rotation of the private key](#actions-triggering-private-key-rotation)
+above). Note that if the private key secret already exists when creating the
+certificate object, the existing private key will not be used, since the
+rotation mechanism also includes the initial issuance.
+
+
+
+👉 We recommend that you configure `rotationPolicy: Always` on your Certificate
+resources. Rotating both the certificate and the private key simultaneously
+prevents the risk of issuing a certificate with an exposed private key. Another
+benefit to renewing the private key regularly is to let you be confident that
+the private key rotation can be done in case of emergency. More generally, it is
+a good practice to be rotating the keys as often as possible, reducing the risk
+associated with compromised keys.
+
+
+
+## Cleaning up Secrets when Certificates are deleted
+
+By default, cert-manager does not delete the `Secret` resource containing the signed certificate when the corresponding `Certificate` resource is deleted.
+This means that deleting a `Certificate` won't take down any services that are currently relying on that certificate, but the certificate will no longer be renewed.
+The `Secret` needs to be manually deleted if it is no longer needed.
+
+If you would prefer the `Secret` to be deleted automatically when the `Certificate` is deleted, you need to configure your installation to pass the `--enable-certificate-owner-ref` flag to the controller.
+
+## Renewal
+
+cert-manager will automatically renew `Certificate`s. It will calculate _when_ to renew a `Certificate` based on the issued X.509 certificate's duration and a 'renewBefore' value which specifies _how long_ before expiry a certificate should be renewed.
+
+`spec.duration` and `spec.renewBefore` fields on a `Certificate` can be used to specify an X.509 certificate's duration and a 'renewBefore' value. Default value for `spec.duration` is 90 days. Some issuers might be configured to only issue certificates with a set duration, so the actual duration may be different.
+Minimum value for `spec.duration` is 1 hour and minimum value for `spec.renewBefore` is 5 minutes.
+It is also required that `spec.duration` > `spec.renewBefore`.
+
+Once an X.509 certificate has been issued, cert-manager will calculate the renewal time for the `Certificate`. By default this will be 2/3 through the X.509 certificate's duration. If `spec.renewBefore` has been set, it will be `spec.renewBefore` amount of time before expiry. cert-manager will set `Certificate`'s `status.RenewalTime` to the time when the renewal will be attempted.
+
+## Additional Certificate Output Formats
+
+
+
+⛔️ The additional certificate output formats feature is currently in an
+_experimental_ alpha state, and is subject to breaking changes or complete
+removal in future releases. This feature is only enabled by adding it to the
+`--feature-gates` flag on the cert-manager controller and webhook components:
+
+```bash
+--feature-gates=AdditionalCertificateOutputFormats=true
+```
+
+
+
+`additionalOutputFormats` is a field on the Certificate `spec` that allows
+specifying additional supplementary formats of issued certificates and their
+private key. There are currently two supported additional output formats:
+`CombinedPEM` and `DER`. Both output formats can be specified on the same
+Certificate.
+
+```yaml
+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:
+ tls.key:
+ tls.crt:
+ tls-combined.pem:
+ key.der:
+```
+
+#### `CombinedPEM`
+
+The `CombinedPEM` type will create a new key entry in the resulting
+Certificate's Secret `tls-combined.pem`. This entry will contain the PEM encoded
+private key, followed by at least one new line character, followed by the PEM
+encoded signed certificate chain-
+
+```text
+ + "\n" +
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: my-cert-tls
+type: kubernetes.io/tls
+data:
+ tls-combined.pem:
+ ...
+```
+
+#### `DER`
+
+The `DER` type will create a new key entry in the resulting Certificate's Secret
+`key.der`. This entry will contain the DER binary format of the private key.
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: my-cert-tls
+type: kubernetes.io/tls
+data:
+ key.der:
+ ...
+```
diff --git a/content/v1.12-docs/usage/csi.md b/content/v1.12-docs/usage/csi.md
new file mode 100644
index 0000000000..5e1a6124b0
--- /dev/null
+++ b/content/v1.12-docs/usage/csi.md
@@ -0,0 +1,85 @@
+---
+title: CSI Driver
+description: 'cert-manager usage: CSI driver'
+---
+
+## Enabling mTLS of Pods using the cert-manager CSI Driver
+
+A [Container Storage Interface (CSI)
+driver](../projects/csi-driver.md) has been created to
+facilitate mTLS of Pods running inside your cluster through use of cert-manager.
+Using this driver will ensure that the private key and corresponding signed
+certificate will be unique to each Pod and will be stored on disk to the node
+that the Pod is scheduled to. The life cycle of the certificate key pair matches
+that of the Pod meaning that they will be created at Pod creation, and destroyed
+during termination. This driver also handles renewal on live certificates on the
+fly.
+
+A [CSI
+driver](https://github.com/container-storage-interface/spec/blob/master/spec.md)
+is a storage plugin that is deployed into your Kubernetes cluster that can
+honor volume requests specified on Pods, just like those enabled by default such as
+the `Secret`, `ConfigMap`, or `hostPath` volume drivers. In the case of the cert-manager
+CSI driver, it makes use of the ephemeral volume type, made beta as of
+[`v1.16`](https://kubernetes.io/docs/concepts/storage/volumes/#csi-ephemeral-volumes)
+and as such will only work from the Kubernetes version `v1.16`. An ephemeral
+volumes means that the volume is created and destroyed as the Pod is created and
+terminated, as well as specifying the volume attributes, without the need of a
+`PersistentVolume`. This gives the feature of not only having unique
+certificates and keys per Pod, where the private key never leaves the hosts
+node, but that the desired certificate for that Pod template can be defined in
+line with the deployment spec.
+
+> **Warning**: Use of the CSI driver is mostly intended for supporting a PKI of
+> your cluster and facilitating mTLS, and as such, a private Certificate
+> Authority issuer should be used - CA, Vault, and perhaps Venafi, or other
+> external issuers. It is *not* recommended to use public Certificate
+> Authorities, for example Let's Encrypt, which hold strict rate limits on the
+> number of certificates that can be issued for a single domain. Like Pods,
+> these certificate key pairs are designed to be non-immutable and can be
+> created and destroyed at any time during normal operation.
+
+## How Does it Work?
+
+The CSI specification is a protocol and standard for building storage drivers
+for container orchestration platforms with the intention that a single driver
+may be ported across multiple platforms and outlines a consistent specification
+to how drivers should behave from an infrastructure perspective. Since
+cert-manager is designed to only be run with a Kubernetes cluster, so too does
+the cert-manager CSI driver.
+
+The driver should be deployed as a
+[DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)
+which means a single instance of the driver may be run on each node. The driver
+will not work when running multiple instances on a single node. The set of nodes
+that the driver runs on can be restricted using the
+[`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/)
+in its Pod template.
+
+When a Pod is scheduled to a node with a cert-manager CSI volume specified, the
+[`Kubelet`](https://kubernetes.io/docs/concepts/overview/components/#kubelet)
+running on that node will send a `NodePublishVolume` call to the driver on that
+node, containing that Pods information as well as the attributes detailed from
+the in-line volume attributes. From this, the driver will generate a private key
+as well as a certificate request based upon that key using information built
+from the volume attributes. The driver will create a `CertificateRequest`
+resource in the same namespace in the Pod that, if valid, cert-manager will
+return a signed certificate.
+
+The resulting signed certificate and generated key will be written to that
+node's file system to be mounted to the Pods file system. Since the driver needs
+access to the nodes file system it must be made privileged. Once mounted, the
+Pod will begin execution with the unique private key and certificate available in
+its file system, as defined by its mount path.
+
+By default, the driver will keep track of certificates created in order to
+monitor when they should be marked for renewal. When this happens, the driver
+will request for a new signed certificate, and when successful, will simply
+overwrite the existing certificate in path.
+
+When the Pod is marked for termination, the `NodeUnpublishVolume` call is made
+to the node's driver which in turn destroys the certificate and key from the
+nodes file system.
+
+The CSI driver is able to recover its full state in the event the its Pod being
+terminated.
diff --git a/content/v1.12-docs/usage/gateway.md b/content/v1.12-docs/usage/gateway.md
new file mode 100644
index 0000000000..9aa05cf1a1
--- /dev/null
+++ b/content/v1.12-docs/usage/gateway.md
@@ -0,0 +1,402 @@
+---
+title: Securing gateway.networking.k8s.io Gateway Resources
+description: 'cert-manager usage: Kubernetes Gateways'
+---
+
+**FEATURE STATE**: cert-manager 1.5 [alpha]
+
+
+
+📌 This page focuses on automatically creating Certificate resources by
+annotating Kubernetes Gateway resource. If you are looking for using an ACME Issuer along
+with HTTP-01 challenges using the Kubernetes Gateway API, see [ACME
+HTTP-01](../configuration/acme/http01/README.md).
+
+
+
+
+
+🚧 cert-manager 1.8+ is tested with v1alpha2 Kubernetes Gateway API. It should also work
+with v1beta1 because of resource conversion, but has not been tested with it.
+
+
+
+cert-manager can generate TLS certificates for Gateway resources. This is
+configured by adding annotations to a Gateway and is similar to the process for
+[Securing Ingress Resources](../usage/ingress.md).
+
+The Gateway resource is part of the [Gateway API][gwapi], a set of CRDs that you
+install on your Kubernetes cluster and which provide various improvements over
+the Ingress API.
+
+[gwapi]: https://gateway-api.sigs.k8s.io
+
+The Gateway resource holds the TLS configuration, as illustrated in the
+following diagram (source: https://gateway-api.sigs.k8s.io):
+
+![Gateway vs. HTTPRoute](/images/gateway-roles.png)
+
+
+
+📌 This feature requires the installation of the [Gateway API bundle](https://gateway-api.sigs.k8s.io/guides/#installing-a-gateway-controller) and passing a
+feature flag to the cert-manager controller.
+
+To install v1.5.1 Gateway API bundle (Gateway CRDs and webhook), run the following command:
+
+```sh
+kubectl apply -f "https://github.com/kubernetes-sigs/gateway-api/releases/download/v0.5.1/standard-install.yaml"
+```
+
+To enable the feature in cert-manager, turn on the `GatewayAPI` feature gate:
+
+- If you are using Helm:
+
+ ```sh
+ helm upgrade --install cert-manager jetstack/cert-manager --namespace cert-manager \
+ --set "extraArgs={--feature-gates=ExperimentalGatewayAPISupport=true}"
+ ```
+
+- If you are using the raw cert-manager manifests, add the following flag to the
+ cert-manager controller Deployment:
+
+ ```yaml
+ args:
+ - --feature-gates=ExperimentalGatewayAPISupport=true
+ ```
+
+The Gateway API CRDs should either be installed before cert-manager starts or
+the cert-manager Deployment should be restarted after installing the Gateway API
+CRDs. This is important because some of the cert-manager components only perform
+the Gateway API check on startup. You can restart cert-manager with the
+following command:
+
+```sh
+kubectl rollout restart deployment cert-manager -n cert-manager
+```
+
+
+
+The annotations `cert-manager.io/issuer` or `cert-manager.io/cluster-issuer`
+tell cert-manager to create a Certificate for a Gateway. For example, the
+following Gateway will trigger the creation of a Certificate with the name
+`example-com-tls`:
+
+```yaml
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: Gateway
+metadata:
+ name: example
+ annotations:
+ cert-manager.io/issuer: foo
+spec:
+ gatewayClassName: foo
+ listeners:
+ - name: http
+ hostname: example.com
+ port: 443
+ protocol: HTTPS
+ allowedRoutes:
+ namespaces:
+ from: All
+ tls:
+ mode: Terminate
+ certificateRefs:
+ - name: example-com-tls
+```
+
+A few moments later, cert-manager will create a Certificate. The Certificate is
+named after the Secret name `example-com-tls`. The `dnsNames` field is set with
+the `hostname` field from the Gateway spec.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com-tls
+spec:
+ issuerRef:
+ name: my-issuer
+ kind: Issuer
+ group: cert-manager.io
+ dnsNames:
+ - example.com # ✅ Copied from the `hostname` field.
+ secretName: example-com-tls
+```
+
+
+
+🚧 this mechanism can only be used to create Secrets in the same namespace as the `Gateway`, see [`cert-manager#5610`](https://github.com/cert-manager/cert-manager/issues/5610)
+
+
+
+## Use cases
+
+### Generate TLS certs for selected TLS blocks
+
+cert-manager skips any listener block that cannot be used for generating a
+Certificate. For a listener block to be used for creating a Certificate, it must
+meet the following requirements:
+
+| Field | Requirement |
+|--------------------------------|-------------------------------------------------------------|
+| `tls.hostname` | Must not be empty. |
+| `tls.mode` | Must be set to `Terminate`. `Passthrough` is not supported. |
+| `tls.certificateRef.name` | Cannot be left empty. |
+| `tls.certificateRef.kind` | If specified, must be set to `Secret`. |
+| `tls.certificateRef.group` | If specified, must be set to `core`. |
+| `tls.certificateRef.namespace` | If specified, must be the same as the `Gateway`. |
+
+In the following example, the first four listener blocks will not be used to
+generate Certificate resources:
+
+```yaml
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: Gateway
+metadata:
+ name: my-gateway
+ namespace: default
+ annotations:
+ cert-manager.io/issuer: my-issuer
+spec:
+ listeners:
+ # ❌ Missing "tls" block, the following listener is skipped.
+ - hostname: example.com
+
+ # ❌ Missing "hostname", the following listener is skipped.
+ - tls:
+ certificateRefs:
+ - name: example-com-tls
+ kind: Secret"
+ group: core
+
+ # ❌ "mode: Passthrough" is not supported, the following listener is skipped.
+ - hostname: example.com
+ tls:
+ mode: Passthrough
+ certificateRefs:
+ - name: example-com-tls
+ kind: Secret
+ group: core
+
+ # ❌ Cross-namespace secret references are not supported, the following listener is skipped.
+ - hostname: foo.example.com
+ port: 443
+ protocol: HTTPS
+ allowedRoutes:
+ namespaces:
+ from: All
+ tls:
+ mode: Terminate
+ certificateRefs:
+ - name: example-com-tls
+ kind: Secret
+ group: core
+ namespace: other-namespace
+
+ # ✅ The following listener is valid.
+ - hostname: foo.example.com # ✅ Required.
+ port: 443
+ protocol: HTTPS
+ allowedRoutes:
+ namespaces:
+ from: All
+ tls:
+ mode: Terminate # ✅ Required. "Terminate" is the only supported mode.
+ certificateRefs:
+ - name: example-com-tls # ✅ Required.
+ kind: Secret # ✅ Required. "Secret" is the only valid value.
+ group: core # ✅ Required. "core" is the only valid value.
+```
+
+cert-manager has skipped over the first four listener blocks and has created a
+single Certificate named `example-com-tls` for the last listener block:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com-tls
+spec:
+ issuerRef:
+ name: my-issuer
+ kind: Issuer
+ group: cert-manager.io
+ dnsNames:
+ - foo.example.com
+ secretName: example-com-tls
+```
+
+### Two listeners with the same Secret name
+
+The same Secret name can be re-used in multiple TLS blocks, regardless of the
+hostname. Let us imagine that you have these two listeners:
+
+```yaml
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: Gateway
+metadata:
+ name: example
+ annotations:
+ cert-manager.io/issuer: my-issuer
+spec:
+ gatewayClassName: foo
+ listeners:
+ # Listener 1.
+ - hostname: example.com
+ port: 443
+ protocol: HTTPS
+ routes:
+ kind: HTTPRoute
+ parentRefs:
+ - name: example
+ kind: Gateway
+ tls:
+ mode: Terminate
+ certificateRefs:
+ - name: example-com-tls
+ kind: Secret
+ group: core
+
+ # Listener 2: Same Secret name as Listener 1, with a different hostname.
+ - hostname: *.example.com
+ port: 443
+ protocol: HTTPS
+ routes:
+ kind: HTTPRoute
+ parentRefs:
+ - name: example
+ kind: Gateway
+ tls:
+ mode: Terminate
+ certificateRefs:
+ - name: example-com-tls
+ kind: Secret
+ group: core
+
+ # Listener 3: also same Secret name, except the hostname is also the same.
+ - hostname: *.example.com
+ port: 8443
+ protocol: HTTPS
+ routes:
+ kind: HTTPRoute
+ parentRefs:
+ - name: example
+ kind: Gateway
+ tls:
+ mode: Terminate
+ certificateRefs:
+ - name: example-com-tls
+ kind: Secret
+ group: core
+
+ # Listener 4: different Secret name.
+ - hostname: site.org
+ port: 443
+ protocol: HTTPS
+ routes:
+ kind: HTTPRoute
+ parentRefs:
+ - name: example
+ kind: Gateway
+ tls:
+ mode: Terminate
+ certificateRefs:
+ - name: site-org-tls
+ kind: Secret
+ group: core
+```
+
+cert-manager will create two Certificates since two Secret names are used:
+`example-com-tls` and `site-org-tls`. Note the Certificate's `dnsNames` contains
+a single occurrence of `*.example.com ` for both listener 2 and 3 (the
+`hostname` values are de-duplicated).
+
+The two Certificates look like this:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com-tls
+spec:
+ issuerRef:
+ name: my-issuer
+ kind: Issuer
+ group: cert-manager.io
+ dnsNames:
+ - example.com # From listener 1.
+ - *.example.com # From listener 2 and 3.
+ secretName: example-com-tls
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: site-org-tls
+spec:
+ issuerRef:
+ name: my-issuer
+ kind: Issuer
+ group: cert-manager.io
+ dnsNames:
+ - site.org # From listener 4.
+ secretName: site-org-tls
+```
+
+## Supported Annotations
+
+If you are migrating to Gateway resources from Ingress resources, be aware that
+there are some differences between [the annotations for Ingress resources](./ingress.md#supported-annotations)
+versus the annotations for Gateway resources.
+
+The Gateway resource supports the following annotations for generating
+Certificate resources:
+
+- `cert-manager.io/issuer`: the name of an Issuer to acquire the certificate
+ required for this Gateway. The Issuer _must_ be in the same namespace as the
+ Gateway resource.
+
+- `cert-manager.io/cluster-issuer`: the name of a ClusterIssuer to acquire the
+ Certificate required for this Gateway. It does not matter which namespace your
+ Gateway resides, as `ClusterIssuers` are non-namespaced resources.
+
+- `cert-manager.io/issuer-kind`: the kind of the external issuer resource, for
+ example `AWSPCACIssuer`. This is only necessary for out-of-tree issuers.
+
+- `cert-manager.io/issuer-group`: the API group of the external issuer
+ controller, for example `awspca.cert-manager.io`. This is only necessary for
+ out-of-tree issuers.
+
+- `cert-manager.io/common-name`: (optional) this annotation allows you to
+ configure `spec.commonName` for the Certificate to be generated.
+
+- ` cert-manager.io/duration`: (optional) this annotation allows you to
+ configure `spec.duration` field for the Certificate to be generated.
+
+- `cert-manager.io/renew-before`: (optional) this annotation allows you to
+ configure `spec.renewBefore` field for the Certificate to be generated.
+
+- `cert-manager.io/usages`: (optional) this annotation allows you to configure
+ `spec.usages` field for the Certificate to be generated. Pass a string with
+ comma-separated values i.e "key agreement,digital signature, server auth"
+
+- `cert-manager.io/revision-history-limit`: (optional) this annotation allows you to
+ configure `spec.revisionHistoryLimit` field to limit the number of CertificateRequests to be kept for a Certificate.
+ Minimum value is 1. If unset all CertificateRequests will be kept.
+
+- `cert-manager.io/private-key-algorithm`: (optional) this annotation allows you to
+ configure `spec.privateKey.algorithm` field to set the algorithm for private key generation for a Certificate.
+ Valid values are `RSA`, `ECDSA` and `Ed25519`. If unset an algorithm `RSA` will be used.
+
+- `cert-manager.io/private-key-encoding`: (optional) this annotation allows you to
+ configure `spec.privateKey.encoding` field to set the encoding for private key generation for a Certificate.
+ Valid values are `PKCS1` and `PKCS8`. If unset an algorithm `PKCS1` will be used.
+
+- `cert-manager.io/private-key-size`: (optional) this annotation allows you to
+ configure `spec.privateKey.size` field to set the size of the private key for a Certificate.
+ If algorithm is set to `RSA`, valid values are `2048`, `4096` or `8192`, and will default to `2048` if not specified.
+ If algorithm is set to `ECDSA`, valid values are `256`, `384` or `521`, and will default to `256` if not specified.
+ If algorithm is set to `Ed25519`, size is ignored.
+
+- `cert-manager.io/private-key-rotation-policy`: (optional) this annotation allows you to
+ configure `spec.privateKey.rotationPolicy` field to set the rotation policy of the private key for a Certificate.
+ Valid values are `Never` and `Always`. If unset a rotation policy `Never` will be used.
diff --git a/content/v1.12-docs/usage/ingress.md b/content/v1.12-docs/usage/ingress.md
new file mode 100644
index 0000000000..e70c77390f
--- /dev/null
+++ b/content/v1.12-docs/usage/ingress.md
@@ -0,0 +1,175 @@
+---
+title: Securing Ingress Resources
+description: 'cert-manager usage: Kubernetes Ingress'
+---
+
+A common use-case for cert-manager is requesting TLS signed certificates to
+secure your ingress resources. This can be done by simply adding annotations to
+your `Ingress` resources and cert-manager will facilitate creating the
+`Certificate` resource for you. A small sub-component of cert-manager,
+ingress-shim, is responsible for this.
+
+## How It Works
+
+The sub-component ingress-shim watches `Ingress` resources across your cluster.
+If it observes an `Ingress` with annotations described in the [Supported
+Annotations](#supported-annotations) section, it will ensure a `Certificate`
+resource with the name provided in the `tls.secretName` field and configured as
+described on the `Ingress` exists in the `Ingress`'s namespace. For example:
+
+```yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ annotations:
+ # add an annotation indicating the issuer to use.
+ cert-manager.io/cluster-issuer: nameOfClusterIssuer
+ name: myIngress
+ namespace: myIngress
+spec:
+ rules:
+ - host: example.com
+ http:
+ paths:
+ - pathType: Prefix
+ path: /
+ backend:
+ service:
+ name: myservice
+ port:
+ number: 80
+ tls: # < placing a host in the TLS config will determine what ends up in the cert's subjectAltNames
+ - hosts:
+ - example.com
+ secretName: myingress-cert # < cert-manager will store the created certificate in this secret.
+```
+
+## Supported Annotations
+
+You can specify the following annotations on Ingress resources in order to
+trigger Certificate resources to be automatically created:
+
+- `cert-manager.io/issuer`: the name of the issuer that should issue the certificate
+ required for this Ingress.
+
+ > ⚠️ This annotation does _not_ assume a namespace scoped issuer. It will
+ default to cert-manager.io Issuer, however in case of external issuer types,
+ this should be used for both namespaced and cluster scoped issuer types.
+
+ > ⚠️ If a namespace scoped issuer is used then the issuer *must* be in
+ the same namespace as the Ingress resource.
+
+- `cert-manager.io/cluster-issuer`: the name of a cert-manager.io ClusterIssuer
+ to acquire the certificate required for this Ingress. It does not matter which
+ namespace your Ingress resides, as ClusterIssuers are non-namespaced
+ resources.
+
+ > ⚠️ This annotation is a shortcut to refer to to
+ cert-manager.io ClusterIssuer without having to specify group and kind. It is
+ _not_ intended to be used to specify an external cluster-scoped issuer- please
+ use `cert-manager.io/issuer` annotation for those.
+
+- `cert-manager.io/issuer-kind`: the kind of the external issuer resource, for
+ example `AWSPCAIssuer`. This is only necessary for out-of-tree issuers.
+
+- `cert-manager.io/issuer-group`: the API group of the external issuer
+ controller, for example `awspca.cert-manager.io`. This is only necessary for
+ out-of-tree issuers.
+
+- `kubernetes.io/tls-acme: "true"`: this annotation requires additional
+ configuration of the ingress-shim [see below](#optional-configuration).
+ Namely, a default Issuer must be specified as arguments to the ingress-shim
+ container.
+
+- `acme.cert-manager.io/http01-ingress-class`: this annotation allows you to
+ configure the ingress class that will be used to solve challenges for this
+ ingress. Customizing this is useful when you are trying to secure internal
+ services, and need to solve challenges using a different ingress class to that
+ of the ingress. If not specified and the `acme-http01-edit-in-place` annotation
+ is not set, this defaults to the ingress class defined in the Issuer resource.
+
+- `acme.cert-manager.io/http01-edit-in-place: "true"`: this controls whether the
+ ingress is modified 'in-place', or a new one is created specifically for the
+ HTTP01 challenge. If present, and set to "true", the existing ingress will be
+ modified. Any other value, or the absence of the annotation assumes "false".
+ This annotation will also add the annotation
+ `"cert-manager.io/issue-temporary-certificate": "true"` onto created
+ certificates which will cause a [temporary
+ certificate](./certificate.md#temporary-certificates-whilst-issuing) to be set
+ on the resulting Secret until the final signed certificate has been returned.
+ This is useful for keeping compatibility with the `ingress-gce` component.
+
+- `cert-manager.io/common-name`: (optional) this annotation allows you to
+ configure `spec.commonName` for the Certificate to be generated.
+
+- ` cert-manager.io/duration`: (optional) this annotation allows you to
+ configure `spec.duration` field for the Certificate to be generated.
+
+- `cert-manager.io/renew-before`: (optional) this annotation allows you to
+ configure `spec.renewBefore` field for the Certificate to be generated.
+
+- `cert-manager.io/usages`: (optional) this annotation allows you to configure
+ `spec.usages` field for the Certificate to be generated. Pass a string with
+ comma-separated values i.e "key agreement,digital signature, server auth"
+
+- `cert-manager.io/revision-history-limit`: (optional) this annotation allows you to
+ configure `spec.revisionHistoryLimit` field to limit the number of CertificateRequests to be kept for a Certificate.
+ Minimum value is 1. If unset all CertificateRequests will be kept.
+
+- `cert-manager.io/private-key-algorithm`: (optional) this annotation allows you to
+ configure `spec.privateKey.algorithm` field to set the algorithm for private key generation for a Certificate.
+ Valid values are `RSA`, `ECDSA` and `Ed25519`. If unset an algorithm `RSA` will be used.
+
+- `cert-manager.io/private-key-encoding`: (optional) this annotation allows you to
+ configure `spec.privateKey.encoding` field to set the encoding for private key generation for a Certificate.
+ Valid values are `PKCS1` and `PKCS8`. If unset an algorithm `PKCS1` will be used.
+
+- `cert-manager.io/private-key-size`: (optional) this annotation allows you to
+ configure `spec.privateKey.size` field to set the size of the private key for a Certificate.
+ If algorithm is set to `RSA`, valid values are `2048`, `4096` or `8192`, and will default to `2048` if not specified.
+ If algorithm is set to `ECDSA`, valid values are `256`, `384` or `521`, and will default to `256` if not specified.
+ If algorithm is set to `Ed25519`, size is ignored.
+
+- `cert-manager.io/private-key-rotation-policy`: (optional) this annotation allows you to
+ configure `spec.privateKey.rotationPolicy` field to set the rotation policy of the private key for a Certificate.
+ Valid values are `Never` and `Always`. If unset a rotation policy `Never` will be used.
+
+
+## Optional Configuration
+
+The ingress-shim sub-component is deployed automatically as part of
+installation.
+
+If you would like to use the old
+[kube-lego](https://github.com/jetstack/kube-lego) `kubernetes.io/tls-acme:
+"true"` annotation for fully automated TLS, you will need to configure a default
+`Issuer` when deploying cert-manager. This can be done by adding the following
+`--set` when deploying using Helm:
+
+```bash
+ --set ingressShim.defaultIssuerName=letsencrypt-prod \
+ --set ingressShim.defaultIssuerKind=ClusterIssuer \
+ --set ingressShim.defaultIssuerGroup=cert-manager.io
+```
+
+Or by adding the following arguments to the cert-manager deployment
+`podTemplate` container arguments.
+
+```
+ - --default-issuer-name=letsencrypt-prod
+ - --default-issuer-kind=ClusterIssuer
+ - --default-issuer-group=cert-manager.io
+```
+
+In the above example, cert-manager will create `Certificate` resources that
+reference the `ClusterIssuer` `letsencrypt-prod` for all Ingresses that have a
+`kubernetes.io/tls-acme: "true"` annotation.
+
+Issuers configured via annotations have a preference over the default issuer. If a default issuer is configured via CLI flags and a `cert-manager.io/cluster-issuer` or `cert-manager.io/issuer` annotation also has been added to an Ingress, the created `Certificate` will refer to the issuer configured via annotation.
+
+For more information on deploying cert-manager, read the [installation
+guide](../installation/README.md).
+
+## Troubleshooting
+
+If you do not see a `Certificate` resource being created after applying the ingress-shim annotations check that at least `cert-manager.io/issuer` or `cert-manager.io/cluster-issuer` is set. If you want to use `kubernetes.io/tls-acme: "true"` make sure to have checked all steps above and you might want to look for errors in the cert-manager pod logs if not resolved.
\ No newline at end of file
diff --git a/content/docs/usage/istio.md b/content/v1.12-docs/usage/istio.md
similarity index 100%
rename from content/docs/usage/istio.md
rename to content/v1.12-docs/usage/istio.md
diff --git a/content/v1.12-docs/usage/kube-csr.md b/content/v1.12-docs/usage/kube-csr.md
new file mode 100644
index 0000000000..f6abb93f74
--- /dev/null
+++ b/content/v1.12-docs/usage/kube-csr.md
@@ -0,0 +1,166 @@
+---
+title: Kubernetes CertificateSigningRequests
+description: 'cert-manager usage: Kubernetes CertificateSigningRequest resources'
+---
+
+Kubernetes has an in-built
+[CertificateSigningRequest](https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/)
+resource. This resource is similar to the cert-manager
+[CertificateRequest](../concepts/certificaterequest.md) in that it is used to
+request an X.509 signed certificate from a referenced Certificate Authority
+(CA).
+
+Using this resource may be useful for users who are using an application that
+supports this resource, but not the cert-manager CertificateRequest resource,
+and they still wish for certificates to be signed through cert-manager.
+
+CertificateSigningRequests reference a `SignerName` or signer as the entity it
+wishes to sign its request from. For cert-manager, a signer can be mapped to
+either an [Issuer or ClusterIssuer](../configuration/README.md).
+
+#### Feature State
+
+This feature is currently in an _experimental_ state, and its behavior is
+subject to change in further releases.
+
+
+
+⛔️ This feature is only enabled by adding it to the `--feature-gates` flag on
+the cert-manager controller:
+
+```bash
+--feature-gates=ExperimentalCertificateSigningRequestControllers=true
+```
+
+Which can be added using Helm:
+
+```bash
+$ helm install \
+ cert-manager jetstack/cert-manager \
+ --namespace cert-manager \
+ --create-namespace \
+ --set featureGates="ExperimentalCertificateSigningRequestControllers=true" \
+ # --set installCRDs=true
+```
+
+> Note: cert-manager supports signing CertificateSigningRequests
+> using all [internal Issuers](../configuration/README.md).
+
+> Note: cert-manager _does not_ automatically approve CertificateSigningRequests
+> that reference a cert-manager [Issuer](../configuration/README.md). Please refer to
+> the [Kubernetes documentation](https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#request-signing-process)
+> for the request process of CertificateSigningRequests.
+
+
+
+
+
+## Signer Name
+
+CertificateSigningRequests contain a
+[`spec.signerName`](https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#request-signing-process)
+field to reference a CA to sign the request. cert-manager Issuers or
+ClusterIssuers are referenced in the following form:
+
+```
+.cert-manager.io/.
+```
+
+For example, a namespaced Issuer in the namespace `sandbox` with the name
+`my-issuer` would be referenced via:
+
+```yaml
+ signerName: issuers.cert-manager.io/sandbox.my-issuer
+```
+
+A ClusterIssuer with the name `my-cluster-issuer` would be referenced via:
+
+```yaml
+ signerName: clusterissuers.cert-manager.io/my-cluster-issuer
+```
+
+### Referencing Namespaced Issuers
+
+Unlike CertificateRequests, CertificateSigningRequests are cluster scoped
+resources. To prevent users from requesting certificates from a namespaced
+Issuer in a namespace that they otherwise would not have access to, cert-manager
+performs a
+[SubjectAccessReview](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#checking-api-access).
+This review ensures that the requesting user has the permission to `reference`
+the `signers` resource in the given namespace. The name should be either the
+name of the Issuer, or `"*"` to reference all Issuers in that namespace.
+
+An example Role to give permissions to reference Issuers in the `sandbox`
+namespace would look like the following:
+
+```yaml
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: cert-manager-referencer:my-issuer
+ namespace: sandbox
+rules:
+- apiGroups: ["cert-manager.io"]
+ resources: ["signers"]
+ verbs: ["reference"]
+ resourceNames:
+ - "my-issuer" # To give permission to _only_ reference Issuers with the name 'my-issuer'
+ - "*" # To give permission to reference Issuers with any name in this namespace
+```
+
+## Annotations
+
+To keep feature parity with CertificateRequests, annotations are used to store
+values that do not exist as `spec` or `status` fields on the
+CertificateSigningRequest resource. These fields are either set by the
+_requester_ or by the _signer_ as labelled below.
+
+Requester annotations:
+
+- `experimental.cert-manager.io/request-duration`: **Set by the requester**. Accepts
+ a [Go time duration](https://golang.org/pkg/time/#ParseDuration) string
+ specifying the requested certificate duration. Defaults to 90 days. Some
+ signers such as Venafi or ACME typically _do not_ allow requesting a
+ duration.
+
+- `experimental.cert-manager.io/request-is-ca`: **Set by the requester**. If set to
+ `"true"`, will request for a CA certificate.
+
+- `experimental.cert-manager.io/private-key-secret-name`: **Set by the
+ requester**. Required only for the SelfSigned signer. Used to reference a
+ Secret which contains the PEM encoded private key of the requester's X.509
+ certificate signing request at key `tls.key`. Used to sign the requester's
+ request.
+
+- `venafi.experimental.cert-manager.io/custom-fields`: **Set by the
+ requester**. Optional for only the Venafi signer. Used for adding custom
+ fields to the Venafi request. This will only work with Venafi TPP `v19.3`
+ and higher. The value is a JSON array with objects containing the name and
+ value keys, for example:
+ ```
+ venafi.experimental.cert-manager.io/custom-fields: |-
+ [
+ {"name": "field-name", "value": "field value"},
+ {"name": "field-name-2", "value": "field value 2"}
+ ]
+ ```
+
+Signer annotations:
+
+- `venafi.experimental.cert-manager.io/pickup-id`: **Set by the signer**. Only
+ used for the Venafi signer. Used to record the Venafi Pickup ID of a
+ certificate signing request that has been submitted to the Venafi API for
+ collection during issuance.
+
+## Usage
+
+CertificateSigningRequests can be manually created using
+[cmctl](../reference/cmctl.md#experimental).
+This command takes a manifest file containing a
+[Certificate](../usage/certificate.md) resource as input. This generates a
+private key and creates a CertificateSigningRequest. CertificateSigningRequests
+are not approved by default, so you will likely need to approve it manually:
+
+```bash
+$ kubectl certificate approve
+```
diff --git a/content/v1.12-docs/usage/prometheus-metrics.md b/content/v1.12-docs/usage/prometheus-metrics.md
new file mode 100644
index 0000000000..968ce2077d
--- /dev/null
+++ b/content/v1.12-docs/usage/prometheus-metrics.md
@@ -0,0 +1,69 @@
+---
+title: Prometheus Metrics
+description: 'cert-manager usage: Prometheus metrics'
+---
+
+To help with operations and insights into cert-manager activities, cert-manager exposes metrics in the [Prometheus](https://prometheus.io/) format from the controller component. These are available at the standard `/metrics` path of the controller component's configured HTTP port.
+
+## Scraping Metrics
+
+How metrics are scraped will depend how you're operating your Prometheus server(s). These examples presume the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator) is being used to run Prometheus, and configure Pod or Service Monitor CRDs.
+
+### Helm
+
+If you're deploying cert-manager with helm, a `ServiceMonitor` resource can be configured. This configuration should enable metric scraping, and the configuration can be further tweaked as described in the [Helm configuration documentation](https://github.com/cert-manager/cert-manager/blob/master/deploy/charts/cert-manager/README.template.md#configuration).
+
+```yaml
+prometheus:
+ enabled: true
+ servicemonitor:
+ enabled: true
+```
+
+### Regular Manifests
+
+If you're not using helm to deploy cert-manager and instead using the provided regular YAML manifests, this example `PodMonitor` and deployment patch should be all you need to start ingesting cert-manager metrics.
+
+1. [Apply the following patch](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/#use-a-strategic-merge-patch-to-update-a-deployment) to your cert-manager deployment
+
+```yaml
+spec:
+ template:
+ spec:
+ containers:
+ - name: cert-manager-controller
+ ports:
+ - containerPort: 9402
+ name: http
+ protocol: TCP
+```
+
+2. Create the following `PodMonitor`
+
+```yaml
+apiVersion: monitoring.coreos.com/v1
+kind: PodMonitor
+metadata:
+ name: cert-manager
+ namespace: cert-manager
+ labels:
+ app: cert-manager
+ app.kubernetes.io/name: cert-manager
+ app.kubernetes.io/instance: cert-manager
+ app.kubernetes.io/component: "controller"
+spec:
+ jobLabel: app.kubernetes.io/name
+ selector:
+ matchLabels:
+ app: cert-manager
+ app.kubernetes.io/name: cert-manager
+ app.kubernetes.io/instance: cert-manager
+ app.kubernetes.io/component: "controller"
+ podMetricsEndpoints:
+ - port: http
+ honorLabels: true
+```
+
+## Monitoring Mixin
+
+Monitoring mixins are a way to bundle common alerts, rules, and dashboards for an application in a configurable and extensible way, using the Jsonnet data templating language. A cert-manager monitoring mixin can be found here https://gitlab.com/uneeq-oss/cert-manager-mixin. Documentation on usage can be found with the `cert-manager-mixin` project.
diff --git a/content/v1.13-docs/README.md b/content/v1.13-docs/README.md
new file mode 100644
index 0000000000..c53f1bc99f
--- /dev/null
+++ b/content/v1.13-docs/README.md
@@ -0,0 +1,26 @@
+---
+title: cert-manager
+description: cert-manager documentation homepage
+---
+
+cert-manager adds certificates and certificate issuers as resource types in
+Kubernetes clusters, and simplifies the process of obtaining, renewing and
+using those certificates.
+
+It can issue certificates from a variety of supported sources, including
+[Let's Encrypt](https://letsencrypt.org), [HashiCorp Vault](https://www.vaultproject.io),
+and [Venafi](https://www.venafi.com/) as well as private PKI.
+
+It will ensure certificates are valid and up to date, and attempt to
+renew certificates at a configured time before expiry.
+
+It is loosely based upon the work of
+[kube-lego](https://github.com/jetstack/kube-lego) and has borrowed some
+wisdom from other similar projects such as
+[kube-cert-manager](https://github.com/PalmStoneGames/kube-cert-manager).
+
+![High level overview diagram explaining cert-manager architecture](/images/high-level-overview.svg)
+
+This website provides the full technical documentation for the project, and can be
+used as a reference; if you feel that there's anything missing, please let us know
+or [raise a PR](https://github.com/cert-manager/website/pulls) to add it.
diff --git a/content/v1.13-docs/cli/README.md b/content/v1.13-docs/cli/README.md
new file mode 100644
index 0000000000..0d1a516335
--- /dev/null
+++ b/content/v1.13-docs/cli/README.md
@@ -0,0 +1,7 @@
+---
+title: CLI reference
+description: cert-manager CLI documentation
+---
+
+View the `--help` output from our various CLI tools, including those which run in containers in your cluster.
+This might help if you need to tweak an option or if you need to check which values are valid!
\ No newline at end of file
diff --git a/content/v1.13-docs/cli/acmesolver.md b/content/v1.13-docs/cli/acmesolver.md
new file mode 100644
index 0000000000..baee31aff4
--- /dev/null
+++ b/content/v1.13-docs/cli/acmesolver.md
@@ -0,0 +1,17 @@
+---
+title: acmesolver CLI reference
+description: "cert-manager acmesolver CLI documentation"
+---
+```
+HTTP server used to solve ACME challenges.
+
+Usage:
+ acmesolver [flags]
+
+Flags:
+ --domain string the domain name to verify
+ -h, --help help for acmesolver
+ --key string the challenge key to respond with
+ --listen-port int the port number to listen on for connections (default 8089)
+ --token string the challenge token to verify against
+```
diff --git a/content/v1.13-docs/cli/cainjector.md b/content/v1.13-docs/cli/cainjector.md
new file mode 100644
index 0000000000..0bcdf50014
--- /dev/null
+++ b/content/v1.13-docs/cli/cainjector.md
@@ -0,0 +1,45 @@
+---
+title: cainjector CLI reference
+description: "cert-manager cainjector CLI documentation"
+---
+```
+
+cert-manager CA injector is a Kubernetes addon to automate the injection of CA data into
+webhooks and APIServices from cert-manager certificates.
+
+It will ensure that annotated webhooks and API services always have the correct
+CA data from the referenced certificates, which can then be used to serve API
+servers and webhook servers.
+
+Usage:
+ ca-injector [flags]
+
+Flags:
+ --add_dir_header If true, adds the file directory to the header of the log messages
+ --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
+ --enable-profiling Enable profiling for cainjector
+ --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
+ AllAlpha=true|false (ALPHA - default=false)
+ AllBeta=true|false (BETA - default=false)
+ -h, --help help for ca-injector
+ --kubeconfig string Paths to a kubeconfig. Only required if out-of-cluster.
+ --leader-elect If true, cainjector will perform leader election between instances to ensure no more than one instance of cainjector operates at a time (default true)
+ --leader-election-lease-duration duration The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. This is only applicable if leader election is enabled. (default 1m0s)
+ --leader-election-namespace string Namespace used to perform leader election. Only used if leader election is enabled (default "kube-system")
+ --leader-election-renew-deadline duration The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. This is only applicable if leader election is enabled. (default 40s)
+ --leader-election-retry-period duration The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled. (default 15s)
+ --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+ --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
+ --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
+ --log_file string If non-empty, use this log file (no effect when -logtostderr=true)
+ --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
+ --logtostderr log to standard error instead of files (default true)
+ --namespace string If set, this limits the scope of cainjector to a single namespace. If set, cainjector will not update resources with certificates outside of the configured namespace.
+ --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
+ --profiler-address string Address of the Go profiler (pprof) if enabled. This should never be exposed on a public interface. (default "localhost:6060")
+ --skip_headers If true, avoid header prefixes in the log messages
+ --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
+ --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
+ -v, --v Level number for the log level verbosity
+ --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
+```
diff --git a/content/v1.13-docs/cli/cmctl.md b/content/v1.13-docs/cli/cmctl.md
new file mode 100644
index 0000000000..dff83b3bc2
--- /dev/null
+++ b/content/v1.13-docs/cli/cmctl.md
@@ -0,0 +1,30 @@
+---
+title: cmctl CLI reference
+description: "cert-manager cmctl CLI documentation"
+---
+```
+
+cmctl is a CLI tool manage and configure cert-manager resources for Kubernetes
+
+Usage: cmctl [command]
+
+Available Commands:
+ approve Approve a CertificateRequest
+ check Check cert-manager components
+ convert Convert cert-manager config files between different API versions
+ create Create cert-manager resources
+ deny Deny a CertificateRequest
+ experimental Interact with experimental features
+ help Help about any command
+ inspect Get details on certificate related resources
+ renew Mark a Certificate for manual renewal
+ status Get details on current status of cert-manager resources
+ upgrade Tools that assist in upgrading cert-manager
+ version Print the cert-manager CLI version and the deployed cert-manager version
+
+Flags:
+ -h, --help help for cmctl
+ --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+
+Use "cmctl [command] --help" for more information about a command.
+```
diff --git a/content/v1.13-docs/cli/controller.md b/content/v1.13-docs/cli/controller.md
new file mode 100644
index 0000000000..768ffb05cc
--- /dev/null
+++ b/content/v1.13-docs/cli/controller.md
@@ -0,0 +1,78 @@
+---
+title: controller CLI reference
+description: "cert-manager controller CLI documentation"
+---
+```
+
+cert-manager is a Kubernetes addon to automate the management and issuance of
+TLS certificates from various issuing sources.
+
+It will ensure certificates are valid and up to date periodically, and attempt
+to renew certificates at an appropriate time before expiry.
+
+Usage:
+ cert-manager-controller [flags]
+
+Flags:
+ --acme-http01-solver-image string The docker image to use to solve ACME HTTP01 challenges. You most likely will not need to change this parameter unless you are testing a new feature or developing cert-manager. (default "quay.io/jetstack/cert-manager-acmesolver:canary")
+ --acme-http01-solver-nameservers strings A list of comma separated dns server endpoints used for ACME HTTP01 check requests. This should be a list containing host and port, for example 8.8.8.8:53,8.8.4.4:53
+ --acme-http01-solver-resource-limits-cpu string Defines the resource limits CPU size when spawning new ACME HTTP01 challenge solver pods. (default "100m")
+ --acme-http01-solver-resource-limits-memory string Defines the resource limits Memory size when spawning new ACME HTTP01 challenge solver pods. (default "64Mi")
+ --acme-http01-solver-resource-request-cpu string Defines the resource request CPU size when spawning new ACME HTTP01 challenge solver pods. (default "10m")
+ --acme-http01-solver-resource-request-memory string Defines the resource request Memory size when spawning new ACME HTTP01 challenge solver pods. (default "64Mi")
+ --acme-http01-solver-run-as-non-root Defines the ability to run the http01 solver as root for troubleshooting issues (default true)
+ --add_dir_header If true, adds the file directory to the header of the log messages
+ --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
+ --auto-certificate-annotations strings The annotation consumed by the ingress-shim controller to indicate a ingress is requesting a certificate (default [kubernetes.io/tls-acme])
+ --cluster-issuer-ambient-credentials Whether a cluster-issuer may make use of ambient credentials for issuers. 'Ambient Credentials' are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the ClusterIssuer API object. When this flag is enabled, the following sources for credentials are also used: AWS - All sources the Go SDK defaults to, notably including any EC2 IAM roles available via instance metadata. (default true)
+ --cluster-resource-namespace string Namespace to store resources owned by cluster scoped resources such as ClusterIssuer in. This must be specified if ClusterIssuers are enabled. (default "kube-system")
+ --controllers strings A list of controllers to enable. '--controllers=*' enables all on-by-default controllers, '--controllers=foo' enables just the controller named 'foo', '--controllers=*,-foo' disables the controller named 'foo'.
+ All controllers: issuers, clusterissuers, certificates-metrics, ingress-shim, gateway-shim, orders, challenges, certificaterequests-issuer-acme, certificaterequests-approver, certificaterequests-issuer-ca, certificaterequests-issuer-selfsigned, certificaterequests-issuer-vault, certificaterequests-issuer-venafi, certificates-trigger, certificates-issuing, certificates-key-manager, certificates-request-manager, certificates-readiness, certificates-revision-manager (default [*])
+ --copied-annotation-prefixes strings Specify which annotations should/shouldn't be copiedfrom Certificate to CertificateRequest and Order, as well as from CertificateSigningRequest to Order, by passing a list of annotation key prefixes.A prefix starting with a dash(-) specifies an annotation that shouldn't be copied. Example: '*,-kubectl.kuberenetes.io/'- all annotationswill be copied apart from the ones where the key is prefixed with 'kubectl.kubernetes.io/'. (default [*,-kubectl.kubernetes.io/,-fluxcd.io/,-argocd.argoproj.io/])
+ --default-issuer-group string Group of the Issuer to use when the tls is requested but issuer group is not specified on the ingress resource. (default "cert-manager.io")
+ --default-issuer-kind string Kind of the Issuer to use when the tls is requested but issuer kind is not specified on the ingress resource. (default "Issuer")
+ --default-issuer-name string Name of the Issuer to use when the tls is requested but issuer name is not specified on the ingress resource.
+ --dns01-check-retry-period duration The duration the controller should wait between a propagation check. Despite the name, this flag is used to configure the wait period for both DNS01 and HTTP01 challenge propagation checks. For DNS01 challenges the propagation check verifies that a TXT record with the challenge token has been created. For HTTP01 challenges the propagation check verifies that the challenge token is served at the challenge URL.This should be a valid duration string, for example 180s or 1h (default 10s)
+ --dns01-recursive-nameservers strings A list of comma separated dns server endpoints used for DNS01 check requests. This should be a list containing host and port, for example 8.8.8.8:53,8.8.4.4:53
+ --dns01-recursive-nameservers-only When true, cert-manager will only ever query the configured DNS resolvers to perform the ACME DNS01 self check. This is useful in DNS constrained environments, where access to authoritative nameservers is restricted. Enabling this option could cause the DNS01 self check to take longer due to caching performed by the recursive nameservers.
+ --enable-certificate-owner-ref Whether to set the certificate resource as an owner of secret where the tls certificate is stored. When this flag is enabled, the secret will be automatically removed when the certificate resource is deleted.
+ --enable-profiling Enable profiling for controller.
+ --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
+ AdditionalCertificateOutputFormats=true|false (ALPHA - default=false)
+ AllAlpha=true|false (ALPHA - default=false)
+ AllBeta=true|false (BETA - default=false)
+ ExperimentalCertificateSigningRequestControllers=true|false (ALPHA - default=false)
+ ExperimentalGatewayAPISupport=true|false (ALPHA - default=false)
+ LiteralCertificateSubject=true|false (ALPHA - default=false)
+ ServerSideApply=true|false (ALPHA - default=false)
+ StableCertificateRequestName=true|false (ALPHA - default=false)
+ UseCertificateRequestBasicConstraints=true|false (ALPHA - default=false)
+ ValidateCAA=true|false (ALPHA - default=false)
+ -h, --help help for cert-manager-controller
+ --issuer-ambient-credentials Whether an issuer may make use of ambient credentials. 'Ambient Credentials' are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the Issuer API object. When this flag is enabled, the following sources for credentials are also used: AWS - All sources the Go SDK defaults to, notably including any EC2 IAM roles available via instance metadata.
+ --kube-api-burst int the maximum burst queries-per-second of requests sent to the Kubernetes apiserver (default 50)
+ --kube-api-qps float32 indicates the maximum queries-per-second requests to the Kubernetes apiserver (default 20)
+ --kubeconfig string Paths to a kubeconfig. Only required if out-of-cluster.
+ --leader-elect If true, cert-manager will perform leader election between instances to ensure no more than one instance of cert-manager operates at a time (default true)
+ --leader-election-lease-duration duration The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. This is only applicable if leader election is enabled. (default 1m0s)
+ --leader-election-namespace string Namespace used to perform leader election. Only used if leader election is enabled (default "kube-system")
+ --leader-election-renew-deadline duration The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. This is only applicable if leader election is enabled. (default 40s)
+ --leader-election-retry-period duration The duration the clients should wait between attempting acquisition and renewal of a leadership. This is only applicable if leader election is enabled. (default 15s)
+ --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
+ --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
+ --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
+ --log_file string If non-empty, use this log file (no effect when -logtostderr=true)
+ --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
+ --logtostderr log to standard error instead of files (default true)
+ --master string Optional apiserver host address to connect to. If not specified, autoconfiguration will be attempted.
+ --max-concurrent-challenges int The maximum number of challenges that can be scheduled as 'processing' at once. (default 60)
+ --metrics-listen-address string The host and port that the metrics endpoint should listen on. (default "0.0.0.0:9402")
+ --namespace string If set, this limits the scope of cert-manager to a single namespace and ClusterIssuers are disabled. If not specified, all namespaces will be watched
+ --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
+ --profiler-address string The host and port that Go profiler should listen on, i.e localhost:6060. Ensure that profiler is not exposed on a public address. Profiler will be served at /debug/pprof. (default "localhost:6060")
+ --skip_headers If true, avoid header prefixes in the log messages
+ --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
+ --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
+ -v, --v Level number for the log level verbosity
+ --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
+```
diff --git a/content/v1.13-docs/cli/webhook.md b/content/v1.13-docs/cli/webhook.md
new file mode 100644
index 0000000000..f4d6ef30c3
--- /dev/null
+++ b/content/v1.13-docs/cli/webhook.md
@@ -0,0 +1,51 @@
+---
+title: webhook CLI reference
+description: "cert-manager webhook CLI documentation"
+---
+```
+Webhook component providing API validation, mutation and conversion functionality for cert-manager (canary) ()
+
+Usage:
+ webhook [flags]
+
+Flags:
+ --add-dir-header If true, adds the file directory to the header of the log messages
+ --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
+ --api-server-host string Optional apiserver host address to connect to. If not specified, autoconfiguration will be attempted.
+ --config string Path to a file containing a WebhookConfiguration object used to configure the webhook
+ --dynamic-serving-ca-secret-name string name of the secret used to store the CA that signs serving certificates certificates
+ --dynamic-serving-ca-secret-namespace string namespace of the secret used to store the CA that signs serving certificates
+ --dynamic-serving-dns-names strings DNS names that should be present on certificates generated by the dynamic serving CA
+ --enable-profiling Enable profiling for webhook.
+ --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
+ AdditionalCertificateOutputFormats=true|false (ALPHA - default=false)
+ AllAlpha=true|false (ALPHA - default=false)
+ AllBeta=true|false (BETA - default=false)
+ ExperimentalCertificateSigningRequestControllers=true|false (ALPHA - default=false)
+ ExperimentalGatewayAPISupport=true|false (ALPHA - default=false)
+ LiteralCertificateSubject=true|false (ALPHA - default=false)
+ ServerSideApply=true|false (ALPHA - default=false)
+ StableCertificateRequestName=true|false (ALPHA - default=false)
+ UseCertificateRequestBasicConstraints=true|false (ALPHA - default=false)
+ ValidateCAA=true|false (ALPHA - default=false)
+ --healthz-port int port number to listen on for insecure healthz connections (default 6080)
+ -h, --help help for webhook
+ --kubeconfig string optional path to the kubeconfig used to connect to the apiserver. If not specified, in-cluster-config will be used
+ --log-backtrace-at traceLocation when logging hits line file:N, emit a stack trace (default :0)
+ --log-dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
+ --log-file string If non-empty, use this log file (no effect when -logtostderr=true)
+ --log-file-max-size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
+ --logtostderr log to standard error instead of files (default true)
+ --one-output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
+ --profiler-address string Address of the Go profiler (pprof). This should never be exposed on a public interface. If this flag is not set, the profiler is not run. (default "localhost:6060")
+ --secure-port int port number to listen on for secure TLS connections (default 6443)
+ --skip-headers If true, avoid header prefixes in the log messages
+ --skip-log-headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
+ --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
+ --tls-cert-file string path to the file containing the TLS certificate to serve with
+ --tls-cipher-suites strings Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be use. Possible values: TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_RC4_128_SHA
+ --tls-min-version string Minimum TLS version supported. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13
+ --tls-private-key-file string path to the file containing the TLS private key to serve with
+ -v, --v Level number for the log level verbosity
+ --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
+```
diff --git a/content/v1.13-docs/concepts/README.md b/content/v1.13-docs/concepts/README.md
new file mode 100644
index 0000000000..48ed7e2377
--- /dev/null
+++ b/content/v1.13-docs/concepts/README.md
@@ -0,0 +1,11 @@
+---
+title: Concepts
+description: cert-manager core concepts
+---
+
+There are several components and ideas that make up cert-manager. This section
+describes them on a conceptual level, to aid with understanding how cert-manager
+does its job.
+
+You probably don't want this section if you're just getting started; check out
+a [tutorial](../tutorials/README.md) instead.
\ No newline at end of file
diff --git a/content/v1.13-docs/concepts/acme-orders-challenges.md b/content/v1.13-docs/concepts/acme-orders-challenges.md
new file mode 100644
index 0000000000..80c31606e4
--- /dev/null
+++ b/content/v1.13-docs/concepts/acme-orders-challenges.md
@@ -0,0 +1,100 @@
+---
+title: ACME Orders and Challenges
+description: 'cert-manager core concepts: ACME Orders and Challenges'
+---
+
+cert-manager supports requesting certificates from ACME servers, including from
+[Let's Encrypt](https://letsencrypt.org/), with use of the [ACME
+Issuer](../configuration/acme/README.md). These certificates are typically trusted on
+the public Internet by most computers. To successfully request a certificate,
+cert-manager must solve ACME Challenges which are completed in order to prove
+that the client owns the DNS addresses that are being requested.
+
+In order to complete these challenges, cert-manager introduces two
+`CustomResource` types; `Orders` and `Challenges`.
+
+## Orders
+
+`Order` resources are used by the ACME issuer to manage the lifecycle of an ACME
+'order' for a signed TLS certificate. More details on ACME orders and domain
+validation can be found on the Let's Encrypt website
+[here](https://letsencrypt.org/how-it-works/). An order represents a single
+certificate request which will be created automatically once a new
+[`CertificateRequest`](./certificaterequest.md) resource referencing an ACME
+issuer has been created. `CertificateRequest` resources are created
+automatically by cert-manager once a [`Certificate`](./certificate.md) resource
+is created, has its specification changed, or needs renewal.
+
+As an end-user, you will never need to manually create an `Order` resource.
+Once created, an `Order` cannot be changed. Instead, a new `Order` resource must
+be created.
+
+The `Order` resource encapsulates multiple ACME 'challenges' for that 'order',
+and as such, will manage one or more `Challenge` resources.
+
+## Challenges
+
+`Challenge` resources are used by the ACME issuer to manage the lifecycle of an
+ACME 'challenge' that must be completed in order to complete an 'authorization'
+for a single DNS name/identifier.
+
+When an `Order` resource is created, the order controller will create
+`Challenge` resources for each DNS name that is being authorized with the ACME
+server.
+
+As an end-user, you will never need to manually create a `Challenge` resource.
+Once created, a `Challenge` cannot be changed. Instead, a new `Challenge`
+resource must be created.
+
+### Challenge Lifecycle
+
+After a `Challenge` resource has been created, it will be initially queued for
+processing. Processing will not begin until the challenge has been 'scheduled'
+to start. This scheduling process prevents too many challenges being attempted
+at once, or multiple challenges for the same DNS name being attempted at once.
+For more information on how challenges are scheduled, read the [challenge
+scheduling](#challenge-scheduling).
+
+Once a challenge has been scheduled, it will first be 'synced' with the ACME
+server in order to determine its current state. If the challenge is already
+valid, its 'state' will be updated to 'valid', and will also set
+`status.processing = false` to 'unschedule' itself.
+
+If the challenge is still 'pending', the challenge controller will 'present' the
+challenge using the configured solver, one of HTTP01 or DNS01. Once the
+challenge has been 'presented', it will set `status.presented = true`.
+
+Once 'presented', the challenge controller will perform a 'self check' to
+ensure that the challenge has 'propagated' (i.e. the authoritative DNS servers
+have been updated to respond correctly, or the changes to the ingress resources
+have been observed and in-use by the ingress controller).
+
+If the self check fails, cert-manager will retry the self check with a fixed 10
+second retry interval. Challenges that do not ever complete the self check will
+continue retrying until the user intervenes by either retrying the `Order` (by
+deleting the `Order` resource) or amending the associated `Certificate` resource
+to resolve any configuration errors.
+
+Once the self check is passing, the ACME 'authorization' associated with this
+challenge will be 'accepted'.
+
+The final state of the authorization after accepting it will be copied across to
+the Challenge's `status.state` field, as well as the 'error reason' if an error
+occurred whilst the ACME server attempted to validate the challenge.
+
+Once a Challenge has entered the `valid`, `invalid`, `expired` or `revoked`
+state, it will set `status.processing = false` to prevent any further processing
+of the ACME challenge, and to allow another challenge to be scheduled if there
+is a backlog of challenges to complete.
+
+### Challenge Scheduling
+
+Instead of attempting to process all challenges at once, challenges are
+'scheduled' by cert-manager.
+
+This scheduler applies a cap on the maximum number of simultaneous challenges
+as well as disallows two challenges for the same DNS name and solver type
+(`HTTP01` or `DNS01`) to be completed at once.
+
+The maximum number of challenges that can be processed at a time is 60 as of
+[`ddff78`](https://github.com/cert-manager/cert-manager/blob/ddff78f011558e64186d61f7c693edced1496afa/pkg/controller/acmechallenges/scheduler/scheduler.go#L31-L33).
\ No newline at end of file
diff --git a/content/v1.13-docs/concepts/ca-injector.md b/content/v1.13-docs/concepts/ca-injector.md
new file mode 100644
index 0000000000..2c7c8dd638
--- /dev/null
+++ b/content/v1.13-docs/concepts/ca-injector.md
@@ -0,0 +1,234 @@
+---
+title: CA Injector
+description: 'cert-manager core concepts: CA Injector'
+---
+
+`cainjector` helps to configure the CA certificates for:
+[Mutating Webhooks],
+[Validating Webhooks]
+[Conversion Webhooks] and [API Services]
+
+In particular, `cainjector` populates the `caBundle` field of four API types:
+`ValidatingWebhookConfiguration`,
+`MutatingWebhookConfiguration`
+`CustomResourceDefinition` and `APIService`.
+The first three resource types are used to configure how the Kubernetes API server connects to webhooks.
+This `caBundle` data is loaded by the Kubernetes API server and used to verify the serving certificates of webhook API servers.
+`APIService` is used to represent an [Extension API Server]. `caBundle` of `APIService` can be populated with CA cert that can be used to validate the API server's serving certificate.
+
+We will refer to these four API types as *injectable* resources.
+
+
+An *injectable* resource MUST have one of these annotations:
+`cert-manager.io/inject-ca-from`,
+`cert-manager.io/inject-ca-from-secret`, or
+`cert-manager.io/inject-apiserver-ca`, depending on the injection *source*.
+This is explained in more detail below.
+
+`cainjector` copies CA data from one of three *sources*:
+a Kubernetes `Secret`,
+a cert-manager `Certificate`, or from
+the Kubernetes API server CA certificate (which `cainjector` itself uses to verify its TLS connection to the Kubernetes API server).
+
+If the *source* is a Kubernetes `Secret`, that resource MUST also have an `cert-manager.io/allow-direct-injection: "true"` annotation.
+The three *source* types are explained in more detail below.
+
+
+## Examples
+
+Here are examples demonstrating how to use the three `cainjector` *sources*.
+In each case we use `ValidatingWebhookConfiguration` as the *injectable*,
+but you can substitute `MutatingWebhookConfiguration` or `CustomResourceDefinition` definition instead.
+
+### Injecting CA data from a Certificate resource
+
+Here is an example of a `ValidatingWebhookConfiguration`
+configured with the annotation `cert-manager.io/inject-ca-from`,
+which will make `cainjector` populate the `caBundle` field using CA data from a cert-manager `Certificate`.
+
+NOTE: This example does not deploy a webhook server,
+it only deploys a partial webhook configuration,
+but it should be sufficient to help you understand what `cainjector` does:
+
+```yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: example1
+
+---
+
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: webhook1
+ annotations:
+ cert-manager.io/inject-ca-from: example1/webhook1-certificate
+webhooks:
+- name: webhook1.example.com
+ admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook1
+ namespace: example1
+ path: /validate
+ port: 443
+ sideEffects: None
+
+---
+
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: webhook1-certificate
+ namespace: example1
+spec:
+ secretName: webhook1-certificate
+ dnsNames:
+ - webhook1.example1
+ issuerRef:
+ name: selfsigned
+
+---
+
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: selfsigned
+ namespace: example1
+spec:
+ selfSigned: {}
+```
+
+You should find that the `caBundle` value is now identical to the CA value in the `Secret` for the `Certificate`:
+
+```
+kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io webhook1 -o yaml | grep caBundle
+kubectl -n example1 get secret webhook1-certificate -o yaml | grep ca.crt
+```
+
+And after a short time, the Kubernetes API server will read that new `caBundle` value and use it to verify a TLS connection to the webhook server.
+
+### Injecting CA data from a Secret resource
+
+Here is another example of a `ValidatingWebhookConfiguration`
+this time configured with the annotation `cert-manager.io/inject-ca-from-secret`,
+which will make `cainjector` populate the `caBundle` field using CA data from a Kubernetes `Secret`.
+
+NOTE: This example does not deploy a webhook server,
+it only deploys a partial webhook configuration,
+but it should be sufficient to help you understand what `cainjector` does:
+
+```yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: example2
+
+---
+
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: webhook2
+ annotations:
+ cert-manager.io/inject-ca-from-secret: example2/example-ca
+webhooks:
+- name: webhook2.example.com
+ admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook2
+ namespace: example2
+ path: /validate
+ port: 443
+ sideEffects: None
+
+---
+
+apiVersion: v1
+kind: Secret
+metadata:
+ name: example-ca
+ namespace: example2
+ annotations:
+ cert-manager.io/allow-direct-injection: "true"
+type: kubernetes.io/tls
+data:
+ ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5akNDQWQ2Z0F3SUJBZ0lRTkdJZ24yM3BQYVpNbk9MUjJnVmZHakFOQmdrcWhraUc5dzBCQVFzRkFEQVYKTVJNd0VRWURWUVFERXdwRmVHRnRjR3hsSUVOQk1CNFhEVEl3TURreU5ERTFOREEwTVZvWERUSXdNVEl5TXpFMQpOREEwTVZvd0ZURVRNQkVHQTFVRUF4TUtSWGhoYlhCc1pTQkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBS2F3RzVoMzlreHdyNEl0WCtHaDNYVWQrdTVJc2ZlSFdoTTc4TTRQTmZFeXhQMXoKRmNLN1d0MHJFMkwwNUppYmQ4ZjNpb3k5OXNnQ3I4OEw2SWxYZTB0RnkzNysxenJ4TFluR2hDQnZzZjltd0hLbgpIVTEvNERwQjROZkhPbFllNE9tbHVoNE9HdmZINU1EbDh5OWZGMjhXRXVBQ2dwdmpCUWxvRDNlVjJ5UmJvQ2kyCmtSTDJWYTFZL0FQZEpWK21VYkFvZmg0bllmUmNLRTJsSUg0RG5ZdXFPU3JaaituZUQ2M2RTSktxcHQ5K2luN2YKNHljZ2pQYU93MmdyKzhLK291QTlSQTV1VDI3SVNJcUJDcEV6elRqbVBUUWNvUTYxZGF0aDZkc1lsTEU4aWZWUwp4RWZuVEdQKy94M0FXQXR4eU5lanVuZGFXbVNFL3h5OHh0K0FxblVDQXdFQUFhTkNNRUF3RGdZRFZSMFBBUUgvCkJBUURBZ0trTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkowNkc5eEc2V1VBTHB6T3JYaHAKV2dsTm5qMkFNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUI3ZG9CZnBLR3o4VlRQSnc0YXhpdisybzJpMHE1SQpSRzU2UE81WnhKQktZQlRROElHQmFOSm1yeGtmNTJCV0ttUGp4cXlNSGRwWjVBU00zOUJkZVUzRGtEWHp4RkgwCjM5RU12UnhIUERyMGQ4cTFFbndQT0xZY1hzNjJhYjdidE11cTJUMFNNZzRYMkY5VmNKTW5YdjlrNnA0VGZNR3MKVThCQnJhVGhUZm53ejBsWXMyblFjdzNmZjZ1bG1wWlk4K3BTak1aVDNJZHZOMFA4Y2hOdUlmUFRHWDJmSlo2NQpxcUUrelRoU3hIeXFTOTVoczhsd1lRRUhGQlVsalRnMCtQZThXL0hOSXZBOU9TYWw1U3UvdlhydmcxN04xdHVyCk5XcWRyZU5OVm1ubXMvTFJodmthWTBGblRvbFNBRkNXWS9GSDY5ZzRPcThiMHVyK3JVMHZOZFFXCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+ tls.key: ""
+ tls.crt: ""
+```
+
+You should find that the `caBundle` value is now identical to the `ca.crt` value in the `Secret`:
+
+```
+kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io webhook2 -o yaml | grep caBundle
+```
+
+And after a short time, the Kubernetes API server will read that new `caBundle` value and use it to verify a TLS connection to the webhook server.
+
+This `Secret` based injection mechanism can operate independently of the `Certificate` based mechanism described earlier.
+It will work without the cert-manager CRDs installed
+and it will work if the cert-manager CRDs and associated webhook servers are not yet configured.
+
+NOTE: For this reason, cert-manager uses the `Secret` based injection mechanism to bootstrap its own webhook server.
+The cert-manager webhook server generates its own private key and self-signed certificate and places them in a `Secret` when it starts up.
+
+### Injecting the Kubernetes API Server CA
+
+Here is another example of a `ValidatingWebhookConfiguration`
+this time configured with the annotation `cert-manager.io/inject-apiserver-ca: "true"`,
+which will make `cainjector` populate the `caBundle` field using the same CA certificate used by the Kubernetes API server.
+
+NOTE: This example does not deploy a webhook server,
+it only deploys a partial webhook configuration,
+but it should be sufficient to help you understand what `cainjector` does:
+
+```yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: example3
+
+---
+
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: webhook3
+ annotations:
+ cert-manager.io/inject-apiserver-ca: "true"
+webhooks:
+- name: webhook3.example.com
+ admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook3
+ namespace: example3
+ path: /validate
+ port: 443
+ sideEffects: None
+
+```
+
+You should find that the `caBundle` value is now identical to the CA used in your `KubeConfig` file:
+
+```
+kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io webhook3 -o yaml | grep caBundle
+kubectl config view --minify --raw | grep certificate-authority-data
+```
+
+And after a short time, the Kubernetes API server will read that new `caBundle` value and use it to verify a TLS connection to the webhook server.
+
+NOTE: In this case you will have to ensure that your webhook is configured to serve a TLS certificate that has been signed by the Kubernetes cluster CA.
+The disadvantages of this mechanism are that: you will require access to the private key of the Kubernetes cluster CA and you will need to manually rotate the webhook certificate.
+
+[Validating Webhooks]: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook
+[Mutating Webhooks]: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook
+[Conversion Webhooks]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#webhook-conversion
+[API Services]: https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/
+[Extension API Server]: https://kubernetes.io/docs/tasks/extend-kubernetes/setup-extension-api-server/
\ No newline at end of file
diff --git a/content/v1.13-docs/concepts/certificate.md b/content/v1.13-docs/concepts/certificate.md
new file mode 100644
index 0000000000..3d8ca12198
--- /dev/null
+++ b/content/v1.13-docs/concepts/certificate.md
@@ -0,0 +1,106 @@
+---
+title: Certificate
+description: 'cert-manager core concepts: Certificates'
+---
+
+cert-manager has the concept of `Certificates` that define a desired X.509
+certificate which will be renewed and kept up to date. A `Certificate` is a
+namespaced resource that references an `Issuer` or `ClusterIssuer` that
+determine what will be honoring the certificate request.
+
+When a `Certificate` is created, a corresponding `CertificateRequest` resource
+is created by cert-manager containing the encoded X.509 certificate request,
+`Issuer` reference, and other options based upon the specification of the
+`Certificate` resource.
+
+Here is one such example of a `Certificate` resource.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: acme-crt
+spec:
+ secretName: acme-crt-secret
+ dnsNames:
+ - example.com
+ - foo.example.com
+ issuerRef:
+ name: letsencrypt-prod
+ # We can reference ClusterIssuers by changing the kind here.
+ # The default value is Issuer (i.e. a locally namespaced Issuer)
+ kind: Issuer
+ group: cert-manager.io
+```
+
+This `Certificate` will tell cert-manager to attempt to use the `Issuer` named
+`letsencrypt-prod` to obtain a certificate key pair for the `example.com` and
+`foo.example.com` domains. If successful, the resulting TLS key and certificate
+will be stored in a secret named `acme-crt-secret`, with keys of `tls.key`, and
+`tls.crt` respectively. This secret will live in the same namespace as the
+`Certificate` resource.
+
+When a certificate is issued by an intermediate CA and the `Issuer` can provide
+the issued certificate's chain, the contents of `tls.crt` will be the requested
+certificate followed by the certificate chain.
+
+Additionally, if the Certificate Authority is known, the corresponding CA
+certificate will be stored in the secret with key `ca.crt`. For example, with
+the ACME issuer, the CA is not known and `ca.crt` will not exist in
+`acme-crt-secret`.
+
+cert-manager intentionally avoids adding root certificates to `tls.crt`, because they
+are useless in a situation where TLS is being done securely. For more information,
+see [RFC 5246 section 7.4.2](https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.2)
+which contains the following explanation:
+
+> Because certificate validation requires that root keys be distributed
+> independently, the self-signed certificate that specifies the root
+> certificate authority MAY be omitted from the chain, under the
+> assumption that the remote end must already possess it in order to
+> validate it in any case.
+
+
+
+When configuring a client to connect to a TLS server with a serving certificate that is signed by a private CA,
+you will need to provide the client with the CA certificate in order for it to verify the server.
+`ca.crt` will likely contain the certificate you need to trust,
+but __do not mount the same `Secret` as the server__ to access `ca.crt`.
+This is because:
+
+1. That `Secret` also contains the private key of the server, which should only be accessible to the server.
+ You should use RBAC to ensure that the `Secret` containing the serving certificate and private key are only accessible to Pods that need it.
+2. Rotating CA certificates safely relies on being able to have both the old and new CA certificates trusted at the same time.
+ By consuming the CA directly from the source, this isn't possible;
+ you'll be _forced_ to have some down-time in order to rotate certificates.
+
+When configuring the client you should independently choose and fetch the CA certificates that you want to trust.
+Download the CA out of band and store it in a `Secret` or `ConfigMap` separate from the `Secret` containing the server's private key and certificate.
+
+This ensures that if the material in the `Secret` containing the server key and certificate is tampered with,
+the client will fail to connect to the compromised server.
+
+The same concept also applies when configuring a server for mutually-authenticated TLS;
+don't give the server access to Secret containing the client certificate and private key.
+
+
+
+The `dnsNames` field specifies a list of [`Subject Alternative
+Names`](https://en.wikipedia.org/wiki/Subject_Alternative_Name) to be associated
+with the certificate.
+
+The referenced `Issuer` must exist in the same namespace as the `Certificate`.
+A `Certificate` can alternatively reference a `ClusterIssuer` which is
+non-namespaced and so can be referenced from any namespace.
+
+You can read more on how to configure your `Certificate` resources
+[here](../usage/certificate.md).
+
+## Certificate Lifecycle
+
+This diagram shows the lifecycle of a Certificate named `cert-1` using an
+ACME / Let's Encrypt issuer. You don't need to understand all of these steps
+to use cert-manager; this is more of an explanation of the logic which happens
+under the hood for those curious about the process.
+
+![Life of a Certificate](/images/letsencrypt-flow-cert-manager.png)
\ No newline at end of file
diff --git a/content/v1.13-docs/concepts/certificaterequest.md b/content/v1.13-docs/concepts/certificaterequest.md
new file mode 100644
index 0000000000..5dbc1ca546
--- /dev/null
+++ b/content/v1.13-docs/concepts/certificaterequest.md
@@ -0,0 +1,261 @@
+---
+title: CertificateRequest
+description: 'cert-manager core concepts: CertificateRequests'
+---
+
+The `CertificateRequest` is a namespaced resource in cert-manager that is used
+to request X.509 certificates from an [`Issuer`](./issuer.md). The resource
+contains a base64 encoded string of a PEM encoded certificate request which is
+sent to the referenced issuer. A successful issuance will return a signed
+certificate, based on the certificate signing request. `CertificateRequests` are
+typically consumed and managed by controllers or other systems and should not be
+used by humans - unless specifically needed.
+
+A simple `CertificateRequest` looks like the following:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: CertificateRequest
+metadata:
+ name: my-ca-cr
+spec:
+ request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQzNqQ0NBY1lDQVFBd2daZ3hDekFKQmdOVkJBWVRBbHBhTVE4d0RRWURWUVFJREFaQmNHOXNiRzh4RFRBTApCZ05WQkFjTUJFMXZiMjR4RVRBUEJnTlZCQW9NQ0VwbGRITjBZV05yTVJVd0V3WURWUVFMREF4alpYSjBMVzFoCmJtRm5aWEl4RVRBUEJnTlZCQU1NQ0dwdmMyaDJZVzVzTVN3d0tnWUpLb1pJaHZjTkFRa0JGaDFxYjNOb2RXRXUKZG1GdWJHVmxkWGRsYmtCcVpYUnpkR0ZqYXk1cGJ6Q0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQwpBUW9DZ2dFQkFLd01tTFhuQkNiRStZdTIvMlFtRGsxalRWQ3BvbHU3TlZmQlVFUWl1bDhFMHI2NFBLcDRZQ0c5Cmx2N2kwOHdFMEdJQUgydnJRQmxVd3p6ZW1SUWZ4YmQvYVNybzRHNUFBYTJsY2NMaFpqUlh2NEVMaER0aVg4N3IKaTQ0MWJ2Y01OM0ZPTlRuczJhRkJYcllLWGxpNG4rc0RzTEVuZmpWdXRiV01Zeis3M3ptaGZzclRJUjRzTXo3cQpmSzM2WFM4UkRjNW5oVVcyYU9BZ3lnbFZSOVVXRkxXNjNXYXVhcHg2QUpBR1RoZnJYdVVHZXlZUUVBSENxZmZmCjhyOEt3YTFYK1NwYm9YK1ppSVE0Nk5jQ043OFZnL2dQVHNLZmphZURoNWcyNlk1dEVidHd3MWdRbWlhK0MyRHIKWHpYNU13RzJGNHN0cG5kUnRQckZrU1VnMW1zd0xuc0NBd0VBQWFBQU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQgpBUUFXR0JuRnhaZ0gzd0N3TG5IQ0xjb0l5RHJrMUVvYkRjN3BJK1VVWEJIS2JBWk9IWEFhaGJ5RFFLL2RuTHN3CjJkZ0J3bmlJR3kxNElwQlNxaDBJUE03eHk5WjI4VW9oR3piN0FVakRJWHlNdmkvYTJyTVhjWjI1d1NVQmxGc28Kd005dE1QU2JwcEVvRERsa3NsOUIwT1BPdkFyQ0NKNnZGaU1UbS9wMUJIUWJSOExNQW53U0lUYVVNSFByRzJVMgpjTjEvRGNMWjZ2enEyeENjYVoxemh2bzBpY1VIUm9UWmV1ZEp6MkxmR0VHM1VOb2ppbXpBNUZHd0RhS3BySWp3ClVkd1JmZWZ1T29MT1dNVnFNbGRBcTlyT24wNHJaT3Jnak1HSE9tTWxleVdPS1AySllhaDNrVDdKU01zTHhYcFYKV0ExQjRsLzFFQkhWeGlKQi9Zby9JQWVsCi0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
+ isCA: false
+ usages:
+ - signing
+ - digital signature
+ - server auth
+ # 90 days
+ duration: 2160h
+ 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
+ group: cert-manager.io
+```
+
+This `CertificateRequest` will make cert-manager attempt to request the `Issuer`
+`ca-issuer` in the default issuer group `cert-manager.io`, return a
+certificate based upon the certificate signing request. Other groups can be
+specified inside the `issuerRef` which will change the targeted issuer to other
+external, third party issuers you may have installed.
+
+The resource also exposes the option for stating the certificate as CA, Key
+Usages, and requested validity duration.
+
+All fields within the `spec` of the `CertificateRequest`, as well as any managed
+cert-manager annotations, are immutable and cannot be modified after creation.
+
+A successful issuance of the certificate signing request will cause an update to
+the resource, setting the status with the signed certificate, the CA of the
+certificate (if available), and setting the `Ready` condition to `True`.
+
+Whether issuance of the certificate signing request was successful or not, a retry of the
+issuance will _not_ happen. It is the responsibility of some other controller to
+manage the logic and life cycle of `CertificateRequests`.
+
+## Conditions
+`CertificateRequests` have a set of strongly defined conditions that should be
+used and relied upon by controllers or services to make decisions on what
+actions to take next on the resource.
+
+### Ready
+Each ready condition consists of the pair `Ready` - a boolean value, and
+`Reason` - a string. The set of values and meanings are as follows:
+
+| Ready | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| False | Pending | The `CertificateRequest` is currently pending, waiting for some other operation to take place. This could be that the `Issuer` does not exist yet or the `Issuer` is in the process of issuing a certificate. |
+| False | Failed | The certificate has failed to be issued - either the returned certificate failed to be decoded or an instance of the referenced issuer used for signing failed. No further action will be taken on the `CertificateRequest` by its controller and it can be considered terminally failed. |
+| True | Issued | A signed certificate has been successfully issued by the referenced `Issuer`. |
+
+This condition should be set by the issuer.
+
+### Denied
+| Denied | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| True | \ | The `CertificateRequest` was Denied by an approver. This `CertificateRequest` can be considered terminally failed.
+
+This condition should only be set by an approver.
+
+### Approved
+| Approved | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| True | \ | The `CertificateRequest` was approved by the approver. This `CertificateRequest` is approved and can be issued by the issuer.
+
+This condition should only be set by an approver.
+
+### InvalidRequest
+| InvalidRequest | Reason | Condition Meaning |
+| ----- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| True | \ | The `CertificateRequest` is invalid. This `CertificateRequest` can be considered terminally failed.
+
+
+## UserInfo
+
+`CertificateRequests` include a set of `UserInfo` fields as part of the spec,
+namely: `username`, `groups`, `uid`, and `extra`. These values contain the user
+who created the `CertificateRequest`. This user will be cert-manager itself in
+the case that the `CertificateRequest` was created by a
+[`Certificate`](./certificate.md) resource, or instead the user who created the
+`CertificateRequest` directly.
+
+> **Warning**: These fields are managed by cert-manager and should _never_ be
+> set or modified by anything else. When the `CertificateRequest` is created,
+> these fields will be overridden, and any request attempting to modify them
+> will be rejected.
+
+
+### Approval
+CertificateRequests can be `Approved` or `Denied`. These mutually exclusive
+conditions gate a CertificateRequest from being signed by its managed signer.
+
+- A signer should _not_ sign a managed CertificateRequest without an Approved condition
+- A signer _will_ sign a managed CertificateRequest with an Approved condition
+- A signer will _never_ sign a managed CertificateRequest with a Denied condition
+
+These conditions are _permanent_, and cannot be modified or changed once set.
+
+```bash
+NAMESPACE NAME APPROVED DENIED READY ISSUER REQUESTOR AGE
+istio-system service-mesh-ca-whh5b True True mesh-ca system:serviceaccount:istio-system:istiod 16s
+istio-system my-app-fj9sa True mesh-ca system:serviceaccount:my-app:my-app 4s
+```
+
+
+#### Behavior
+
+The Approved and Denied conditions are two distinct condition types on the
+CertificateRequest. These conditions must only have the status of True, and
+are mutually exclusive (i.e. a CertificateRequest cannot have an Approved and
+Denied condition simultaneously). This behavior is enforced in the cert-manager
+validating admission webhook.
+
+An "approver" is an entity that is responsible for setting the Approved/Denied
+conditions. It is up to the approver's implementation as to what
+CertificateRequests are managed by that approver.
+
+The Reason field of the Approved/Denied condition should be set to *who* set the
+condition. Who can be interpreted however makes sense to the approver
+implementation. For example, it may include the API group of an approving policy
+controller, or the client agent of a manual request.
+
+The Message field of the Approved/Denied condition should be set to *why* the
+condition is set. Again, why can be interpreted however makes sense to the
+implementation of the approver. For example, the name of the resource that
+approves this request, the violations which caused the request to be denied, or
+the team to who manually approved the request.
+
+
+#### Approver Controller
+
+By default, cert-manager will run an internal approval controller which will
+automatically approve _all_ CertificateRequests that reference any internal
+issuer type in any namespace: `cert-manager.io/Issuer`,
+`cert-manager.io/ClusterIssuer`.
+
+To disable this controller, add the following argument to the
+cert-manager-controller: `--controllers=*,-certificaterequests-approver`. This
+can be achieved with helm by appending:
+
+```bash
+--set extraArgs={--controllers='*\,-certificaterequests-approver'}
+```
+
+Alternatively, in order for the internal approver controller to approve
+CertificateRequests that reference an external issuer, add the following RBAC to
+the cert-manager-controller Service Account. Please replace the given resource
+names with the relevant names:
+
+```yaml
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: cert-manager-controller-approve:my-issuer-example-com # edit
+rules:
+- apiGroups:
+ - cert-manager.io
+ resources:
+ - signers
+ verbs:
+ - approve
+ resourceNames:
+ - issuers.my-issuer.example.com/* # edit
+ - clusterissuers.my-issuer.example.com/* # edit
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: cert-manager-controller-approve:my-issuer-example-com # edit
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cert-manager-controller-approve:my-issuer-example-com # edit
+subjects:
+- kind: ServiceAccount
+ name: cert-manager
+ namespace: cert-manager
+```
+
+#### RBAC Syntax
+
+When a user or controller attempts to approve or deny a CertificateRequest, the
+cert-manager webhook will evaluate whether it has sufficient permissions to do
+so. These permissions are based upon the request
+itself- specifically the request's IssuerRef:
+
+```yaml
+apiGroups: ["cert-manager.io"]
+resources: ["signers"]
+verbs: ["approve"]
+resourceNames:
+ # namesapced signers
+ - "./."
+ # cluster scoped signers
+ - "./"
+ # all signers of this resource name
+ - "./*"
+```
+
+An example ClusterRole that would grant the permissions to set the Approve and
+Denied conditions of CertificateRequests that reference the cluster scoped
+`myissuers` external issuer, in the group `my-example.io`, with the name `myapp`:
+
+```yaml
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: my-example-io-my-issuer-myapp-approver
+rules:
+ - apiGroups: ["cert-manager.io"]
+ resources: ["signers"]
+ verbs: ["approve"]
+ resourceNames: ["myissuers.my-example.io/myapp"]
+```
+
+If the approver does not have sufficient permissions defined above to set the
+Approved or Denied conditions, the request will be rejected by the cert-manager
+validating admission webhook.
+
+- The RBAC permissions *must* be granted at the cluster scope
+- Namespaced signers are represented by a namespaced resource using the syntax of `./.`
+- Cluster scoped signers are represented using the syntax of `./`
+- An approver can be granted approval for all namespaces via `./*`
+- The apiGroup must *always* be `cert-manager.io`
+- The resource must *always* be `signers`
+- The verb must *always* be `approve`, which grants the approver the permissions to set *both* Approved and Denied conditions
+
+An example of signing all `myissuer` signers in all namespaces, and
+`clustermyissuers` with the name `myapp`, in the `my-example.io` group:
+
+```yaml
+ resourceNames: ["myissuers.my-example.io/*", "clustermyissuers.my-example.io/myapp"]
+```
+
+An example of signing `myissuer` with the name `myapp` in the namespaces `foo`
+and `bar`:
+
+```yaml
+ resourceNames: ["myissuers.my-example.io/foo.myapp", "myissuers.my-example.io/bar.myapp"]
+```
\ No newline at end of file
diff --git a/content/v1.13-docs/concepts/issuer.md b/content/v1.13-docs/concepts/issuer.md
new file mode 100644
index 0000000000..6293369992
--- /dev/null
+++ b/content/v1.13-docs/concepts/issuer.md
@@ -0,0 +1,44 @@
+---
+title: Issuer
+description: 'cert-manager core concepts: Issuers and ClusterIssuers'
+---
+
+`Issuers`, and `ClusterIssuers`, are Kubernetes resources that represent
+certificate authorities (CAs) that are able to generate signed certificates by honoring
+certificate signing requests. All cert-manager certificates require a referenced
+issuer that is in a ready condition to attempt to honor the request.
+
+An example of an `Issuer` type is `CA`. A simple `CA` `Issuer` is as follows:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: ca-issuer
+ namespace: mesh-system
+spec:
+ ca:
+ secretName: ca-key-pair
+```
+
+This is a simple `Issuer` that will sign certificates based on a private key.
+The certificate stored in the secret `ca-key-pair` can then be used to trust
+newly signed certificates by this `Issuer` in a Public Key Infrastructure (PKI)
+system.
+
+## Namespaces
+
+An `Issuer` is a namespaced resource, and it is not possible to issue
+certificates from an `Issuer` in a different namespace. This means you will need
+to create an `Issuer` in each namespace you wish to obtain `Certificates` in.
+
+If you want to create a single `Issuer` that can be consumed in multiple
+namespaces, you should consider creating a `ClusterIssuer` resource. This is
+almost identical to the `Issuer` resource, however is non-namespaced so it
+can be used to issue `Certificates` across all namespaces.
+
+## Supported Issuers
+
+cert-manager supports a number of 'in-tree', as well as 'out-of-tree' `Issuer`
+types. An exhaustive list of these `Issuer` types can be found in the
+cert-manager [configuration documentation](../configuration/README.md).
diff --git a/content/v1.13-docs/concepts/webhook.md b/content/v1.13-docs/concepts/webhook.md
new file mode 100644
index 0000000000..1bcbbee769
--- /dev/null
+++ b/content/v1.13-docs/concepts/webhook.md
@@ -0,0 +1,80 @@
+---
+title: All About the cert-manager Webhook
+description: |
+ Learn about the webhook component of cert-manager, which validates, converts and sets default values for the cert-manager custom resources
+---
+
+cert-manager extends the Kubernetes API using Custom Resource Definitions.
+It installs a webhook which has three main functions:
+
+- [Validation](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook):
+ Ensures that when cert-manager resources are created or updated, they conform
+ to the rules of the API. This validation is more in depth than for example
+ ensuring resources conform to the OpenAPI schema, but instead contains logic such as
+ not allowing to specify more than one `Issuer` type per `Issuer` resource. The
+ validating admission is always called and will respond with a success or
+ failed response.
+- [Mutation / Defaulting](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook):
+ Changes the contents of resources during create and update operations, for
+ example to set default values.
+- [Conversion](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#webhook-conversion):
+ The webhook is also responsible for implementing a conversion over versions
+ in the cert-manager `CustomResources` (`cert-manager.io`). This means that
+ multiple API versions can be supported simultaneously; from `v1alpha2` through to `v1`.
+ This makes it possible to rely on a particular version of our
+ configuration schema.
+
+> ℹ️ This is known as Dynamic Admission Control.
+> Read more about [Dynamic Admission Control](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) in the Kubernetes documentation.
+
+## Overview
+
+The webhook component is deployed as another pod that runs alongside the main
+cert-manager controller and CA injector components.
+
+In order for the API server to communicate with the webhook component, the
+webhook requires a TLS certificate that the apiserver is configured to trust.
+
+The [`cainjector`](./ca-injector.md) creates `secret/cert-manager-webhook-ca`, a self-signed root CA certificate which is used to sign certificates for the webhook pod.
+
+Then the webhook can be configured with either
+
+1. paths to a TLS certificate and key signed by the webhook CA, or
+2. a reference to the CA Secret for dynamic generation of the certificate and key on webhook startup
+
+## Known Problems and Solutions
+
+### Webhook connection problems on GKE private cluster
+
+If errors occur around the webhook but the webhook is running then the webhook
+is most likely not reachable from the API server. In this case, ensure that the
+API server can communicate with the webhook by following the [GKE private
+cluster explanation](../installation/compatibility.md#gke).
+
+### Webhook connection problems on AWS EKS
+
+When using a custom CNI (such as Weave or Calico) on EKS, the webhook cannot be reached by cert-manager.
+This happens because the control plane cannot be configured to run on a custom CNI on EKS,
+so the CNIs differ between control plane and worker nodes.
+The solution is to [run the webhook in the host network](../installation/compatibility.md#aws-eks) so it can be reached by cert-manager.
+
+### Webhook connection problems shortly after cert-manager installation
+
+When you first install cert-manager, it will take a few seconds before the cert-manager API is usable.
+This is because the cert-manager API requires the cert-manager webhook server, which takes some time to start up.
+Here's why:
+
+* The webhook server performs a leader election at startup which may take a few seconds.
+* The webhook server may take a few seconds to start up and to generate its self-signed CA and serving certificate and to publish those to a Secret.
+* `cainjector` performs a leader election at start up which can take a few seconds.
+* `cainjector`, once started, will take a few seconds to update the `caBundle` in all the webhook configurations.
+
+For these reasons, after installing cert-manager and when performing post-installation cert-manager API operations,
+you will need to check for temporary API configuration errors and retry.
+
+You could also add a post-installation check which performs `kubectl --dry-run` operations on the cert-manager API.
+Or you could add a post-installation check which automatically retries the [Installation Verification](../installation/verify.md) steps until they succeed.
+
+### Other Webhook Problems
+
+If you encounter any other problems with the webhook, please refer to the [webhook troubleshooting guide](../troubleshooting/webhook.md).
diff --git a/content/v1.13-docs/configuration/README.md b/content/v1.13-docs/configuration/README.md
new file mode 100644
index 0000000000..85c5d1334f
--- /dev/null
+++ b/content/v1.13-docs/configuration/README.md
@@ -0,0 +1,30 @@
+---
+title: Issuer Configuration
+description: Learn about configuring cert-manager using Issuer and ClusterIssuer resources.
+---
+
+The first thing you'll need to configure after you've installed cert-manager is an `Issuer` or a `ClusterIssuer`.
+These are resources that represent certificate authorities (CAs)
+able to sign certificates in response to certificate signing requests.
+
+This section documents how the different issuer types can be configured. You might want to
+[read more about `Issuer` and `ClusterIssuer` resources](../concepts/issuer.md).
+
+cert-manager comes with a number of built-in certificate issuers which are denoted by being in
+the `cert-manager.io` group. You can also install external issuers in addition to the built-in types.
+Built-in and external issuers are treated the same and are configured similarly.
+
+## Cluster Resource Namespace
+
+When using `ClusterIssuer` resource types, ensure you understand the purpose of the
+Cluster Resource Namespace; this can be a common source
+of issues for people getting started with cert-manager.
+
+The `ClusterIssuer` resource is cluster scoped. This means that when referencing
+a secret via the `secretName` field, secrets will be looked for in the `Cluster
+Resource Namespace`. By default, this namespace is `cert-manager` however it can be
+changed via a flag on the cert-manager-controller component:
+
+```bash
+--cluster-resource-namespace=my-namespace
+```
diff --git a/content/v1.13-docs/configuration/acme/README.md b/content/v1.13-docs/configuration/acme/README.md
new file mode 100644
index 0000000000..47eb22c9ee
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/README.md
@@ -0,0 +1,391 @@
+---
+title: ACME
+description: 'cert-manager configuration: ACME Issuers'
+---
+
+The ACME Issuer type represents a single account registered with the Automated
+Certificate Management Environment (ACME) Certificate Authority server. When you
+create a new ACME `Issuer`, cert-manager will generate a private key which is
+used to identify you with the ACME server.
+
+Certificates issued by public ACME servers are typically trusted by client's
+computers by default. This means that, for example, visiting a website that is
+backed by an ACME certificate issued for that URL, will be trusted by default by
+most client's web browsers. ACME certificates are typically free.
+
+## Solving Challenges
+
+In order for the ACME CA server to verify that a client owns the domain, or
+domains, a certificate is being requested for, the client must complete
+"challenges". This is to ensure clients are unable to request certificates for
+domains they do not own and as a result, fraudulently impersonate another's
+site. As detailed in the [RFC8555](https://tools.ietf.org/html/rfc8555),
+cert-manager offers two challenge validations - HTTP01 and DNS01 challenges.
+
+[HTTP01](./http01/README.md) challenges are completed by presenting a computed
+key, that should be present at a HTTP URL endpoint and is routable over the
+internet. This URL will use the domain name requested for the certificate. Once
+the ACME server is able to get this key from this URL over the internet, the
+ACME server can validate you are the owner of this domain. When a HTTP01
+challenge is created, cert-manager will automatically configure your cluster
+ingress to route traffic for this URL to a small web server that presents this
+key.
+
+[DNS01](./dns01/README.md) challenges are completed by providing a computed key
+that is present at a DNS TXT record. Once this TXT record has been propagated
+across the internet, the ACME server can successfully retrieve this key via a
+DNS lookup and can validate that the client owns the domain for the requested
+certificate. With the correct permissions, cert-manager will automatically
+present this TXT record for your given DNS provider.
+
+## Configuration
+
+### Creating a Basic ACME Issuer
+
+All ACME `Issuers` follow a similar configuration structure - a clients `email`,
+a `server` URL, a `privateKeySecretRef`, and one or more `solvers`. Below is an
+example of a simple ACME issuer:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ # You must replace this email address with your own.
+ # Let's Encrypt will use this to contact you about expiring
+ # certificates, and issues related to your account.
+ email: user@example.com
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ privateKeySecretRef:
+ # Secret resource that will be used to store the account's private key.
+ name: example-issuer-account-key
+ # Add a single challenge solver, HTTP01 using nginx
+ solvers:
+ - http01:
+ ingress:
+ ingressClassName: nginx
+```
+
+Solvers come in the form of [`dns01`](./dns01/README.md) and
+[`http01`](./http01/README.md) stanzas. For more information on how to configure
+these solver types, visit their respective documentation -
+[DNS01](./dns01/README.md), [HTTP01](./http01/README.md).
+
+### External Account Bindings
+
+cert-manager supports using External Account Bindings with your ACME account.
+External Account Bindings are used to associate your ACME account with an
+external account such as a CA custom database. This is typically not needed for
+most cert-manager users unless you know it is explicitly needed.
+
+External Account Bindings require two fields on an ACME `Issuer` which
+represents your ACME account. These fields are:
+
+- `keyID` - the key ID or account ID of which your external account binding is indexed by the
+external account manager
+- `keySecretRef` - the name and key of a secret containing a base 64 encoded
+URL string of your external account symmetric MAC key
+
+> Note: In _most_ cases, the MAC key must be encoded in `base64URL`. The
+> following command will base64-encode a key and convert it to `base64URL`:
+>
+> ```console
+> $ echo 'my-secret-key' | base64 -w0 | sed -e 's/+/-/g' -e 's/\//_/g' -e 's/=//g'
+> ```
+>
+> You can then create the Secret resource with:
+>
+> ```console
+> $ kubectl create secret generic eab-secret --from-literal \
+> secret={base64 encoded secret key}
+> ```
+
+An example of an ACME issuer with an External Account Binding is as follows.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: my-acme-server-with-eab
+spec:
+ acme:
+ email: user@example.com
+ server: https://my-acme-server-with-eab.com/directory
+ externalAccountBinding:
+ keyID: my-keyID-1
+ keySecretRef:
+ name: eab-secret
+ key: secret
+ privateKeySecretRef:
+ name: example-issuer-account-key
+ solvers:
+ - http01:
+ ingress:
+ ingressClassName: nginx
+```
+
+> Note: cert-manager versions pre-`v1.3.0` also required users to specify the
+> MAC algorithm for EAB by setting
+> `Issuer.spec.acme.externalAccountBinding.keyAlgorithm` field. This field is
+> now deprecated because the upstream Go `x/crypto` library hardcodes the algorithm
+> to `HS256`. (See related discussion upstream
+> [`CL#41430`](https://github.com/golang/go/issues/41430)).
+### Reusing an ACME Account
+
+You may want to reuse a single ACME account across multiple clusters. This
+might especially be useful when using EAB. If the `disableAccountKeyGeneration`
+field is set, cert-manager will not create a new ACME account and use the
+existing key specified in `privateKeySecretRef`. Note that the
+`Issuer`/`ClusterIssuer` will not be ready and will continue to retry until the
+`Secret` is provided.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: my-acme-server-with-existing-acme-account
+spec:
+ acme:
+ email: user@example.com
+ disableAccountKeyGeneration: true
+ privateKeySecretRef:
+ name: example-issuer-account-key
+```
+
+
+### Adding Multiple Solver Types
+
+You may want to use different types of challenge solver configurations for
+different ingress controllers, for example if you want to issue wildcard
+certificates using `DNS01` alongside other certificates that are validated using
+`HTTP01`.
+
+The `solvers` stanza has an optional `selector` field, that can be used to
+specify which `Certificates`, and further, what DNS names *on those*
+`Certificates` should be used to solve challenges.
+
+There are three selector types that can be used to form the requirements that a
+`Certificate` must meet in order to be selected for a solver - `matchLabels`,
+`dnsNames` and `dnsZones`. You can have any number of these three selectors on a
+single solver.
+
+
+#### Match Labels
+
+The `matchLabel` selector requires that all `Certificates` match all of
+the labels that are defined in the string map list of that stanza. For example,
+the following `Issuer` will only match on `Certificates` that have the labels
+`"user-cloudflare-solver": "true"` and `"email": "user@example.com"`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ matchLabels:
+ "use-cloudflare-solver": "true"
+ "email": "user@example.com"
+```
+
+#### DNS Names
+
+The `dnsNames` selector is a list of exact DNS names that should be mapped to a
+solver. This means that `Certificates` containing any of these DNS names will
+be selected. If a match is found, a `dnsNames` selector will take precedence
+over a [`dnsZones`](#dns-zones) selector. If multiple solvers match with the
+same `dnsNames` value, the solver with the most matching labels in
+[`matchLabels`](#match-labels) will be selected. If neither has more matches,
+the solver defined earlier in the list will be selected.
+
+The following example will solve challenges of `Certificates` with DNS names
+`example.com` and `*.example.com` for these domains.
+
+> Note: `dnsNames` take an exact match and do not resolve wildcards, meaning the
+> following `Issuer` *will not* solve for DNS names such as `foo.example.com`.
+> Use the [`dnsZones`](#dns-zones) selector type to match all subdomains within
+> a zone.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ dnsNames:
+ - 'example.com'
+ - '*.example.com'
+```
+
+#### DNS Zones
+
+The `dnsZones` stanza defines a list of DNS zones that can be solved by this
+solver. If a DNS name is an exact match, or a subdomain of any of the specified
+`dnsZones`, this solver will be used, unless a more specific
+[`dnsNames`](#dns-names) match is configured. This means that `sys.example.com`
+will be selected over one specifying `example.com` for the domain
+`www.sys.example.com`. If multiple solvers match with the same `dnsZones` value,
+the solver with the most matching labels in [`matchLabels`](#match-labels) will
+be selected. If neither has more matches, the solver defined earlier in the list
+will be selected.
+
+In the following example, this solver will resolve challenges for the domain
+`example.com`, as well as all of its subdomains `*.example.com`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ dnsZones:
+ - 'example.com'
+```
+
+#### All Together
+
+Each solver is able to have any number of the three selector types defined. In
+the following example, the `DNS01` solver for CloudFlare will be used to solve
+challenges for domains for `Certificates` that contain the DNS names
+`a.example.com` and `b.example.com`. The `DNS01` solver for Google CloudDNS will
+be used to solve challenges for `Certificates` whose DNS names match
+zone `test.example.com` and all of its subdomains (e.g. `foo.test.example.com`).
+
+For all other challenges, the `HTTP01` solver will be used *only* if the
+`Certificate` also contains the label `"use-http01-solver": "true"`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ ...
+ solvers:
+ - http01:
+ ingress:
+ ingressClassName: nginx
+ selector:
+ matchLabels:
+ "use-http01-solver": "true"
+ - dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ dnsNames:
+ - 'a.example.com'
+ - 'b.example.com'
+ - dns01:
+ cloudDNS:
+ project: my-project-id
+ hostedZoneName: 'test-example.com'
+ serviceAccountSecretRef:
+ key: sa
+ name: gcp-sa-secret
+ selector:
+ dnsZones:
+ - 'test.example.com' # This should be the DNS name of the zone
+```
+
+Each individual selector block can contain more than one selector type for
+example:
+
+```yaml
+solvers:
+- dns01:
+ cloudflare:
+ email: user@example.com
+ apiKeySecretRef:
+ name: cloudflare-apikey-secret
+ key: apikey
+ selector:
+ matchLabels:
+ 'email': 'user@example.com'
+ 'solver': 'cloudflare'
+ dnsZones:
+ - 'test.example.com'
+ - 'example.dev'
+```
+
+In this case the `DNS01` solver for Cloudflare will only be used to solve a
+challenge for a DNS name if the `Certificate` has a label from
+`matchLabels` _and_ the DNS name matches a zone from `dnsZones`.
+
+## Private ACME Servers
+
+cert-manager should also work with private or self-hosted ACME servers, as long as they follow the ACME spec.
+
+If your ACME server doesn't use a publicly trusted certificate, you can pass a trusted CA to use when creating your
+issuer, from cert-manager 1.11 onwards:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: my-acme-server-issuer
+spec:
+ acme:
+ server: https://my-acme-server.example.com
+ caBundle:
+ ...
+```
+
+
+{/* The empty link below preserves old links to #alternative-certificate-chain", which matched the old title of this section */}
+
+## Alternative Certificate Chains
+
+It's possible to choose alternative certificate chains when fetching a certificate from an ACME server. This allows issuers to gracefully roll people over to a new root certificate during a transition period; the most famous example was the Let's Encrypt ["ISRG Root" changeover](https://community.letsencrypt.org/t/transition-to-isrgs-root-delayed-until-jan-11-2021/125516).
+
+This functionality is not exclusive to Let's Encrypt; if your ACME server supports signing by multiple CAs you can use `preferredChain` with the value of the Common Name of the chain you want in the Issuer part of the certificate. If the common name matches a difference chain, the server can choose to use and return that new chain.
+
+If the `preferredChain` does not match a certificate the server will return whatever it considers to be its default certificate.
+
+By way of an example, below is how a user would have requested an alternative chain before the (now completed) "ISRG Root" changeover, but note that since this change has already happened there's no need for this with Let's Encrypt any more:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt
+spec:
+ acme:
+ server: https://acme-v02.api.letsencrypt.org/directory
+ preferredChain: "ISRG Root X1"
+```
diff --git a/content/v1.13-docs/configuration/acme/dns01/README.md b/content/v1.13-docs/configuration/acme/dns01/README.md
new file mode 100644
index 0000000000..d952eef568
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/README.md
@@ -0,0 +1,188 @@
+---
+title: DNS01
+description: 'cert-manager configuration: ACME DNS-01 challenges overview'
+---
+
+## Configuring DNS01 Challenge Provider
+
+This page contains details on the different options available on the `Issuer`
+resource's DNS01 challenge solver configuration.
+
+For more information on configuring ACME `Issuers` and their API format, read the
+[ACME Issuers](../README.md) documentation.
+
+DNS01 provider configuration must be specified on the `Issuer` resource, similar
+to the examples in the setting up documentation.
+
+You can read about how the DNS01 challenge type works on the [Let's Encrypt
+challenge types
+page](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge).
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ email: user@example.com
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ privateKeySecretRef:
+ name: example-issuer-account-key
+ solvers:
+ - dns01:
+ cloudDNS:
+ project: my-project
+ serviceAccountSecretRef:
+ name: prod-clouddns-svc-acct-secret
+ key: service-account.json
+```
+
+Each issuer can specify multiple different DNS01 challenge providers, and
+it is also possible to have multiple instances of the same DNS provider on a
+single `Issuer` (e.g. two CloudDNS accounts could be set, each with their own
+name).
+
+For more information on utilizing multiple solver types on a single `Issuer`,
+read the multiple-solver-types section.
+
+## Setting Nameservers for DNS01 Self Check
+
+cert-manager will check the correct DNS records exist before attempting a DNS01
+challenge. By default cert-manager will use the recursive nameservers taken
+from `/etc/resolv.conf` to query for the authoritative nameservers, which it will
+then query directly to verify the DNS records exist.
+
+If this is not desired (for example with multiple authoritative nameservers or
+split-horizon DNS), the cert-manager controller exposes two flags that allows
+you alter this behavior:
+
+`--dns01-recursive-nameservers` Comma separated string with host and port of the
+recursive nameservers cert-manager should query.
+
+`--dns01-recursive-nameservers-only` Forces cert-manager to only use the
+recursive nameservers for verification. Enabling this option could cause the DNS01
+self check to take longer due to caching performed by the recursive nameservers.
+
+
+Example usage:
+```bash
+--dns01-recursive-nameservers-only --dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53
+```
+
+If you're using the `cert-manager` helm chart, you can set recursive nameservers
+through `.Values.extraArgs` or at the command at helm install/upgrade time
+with `--set`:
+
+```bash
+--set 'extraArgs={--dns01-recursive-nameservers-only,--dns01-recursive-nameservers=8.8.8.8:53\,1.1.1.1:53}'
+```
+
+## Delegated Domains for DNS01
+
+By default, cert-manager will not follow CNAME records pointing to subdomains.
+
+If granting cert-manager access to the root DNS zone is not desired, then the
+`_acme-challenge.example.com` subdomain can instead be delegated to some other,
+less privileged domain (`less-privileged.example.org`). This could be achieved in the following way. Say, one has two zones:
+
+* `example.com`
+* `less-privileged.example.org`
+
+1. Create a CNAME record pointing to this less privileged domain:
+```
+_acme-challenge.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+```
+
+2. Grant cert-manager rights to update less privileged `less-privileged.example.org` zone
+
+3. Provide configuration/credentials for updating this less privileged zone
+and add an additional field into the relevant `dns01` solver. Note that `selector`
+field is still working for the original `example.com`, while credentials are provided for
+`less-privileged.example.org`
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ ...
+spec:
+ acme:
+ ...
+ solvers:
+ - selector:
+ dnsZones:
+ - 'example.com'
+ dns01:
+ # Valid values are None and Follow
+ cnameStrategy: Follow
+ route53:
+ region: eu-central-1
+ accessKeyID:
+ hostedZoneID:
+ secretAccessKeySecretRef:
+ ...
+```
+
+If you have a multitude of (sub)domains requiring separate certificates,
+it is possible to share an aliased less-privileged domain. To achieve it one should
+create a CNAME record for each (sub)domain like this:
+
+```txt
+_acme-challenge.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+_acme-challenge.www.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+_acme-challenge.foo.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+_acme-challenge.bar.example.com IN CNAME _acme-challenge.less-privileged.example.org.
+```
+
+With this configuration cert-manager will follow CNAME records recursively in order to determine
+which DNS zone to update during DNS01 challenges.
+
+
+## Supported DNS01 providers
+
+A number of different DNS providers are supported for the ACME `Issuer`. Below
+is a listing of available providers, their `.yaml` configurations, along with
+additional Kubernetes and provider specific notes regarding their usage.
+
+- [ACMEDNS](./acme-dns.md)
+- [Akamai](./akamai.md)
+- [AzureDNS](./azuredns.md)
+- [CloudFlare](./cloudflare.md)
+- [Google](./google.md)
+- [Route53](./route53.md)
+- [DigitalOcean](./digitalocean.md)
+- [RFC2136](./rfc2136.md)
+
+## Webhook
+
+cert-manager also supports out of tree DNS providers using an external webhook.
+Links to these supported providers along with their documentation are below:
+
+- [`AliDNS-Webhook`](https://github.com/pragkent/alidns-webhook)
+- [`cert-manager-alidns-webhook`](https://github.com/DEVmachine-fr/cert-manager-alidns-webhook)
+- [`cert-manager-webhook-civo`](https://github.com/okteto/cert-manager-webhook-civo)
+- [`cert-manager-webhook-dnspod`](https://github.com/qqshfox/cert-manager-webhook-dnspod)
+- [`cert-manager-webhook-dnsimple`](https://github.com/neoskop/cert-manager-webhook-dnsimple)
+- [`cert-manager-webhook-gandi`](https://github.com/bwolf/cert-manager-webhook-gandi)
+- [`cert-manager-webhook-infomaniak`](https://github.com/Infomaniak/cert-manager-webhook-infomaniak)
+- [`cert-manager-webhook-inwx`](https://gitlab.com/smueller18/cert-manager-webhook-inwx)
+- [`cert-manager-webhook-linode`](https://github.com/slicen/cert-manager-webhook-linode)
+- [`cert-manager-webhook-oci`](https://gitlab.com/dn13/cert-manager-webhook-oci) (Oracle Cloud Infrastructure)
+- [`cert-manager-webhook-scaleway`](https://github.com/scaleway/cert-manager-webhook-scaleway)
+- [`cert-manager-webhook-selectel`](https://github.com/selectel/cert-manager-webhook-selectel)
+- [`cert-manager-webhook-softlayer`](https://github.com/cgroschupp/cert-manager-webhook-softlayer)
+- [`cert-manager-webhook-ibmcis`](https://github.com/jb-dk/cert-manager-webhook-ibmcis)
+- [`cert-manager-webhook-loopia`](https://github.com/Identitry/cert-manager-webhook-loopia)
+- [`cert-manager-webhook-arvan`](https://github.com/kiandigital/cert-manager-webhook-arvan)
+- [`bizflycloud-certmanager-dns-webhook`](https://github.com/bizflycloud/bizflycloud-certmanager-dns-webhook)
+- [`cert-manager-webhook-hetzner`](https://github.com/vadimkim/cert-manager-webhook-hetzner)
+- [`cert-manager-webhook-yandex-cloud`](https://github.com/malinink/cert-manager-webhook-yandex-cloud)
+- [`cert-manager-webhook-netcup`](https://github.com/aellwein/cert-manager-webhook-netcup)
+- [`cert-manager-webhook-pdns`](https://github.com/zachomedia/cert-manager-webhook-pdns)
+- [`cert-manager-webhook-zilore`](https://gitlab.com/zilore/cert-manager-webhook-zilore)
+- [`stackit-cert-manager-webhook`](https://github.com/stackitcloud/stackit-cert-manager-webhook)
+
+You can find more information on how to configure webhook providers [here](./webhook.md).
+
+To create a new unsupported DNS provider, follow the development documentation [here](../../../contributing/dns-providers.md).
diff --git a/content/v1.13-docs/configuration/acme/dns01/acme-dns.md b/content/v1.13-docs/configuration/acme/dns01/acme-dns.md
new file mode 100644
index 0000000000..968531bf5f
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/acme-dns.md
@@ -0,0 +1,220 @@
+---
+title: ACMEDNS
+description: 'cert-manager configuration: ACME DNS-01 challenges using ACMEDNS'
+---
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ solvers:
+ - dns01:
+ acmeDNS:
+ host: https://acme.example.com
+ accountSecretRef:
+ name: acme-dns
+ key: acmedns.json
+```
+
+In general, clients to ACMEDNS perform registration on the users behalf and
+inform them of the CNAME entries they must create. This is not possible in
+cert-manager, it is a non-interactive system. Registration must be carried out
+beforehand and the resulting credentials JSON uploaded to the cluster as a
+`Secret`. In this example, we use `curl` and the API endpoints directly.
+Information about setting up and configuring ACMEDNS is available on the
+[ACMEDNS project page](https://github.com/joohoi/acme-dns).
+
+1. First, register with the ACMEDNS server, in this example, there is one
+ running at `auth.example.com`. The command:
+
+ ```sh
+ curl -X POST http://auth.example.com/register
+ ```
+
+ will return a JSON with credentials for your registration:
+
+ ```json
+ {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": []
+ }
+ ```
+
+ It is strongly recommended to restrict the update endpoint to the IP
+ range of your pods. This is done at registration time as follows:
+
+ ```sh
+ curl -X POST http://auth.example.com/register \
+ -H "Content-Type: application/json" \
+ --data '{"allowfrom": ["10.244.0.0/16"]}'
+ ```
+
+ Make sure to update the `allowfrom` field to match your cluster
+ configuration. The JSON will now look like:
+
+ ```json
+ {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ }
+ ```
+
+2. Save this JSON to a file with the key as your domain. You can specify
+ multiple domains with the same credentials if you like. In our example,
+ the returned credentials can be used to verify ownership of
+ `example.com` and and `example.org`.
+
+ ```json
+ {
+ "example.com": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ },
+ "example.org": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ }
+ }
+ ```
+
+3. Next, update your primary DNS server with the CNAME record that will tell the
+ verifier how to locate the challenge TXT record. This is obtained from the
+ `fulldomain` field in the registration:
+
+ ```
+ _acme-challenge.example.com CNAME d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com
+ _acme-challenge.example.org CNAME d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com
+ ```
+
+ The "name" of the record always has the _acme-challenge subdomain, and
+ the "value" of the record matches exactly the fulldomain field from
+ registration.
+
+ At verification time, the domain name `d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com` will be a TXT
+ record that is set to your validation token. When the verifier queries `_acme-challenge.example.com`, it will
+ be directed to the correct location by this CNAME record. This proves that you control `example.com`
+
+4. Create a secret from the credentials JSON that was saved in step 2, this
+ secret is referenced in the `accountSecretRef` field of your DNS01
+ issuer settings. When creating an `Issuer` both this `Issuer` and
+ `Secret` must be in the same namespace. However for a `ClusterIssuer`
+ (which does not have a namespace) the `Secret` must be placed in the
+ same namespace as where the cert-manager pod is running in (in the
+ default setup `cert-manager`).
+
+ ```sh
+ kubectl create secret generic acme-dns --from-file acmedns.json
+ ```
+
+## Limitation of the `acme-dns` server
+
+The [`acme-dns`](https://github.com/joohoi/acme-dns) server has a [known
+limitation](https://github.com/cert-manager/cert-manager/issues/3610#issuecomment-849792721):
+when a set of credentials is used with more than 2 domains, cert-manager
+will fail solving the DNS01 challenges.
+
+Imagining that you have configured the ACMEDNS issuer with a single set of
+credentials, and that the "subdomain" of this set of credentials is
+`d420c923-bbd7-4056-ab64-c3ca54c9b3cf`:
+
+```yaml
+kind: Secret
+metadata:
+ name: auth-example-com
+stringData:
+ acmedns.json: |
+ {
+ "example.com": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ },
+ }
+---
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: my-acme-dns
+spec:
+ acme:
+ solvers:
+ - dns01:
+ acmeDNS:
+ accountSecretRef:
+ name: auth-example-com
+ key: acmedns.json
+ host: auth.example.com
+```
+
+and imagine that you want to create a Certificate with three subdomains:
+
+```yaml
+kind: Certificate
+spec:
+ issuerRef:
+ name: issuer-1
+ dnsNames:
+ - "example.com"
+ - "*.example.com"
+ - "foo.example.com"
+```
+
+cert-manager will only be able to solve 2 challenges out of 3 in a non
+deterministic way. This limitation comes from a "feature" mentioned [this
+acme-dns issue](https://github.com/joohoi/acme-dns/issues/76).
+
+One workaround is to issue one set of acme-dns credentials for each
+domain that we want to be challenged, keeping in mind that each acme-dns
+"subdomain" can only accept at most 2 challenged domains. For example, the
+above secret would become:
+
+```yaml
+kind: Secret
+metadata:
+ name: auth-example-com
+stringData:
+ acmedns.json: |
+ {
+ "example.com": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ },
+ "foo.example.com": {
+ "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
+ "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
+ "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
+ "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
+ "allowfrom": ["10.244.0.0/16"]
+ }
+```
+
+With this setup, we have:
+
+- `example.com` and `*.example.com` are registered in the acme-dns
+ "subdomain" `d420c923-bbd7-4056-ab64-c3ca54c9b3cf`.
+- `foo.example.com` is registered in the acme-dns "subdomain"
+ `d420c923-bbd7-4056-ab64-c3ca54c9b3cf`.
+
+Another workaround is to use `--max-concurrent-challenges 2` when running
+the `cert-manager-controller`. With this setting, acme-dns will only have 2
+TXT records in its database at any time, which mitigates the issue.
\ No newline at end of file
diff --git a/content/v1.13-docs/configuration/acme/dns01/akamai.md b/content/v1.13-docs/configuration/acme/dns01/akamai.md
new file mode 100644
index 0000000000..271f7fd620
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/akamai.md
@@ -0,0 +1,86 @@
+---
+title: Akamai
+description: 'cert-manager configuration: ACME DNS-01 challenges using Akamai DNS'
+---
+
+## Edge DNS
+
+Use Edge DNS to solve DNS01 ACME challenges by creating a `Secret` using [Akamai API credentials](https://developer.akamai.com/getting-started/edgegrid) and an `Issuer` that references the `Secret` and sets the solver type.
+
+### Create a Secret
+
+The `Secret` should look like the following for the `Issuer` to reference. Replace `use_akamai_client_secret`, `use_akamai_access_token` and `use_akamai_client_token` with the respective Akamai API credential values.
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: akamai-secret
+type: Opaque
+stringData:
+ clientSecret: use_akamai_client_secret
+ accessToken: use_akamai_access_token
+ clientToken: use_akamai_client_token
+```
+
+### Create an Issuer
+
+To set Edge DNS for challenge tokens, `cert-manager` uses an `Issuer` that references the above `Secret` and other attributes such as the solver type. The `Issuer` should look like the following. Replace `use_akamai_host` with the Akamai API credential `host` value.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt-akamai-dns
+spec:
+ acme:
+ server: https://acme-v02.api.letsencrypt.org/directory
+ email: contact@me.com
+ privateKeySecretRef:
+ name: letsencrypt-akamai-issuer-account-key
+ solvers:
+ - dns01:
+ akamai:
+ serviceConsumerDomain: use_akamai_host
+ clientTokenSecretRef:
+ name: akamai-secret
+ key: clientToken
+ clientSecretSecretRef:
+ name: akamai-secret
+ key: clientSecret
+ accessTokenSecretRef:
+ name: akamai-secret
+ key: accessToken
+```
+
+### Create a Certificate
+
+The `Certificate` should look like the following and reference the Akamai Edge DNS `Issuer` above.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-zone
+spec:
+ secretName: akamai-crt-secret
+ dnsNames:
+ - '*.example.zone'
+ issuerRef:
+ name: letsencrypt-akamai-dns
+ kind: Issuer
+```
+
+> Note: `cert-manager` will wait for challenge tokens to propagate across the Edge DNS network. Follow the `certificate` status with a command such as the following.
+
+```bash
+kubectl describe certificate example-zone
+```
+
+### Troubleshooting
+
+Follow the `cert-manager` events to identify any issues with a command such as the following.
+
+```bash
+cmctl status certificate example-zone
+```
\ No newline at end of file
diff --git a/content/v1.13-docs/configuration/acme/dns01/azuredns.md b/content/v1.13-docs/configuration/acme/dns01/azuredns.md
new file mode 100644
index 0000000000..bc5de32fec
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/azuredns.md
@@ -0,0 +1,505 @@
+---
+title: AzureDNS
+description: 'cert-manager configuration: ACME DNS-01 challenges using AzureDNS'
+---
+
+cert-manager can create and then delete DNS-01 records in Azure DNS but it needs to authenticate to Azure first.
+There are four authentication methods available:
+
+- [Managed Identity Using AAD Workload Identity](#managed-identity-using-aad-pod-identity) (recommended)
+- [Managed Identity Using AAD Pod Identities](#managed-identity-using-aad-pod-identities) (deprecated)
+- [Managed Identity Using AKS Kubelet Identity](#managed-identity-using-aks-kubelet-identity)
+- [Service Principal](#service-principal)
+
+## Managed Identity Using AAD Workload Identity
+
+> ℹ️ This feature is available in cert-manager `>= v1.11.0`.
+>
+> 📖 Read the [AKS + LoadBalancer + Let's Encrypt tutorial](../../../tutorials/getting-started-aks-letsencrypt/README.md) for an end-to-end example of this authentication method.
+
+Azure AD workload identity (preview) on Azure Kubernetes Service (AKS) allows cert-manager to authenticate to Azure using a Kubernetes ServiceAccount Token and then to manage DNS-01 records in Azure DNS.
+This is the recommended authentication method because it is more secure and easier to maintain than the other methods.
+
+### Reconfigure the cluster
+
+Enable the workload identity federation features on your cluster.
+If you have an Azure AKS cluster you can use the following command:
+
+```bash
+az aks update \
+ --name ${CLUSTER} \
+ --enable-oidc-issuer \
+ --enable-workload-identity # ℹ️ This option is currently only available when using the aks-preview extension.
+```
+
+> ℹ️ You can [install the Azure workload identity extension on other managed and self-managed clusters](https://azure.github.io/azure-workload-identity/docs/installation.html) if you are not using Azure AKS.
+>
+> 📖 Read [Deploy and configure workload identity on an Azure Kubernetes Service (AKS) cluster](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster) for more information about the `--enable-workload-identity` feature.
+>
+### Reconfigure cert-manager
+
+Label the cert-manager controller Pod and ServiceAccount for the attention of the Azure Workload Identity webhook,
+which will result in the cert-manager controller Pod having an extra volume containing a Kubernetes ServiceAccount token which it will use to authenticate with Azure.
+
+If you installed cert-manager using Helm, the labels can be configured using Helm values:
+
+```yaml
+# values.yaml
+podLabels:
+ azure.workload.identity/use: "true"
+serviceAccount:
+ labels:
+ azure.workload.identity/use: "true"
+```
+
+If successful, the cert-manager Pod will have some new environment variables set,
+and the Azure workload-identity ServiceAccount token as a projected volume:
+
+```bash
+kubectl describe pod -n cert-manager -l app.kubernetes.io/component=controller
+```
+
+```terminal
+Containers:
+ ...
+ cert-manager-controller:
+ ...
+ Environment:
+ ...
+ AZURE_CLIENT_ID:
+ AZURE_TENANT_ID: f99bd6a4-665c-41cf-aff1-87a89d5c62d4
+ AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/azure/tokens/azure-identity-token
+ AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/
+ Mounts:
+ /var/run/secrets/azure/tokens from azure-identity-token (ro)
+Volumes:
+ ...
+ azure-identity-token:
+ Type: Projected (a volume that contains injected data from multiple sources)
+ TokenExpirationSeconds: 3600
+```
+
+> 📖 Read about [the role of the Mutating Admission Webhook](https://azure.github.io/azure-workload-identity/docs/installation/mutating-admission-webhook.html) in Azure AD Workload Identity for Kubernetes.
+
+
+### Create a Managed Identity
+
+In order for cert-manager to use the Azure API and manipulate the records in the Azure DNS zone,
+it needs an Azure account and the best type of account to use is called a "Managed Identity".
+This account does not come with a password or an API key and it is designed for use by machines rather than humans.
+
+Choose a managed identity name and create the Managed Identity:
+
+```bash
+export IDENTITY_NAME=cert-manager
+az identity create --name "${IDENTITY_NAME}"
+```
+
+Grant it permission to modify the DNS zone records:
+
+```bash
+export IDENTITY_CLIENT_ID=$(az identity show --name "${IDENTITY_NAME}" --query 'clientId' -o tsv)
+az role assignment create \
+ --role "DNS Zone Contributor" \
+ --assignee IDENTITY_CLIENT_ID \
+ --scope $(az network dns zone show --name $DOMAIN_NAME -o tsv --query id)
+```
+
+> 📖 Read [What are managed identities for Azure resources?](https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview)
+> for an overview of managed identities and their uses.
+>
+> 📖 Read [Azure built-in roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles) to learn about the "DNS Zone Contributor" role.
+>
+> 📖 Read more about [the `az identity` command](https://learn.microsoft.com/en-us/cli/azure/identity).
+
+### Add a Federated Identity
+
+Now associate a federated identity with the managed identity that you created earlier.
+cert-manager will authenticate to Azure using a short lived Kubernetes ServiceAccount token,
+and it will be able to impersonate the managed identity that you created in the previous step.
+
+```bash
+export SERVICE_ACCOUNT_NAME=cert-manager # ℹ️ This is the default Kubernetes ServiceAccount used by the cert-manager controller.
+export SERVICE_ACCOUNT_NAMESPACE=cert-manager # ℹ️ This is the default namespace for cert-manager.
+export SERVICE_ACCOUNT_ISSUER=$(az aks show --resource-group $AZURE_DEFAULTS_GROUP --name $CLUSTER --query "oidcIssuerProfile.issuerUrl" -o tsv)
+az identity federated-credential create \
+ --name "cert-manager" \
+ --identity-name "${IDENTITY_NAME}" \
+ --issuer "${SERVICE_ACCOUNT_ISSUER}" \
+ --subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}"
+```
+
+- `--subject`: is the distinguishing name of the Kubernetes ServiceAccount.
+- `--issuer`: is a URL from which the Azure will download the JWT signing certificate and other metadata
+
+> 📖 Read about [Workload identity federation](https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation) in the Microsoft identity platform documentation.
+>
+> 📖 Read more about [the `az identity federated-credential` command](https://learn.microsoft.com/en-us/cli/azure/identity/federated-credential).
+
+### Configure a ClusterIssuer
+
+For example:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-staging
+spec:
+ acme:
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ email: $EMAIL_ADDRESS
+ privateKeySecretRef:
+ name: letsencrypt-staging
+ solvers:
+ - dns01:
+ azureDNS:
+ hostedZoneName: $AZURE_ZONE_NAME
+ resourceGroupName: $AZURE_RESOURCE_GROUP
+ subscriptionID: $AZURE_SUBSCRIPTION_ID
+ environment: AzurePublicCloud
+ managedIdentity:
+ clientID: $IDENTITY_CLIENT_ID
+```
+
+The following variables need to be filled in.
+
+```bash
+# An email address to which Let's Encrypt will send renewal reminders.
+export EMAIL_ADDRESS=
+# The Azure DNS zone in which the DNS-01 records will be created and deleted.
+export AZURE_ZONE_NAME=
+# The Azure resource group containing the DNS zone.
+export AZURE_RESOURCE_GROUP=
+# The Azure billing account name and ID for the DNS zone.
+export AZURE_SUBSCRIPTION=
+export AZURE_SUBSCRIPTION_ID=$(az account show --name $AZURE_SUBSCRIPTION --query 'id' -o tsv)
+```
+
+#### ⚠️ Using 'Ambient Credentials' with ClusterIssuer and Issuer resources
+
+This authentication method is an example of what cert-manager calls 'ambient credentials'.
+Ambient credentials are enabled by default for ClusterIssuer resources, but disabled by default for Issuer resources.
+This is to prevent unprivileged users, who have permission to create Issuer resources, from issuing certificates using credentials that cert-manager incidentally has access to.
+ClusterIssuer resources are cluster scoped (not namespaced) and only platform administrators should be granted permission to create them.
+
+If you are using this authentication mechanism and ambient credentials are not enabled, you will see this error:
+
+```bash
+error instantiating azuredns challenge solver: ClientID is not set but neither --cluster-issuer-ambient-credentials nor --issuer-ambient-credentials are set.
+```
+
+> ⚠️ It is possible (but not recommended) to enable this authentication mechanism for `Issuer` resources, by setting the `--issuer-ambient-credentials` flag on the cert-manager controller to true.
+
+## Managed Identity Using AAD Pod Identities
+
+> ⚠️ The [open source Azure AD pod-managed identity (preview) in Azure Kubernetes Service has been deprecated as of 10/24/2022](https://github.com/Azure/aad-pod-identity#-announcement).
+> Use Workload Identity instead.
+
+[AAD Pod Identities](https://azure.github.io/aad-pod-identity) allows assigning a [Managed Identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) to a pod. This removes the need for adding explicit credentials into the cluster to create the required DNS records.
+
+> Note: When using Pod identity, even though assigning multiple identities to a single pod is allowed, currently cert-manager does not support this as it is not able to identify which identity to use.
+
+Firstly an identity should be created that has access to contribute to the DNS Zone.
+
+- Example creation using `azure-cli` and `jq`:
+
+```bash
+# Choose a unique Identity name and existing resource group to create identity in.
+IDENTITY=$(az identity create --name $IDENTITY_NAME --resource-group $IDENTITY_GROUP --output json)
+
+# Gets principalId to use for role assignment
+PRINCIPAL_ID=$(echo $IDENTITY | jq -r '.principalId')
+
+# Used for identity binding
+CLIENT_ID=$(echo $IDENTITY | jq -r '.clientId')
+RESOURCE_ID=$(echo $IDENTITY | jq -r '.id')
+
+# Get existing DNS Zone Id
+ZONE_ID=$(az network dns zone show --name $ZONE_NAME --resource-group $ZONE_GROUP --query "id" -o tsv)
+
+# Create role assignment
+az role assignment create --role "DNS Zone Contributor" --assignee $PRINCIPAL_ID --scope $ZONE_ID
+```
+
+- Example creation using Terraform
+
+```terraform
+variable resource_group_name {}
+variable location {}
+variable dns_zone_id {}
+
+# Creates Identity
+resource "azurerm_user_assigned_identity" "dns_identity" {
+ name = "cert-manager-dns01"
+ resource_group_name = var.resource_group_name
+ location = var.location
+}
+
+# Creates Role Assignment
+resource "azurerm_role_assignment" "dns_contributor" {
+ scope = var.dns_zone_id
+ role_definition_name = "DNS Zone Contributor"
+ principal_id = azurerm_user_assigned_identity.dns_identity.principal_id
+}
+
+# Client Id Used for identity binding
+output "identity_client_id" {
+ value = azurerm_user_assigned_identity.dns_identity.client_id
+}
+
+# Resource Id Used for identity binding
+output "identity_resource_id" {
+ value = azurerm_user_assigned_identity.dns_identity.id
+}
+```
+
+Next we need to ensure we have installed [AAD Pod Identity](https://azure.github.io/aad-pod-identity) using their walk-through. This will install the CRDs and deployment required to assign the identity.
+
+Now we can create the identity resource and binding using the below manifest as an example:
+
+```yaml
+apiVersion: "aadpodidentity.k8s.io/v1"
+kind: AzureIdentity
+metadata:
+ annotations:
+ # recommended to use namespaced identites https://azure.github.io/aad-pod-identity/docs/configure/match_pods_in_namespace/
+ aadpodidentity.k8s.io/Behavior: namespaced
+ name: certman-identity
+ namespace: cert-manager # change to your preferred namespace
+spec:
+ type: 0 # MSI
+ resourceID: # Resource Id From Previous step
+ clientID: # Client Id from previous step
+---
+apiVersion: "aadpodidentity.k8s.io/v1"
+kind: AzureIdentityBinding
+metadata:
+ name: certman-id-binding
+ namespace: cert-manager # change to your preferred namespace
+spec:
+ azureIdentity: certman-identity
+ selector: certman-label # This is the label that needs to be set on cert-manager pods
+```
+
+Next we need to ensure the cert-manager pod has a relevant label to use the pod identity binding. This can be done by editing the deployment and adding the below into the `.spec.template.metadata.labels` field
+
+```yaml
+spec:
+ template:
+ metadata:
+ labels:
+ aadpodidbinding: certman-label # must match selector in AzureIdentityBinding
+```
+
+Or by using the helm values `podLabels`
+
+```yaml
+podLabels:
+ aadpodidbinding: certman-label
+```
+
+Lastly when we create the certificate issuer we only need to specify the `hostedZoneName`, `resourceGroupName` and `subscriptionID` fields for the DNS zone. Example below:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ azureDNS:
+ subscriptionID: AZURE_SUBSCRIPTION_ID
+ resourceGroupName: AZURE_DNS_ZONE_RESOURCE_GROUP
+ hostedZoneName: AZURE_DNS_ZONE
+ # Azure Cloud Environment, default to AzurePublicCloud
+ environment: AzurePublicCloud
+```
+
+This authentication mechanism is what cert-manager considers 'ambient credentials'. Use of ambient credentials is disabled by default for cert-manager `Issuer`s. This to ensure unprivileged users who have permission to create issuers cannot issue certificates using any credentials cert-manager incidentally has access to. To enable this authentication mechanism for `Issuer`s, you will need to set `--issuer-ambient-credentials` flag on cert-manager controller to true. (There is a corresponding `--cluster-issuer-ambient-credentials` flag which is set to `true` by default).
+
+If you are using this authentication mechanism and ambient credentials are not enabled, you will see this error:
+```bash
+error instantiating azuredns challenge solver: ClientID is not set but neither --cluster-issuer-ambient-credentials nor --issuer-ambient-credentials are set.
+```
+
+These are necessary to enable Azure Managed Identities.
+
+## Managed Identity Using AKS Kubelet Identity
+
+When creating an AKS cluster in Azure there is the option to use a managed identity that is assigned to the kubelet. This identity is assigned to the underlying node pool in the AKS cluster and can then be used by the cert-manager pods to authenticate to Azure Active Directory.
+
+There are some caveats with this approach, these mainly being:
+
+- Any permissions granted to this identity will also be accessible to all containers running inside the Kubernetes cluster.
+- Using AKS extensions like `Kube Dashboard`, `Virtual Node`, or `HTTP Application Routing` (see full list [here](https://docs.microsoft.com/en-us/azure/aks/use-managed-identity#summary-of-managed-identities)) will create additional identities that are assigned to your node pools. If your node pools have more than one identity assigned, you will need to specify either `clientID` or `resourceID` to select the correct one.
+
+To set this up, firstly you will need to retrieve the identity that the kubelet is using by querying the AKS cluster. This can then be used to create the appropriate permissions in the DNS zone.
+
+- Example commands using `azure-cli`:
+
+```bash
+# Get AKS Kubelet Identity
+PRINCIPAL_ID=$(az aks show -n $CLUSTERNAME -g $CLUSTER_GROUP --query "identityProfile.kubeletidentity.objectId" -o tsv)
+
+# Get existing DNS Zone Id
+ZONE_ID=$(az network dns zone show --name $ZONE_NAME --resource-group $ZONE_GROUP --query "id" -o tsv)
+
+# Create role assignment
+az role assignment create --role "DNS Zone Contributor" --assignee $PRINCIPAL_ID --scope $ZONE_ID
+```
+
+- Example terraform:
+
+```terraform
+variable dns_zone_id {}
+
+# Creating the AKS cluster, abbreviated.
+resource "azurerm_kubernetes_cluster" "cluster" {
+ ...
+ # Creates Identity associated to kubelet
+ identity {
+ type = "SystemAssigned"
+ }
+ ...
+}
+
+resource "azurerm_role_assignment" "dns_contributor" {
+ scope = var.dns_zone_id
+ role_definition_name = "DNS Zone Contributor"
+ principal_id = azurerm_kubernetes_cluster.cluster.kubelet_identity[0].object_id
+ skip_service_principal_aad_check = true # Allows skipping propagation of identity to ensure assignment succeeds.
+}
+```
+
+Then when creating the cert-manager issuer we need to specify the `hostedZoneName`, `resourceGroupName` and `subscriptionID` fields for the DNS Zone.
+
+We also need to specify `managedIdentity.clientID` or `managedIdentity.resourceID` if multiple managed identities are assigned to the node pools.
+
+The value for `managedIdentity.clientID` can be fetched by running this command:
+
+```bash
+az aks show -n $CLUSTERNAME -g $CLUSTER_GROUP --query "identityProfile.kubeletidentity.clientId" -o tsv
+```
+
+Example below:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ azureDNS:
+ subscriptionID: AZURE_SUBSCRIPTION_ID
+ resourceGroupName: AZURE_DNS_ZONE_RESOURCE_GROUP
+ hostedZoneName: AZURE_DNS_ZONE
+ # Azure Cloud Environment, default to AzurePublicCloud
+ environment: AzurePublicCloud
+ # optional, only required if node pools have more than 1 managed identity assigned
+ managedIdentity:
+ # client id of the node pool managed identity (can not be set at the same time as resourceID)
+ clientID: YOUR_MANAGED_IDENTITY_CLIENT_ID
+ # resource id of the managed identity (can not be set at the same time as clientID)
+ # resourceID: YOUR_MANAGED_IDENTITY_RESOURCE_ID
+```
+
+## Service Principal
+
+Configuring the AzureDNS DNS01 Challenge for a Kubernetes cluster requires
+creating a service principal in Azure.
+
+To create the service principal you can use the following script (requires
+`azure-cli` and `jq`):
+
+```bash
+# Choose a name for the service principal that contacts azure DNS to present
+# the challenge.
+$ AZURE_CERT_MANAGER_NEW_SP_NAME=NEW_SERVICE_PRINCIPAL_NAME
+# This is the name of the resource group that you have your dns zone in.
+$ AZURE_DNS_ZONE_RESOURCE_GROUP=AZURE_DNS_ZONE_RESOURCE_GROUP
+# The DNS zone name. It should be something like domain.com or sub.domain.com.
+$ AZURE_DNS_ZONE=AZURE_DNS_ZONE
+
+$ DNS_SP=$(az ad sp create-for-rbac --name $AZURE_CERT_MANAGER_NEW_SP_NAME --output json)
+$ AZURE_CERT_MANAGER_SP_APP_ID=$(echo $DNS_SP | jq -r '.appId')
+$ AZURE_CERT_MANAGER_SP_PASSWORD=$(echo $DNS_SP | jq -r '.password')
+$ AZURE_TENANT_ID=$(echo $DNS_SP | jq -r '.tenant')
+$ AZURE_SUBSCRIPTION_ID=$(az account show --output json | jq -r '.id')
+```
+
+For security purposes, it is appropriate to utilize RBAC to ensure that you
+properly maintain access control to your resources in Azure. The service
+principal that is generated by this tutorial has fine-grained access to ONLY the
+DNS Zone in the specific resource group specified. It requires this permission
+so that it can read/write the \_acme\_challenge TXT records to the zone.
+
+Lower the Permissions of the service principal.
+
+```bash
+$ az role assignment delete --assignee $AZURE_CERT_MANAGER_SP_APP_ID --role Contributor
+```
+
+Give Access to DNS Zone.
+
+```bash
+$ DNS_ID=$(az network dns zone show --name $AZURE_DNS_ZONE --resource-group $AZURE_DNS_ZONE_RESOURCE_GROUP --query "id" --output tsv)
+$ az role assignment create --assignee $AZURE_CERT_MANAGER_SP_APP_ID --role "DNS Zone Contributor" --scope $DNS_ID
+```
+
+Check Permissions. As the result of the following command, we would like to see just one object in the permissions array with "DNS Zone Contributor" role.
+
+```bash
+$ az role assignment list --all --assignee $AZURE_CERT_MANAGER_SP_APP_ID
+```
+
+A secret containing service principal password should be created on Kubernetes to facilitate presenting the challenge to Azure DNS. You can create the secret with the following command:
+
+```bash
+$ kubectl create secret generic azuredns-config --from-literal=client-secret=$AZURE_CERT_MANAGER_SP_PASSWORD
+```
+
+Get the variables for configuring the issuer.
+
+```bash
+$ echo "AZURE_CERT_MANAGER_SP_APP_ID: $AZURE_CERT_MANAGER_SP_APP_ID"
+$ echo "AZURE_CERT_MANAGER_SP_PASSWORD: $AZURE_CERT_MANAGER_SP_PASSWORD"
+$ echo "AZURE_SUBSCRIPTION_ID: $AZURE_SUBSCRIPTION_ID"
+$ echo "AZURE_TENANT_ID: $AZURE_TENANT_ID"
+$ echo "AZURE_DNS_ZONE: $AZURE_DNS_ZONE"
+$ echo "AZURE_DNS_ZONE_RESOURCE_GROUP: $AZURE_DNS_ZONE_RESOURCE_GROUP"
+```
+
+To configure the issuer, substitute the capital cased variables with the values
+from the previous script. You can get the subscription id from the Azure portal.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ azureDNS:
+ clientID: AZURE_CERT_MANAGER_SP_APP_ID
+ clientSecretSecretRef:
+ # The following is the secret we created in Kubernetes. Issuer will use this to present challenge to Azure DNS.
+ name: azuredns-config
+ key: client-secret
+ subscriptionID: AZURE_SUBSCRIPTION_ID
+ tenantID: AZURE_TENANT_ID
+ resourceGroupName: AZURE_DNS_ZONE_RESOURCE_GROUP
+ hostedZoneName: AZURE_DNS_ZONE
+ # Azure Cloud Environment, default to AzurePublicCloud
+ environment: AzurePublicCloud
+```
diff --git a/content/v1.13-docs/configuration/acme/dns01/cloudflare.md b/content/v1.13-docs/configuration/acme/dns01/cloudflare.md
new file mode 100644
index 0000000000..b3f4ded449
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/cloudflare.md
@@ -0,0 +1,108 @@
+---
+title: Cloudflare
+description: 'cert-manager configuration: ACME DNS-01 challenges using Cloudflare DNS'
+---
+
+To use Cloudflare, you may use one of two types of tokens. **API Tokens** allow application-scoped keys bound to specific zones and permissions, while **API Keys** are globally-scoped keys that carry the same permissions as your account.
+
+**API Tokens** are recommended for higher security, since they have more restrictive permissions and are more easily revocable.
+
+## API Tokens
+
+Tokens can be created at **User Profile > API Tokens > API Tokens**. The following settings are recommended:
+
+- Permissions:
+ - `Zone - DNS - Edit`
+ - `Zone - Zone - Read`
+- Zone Resources:
+ - `Include - All Zones`
+
+To create a new `Issuer`, first make a Kubernetes secret containing your new API token:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: cloudflare-api-token-secret
+type: Opaque
+stringData:
+ api-token:
+```
+
+Then in your `Issuer` manifest:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ apiTokenSecretRef:
+ name: cloudflare-api-token-secret
+ key: api-token
+```
+
+## API Keys
+
+API keys can be retrieved at **User Profile > API Tokens > API Keys > Global API Key > View**.
+
+To create a new `Issuer`, first make a Kubernetes secret containing your API key:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: cloudflare-api-key-secret
+type: Opaque
+stringData:
+ api-key:
+```
+
+Then in your `Issuer` manifest:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudflare:
+ email: my-cloudflare-acc@example.com
+ apiKeySecretRef:
+ name: cloudflare-api-key-secret
+ key: api-key
+```
+
+## Troubleshooting
+
+### Actor `com.cloudflare.api.token.xxxx` requires permission `com.cloudflare.api.account.zone.list` to list zones
+If you get the error that your token does not have the correct permission to list zones there can be 2 causes.
+1. The token lacks the `Zone - Zone - Read` permission
+2. cert-manager identified the wrong zone name for the domain due to DNS issues.
+
+In the case of the 2nd issue you will see an error like below:
+```
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Started 6s cert-manager Challenge scheduled for processing
+ Warning PresentError 3s (x2 over 3s) cert-manager Error presenting challenge: Cloudflare API Error for GET "/zones?name="
+ Error: 0: Actor 'com.cloudflare.api.token.xxxx' requires permission 'com.cloudflare.api.account.zone.list' to list zones
+```
+
+In this case we recommend [changing your DNS01 self-check nameservers](./README.md#setting-nameservers-for-dns01-self-check).
+
+## `Cloudflare API error for POST "/zones//dns_records` generic error
+
+You might be hitting this as Cloudflare blocks the use of the API to update DNS records for the following TLDs: `.cf`, `.ga`, `.gq`, `.ml` and `.tk`.
+This is discussed in the [Cloudflare Community](https://community.cloudflare.com/t/unable-to-update-ddns-using-api-for-some-tlds/167228).
+We recommend using an alternative DNS provider when using these TLDs.
\ No newline at end of file
diff --git a/content/v1.13-docs/configuration/acme/dns01/digitalocean.md b/content/v1.13-docs/configuration/acme/dns01/digitalocean.md
new file mode 100644
index 0000000000..4d6c155863
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/digitalocean.md
@@ -0,0 +1,46 @@
+---
+title: DigitalOcean
+description: 'cert-manager configuration: ACME DNS-01 challenges using DigitalOcean DNS'
+---
+
+This provider uses a Kubernetes `Secret` resource to work. In the following
+example, the `Secret` will have to be named `digitalocean-dns` and have a
+sub-key `access-token` with the token in it. For example:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: digitalocean-dns
+data:
+ # insert your DO access token here
+ access-token: "base64 encoded access-token here"
+ ```
+
+The access token must have write access.
+
+To create a Personal Access Token, see [DigitalOcean documentation](https://docs.digitalocean.com/reference/api/create-personal-access-token/).
+
+Handy direct link: https://cloud.digitalocean.com/account/api/tokens/new
+
+To encode your access token into base64, you can use the following
+
+```bash
+echo -n 'your-access-token' | base64
+```
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ digitalocean:
+ tokenSecretRef:
+ name: digitalocean-dns
+ key: access-token
+```
\ No newline at end of file
diff --git a/content/v1.13-docs/configuration/acme/dns01/google.md b/content/v1.13-docs/configuration/acme/dns01/google.md
new file mode 100644
index 0000000000..460239de80
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/google.md
@@ -0,0 +1,242 @@
+---
+title: Google CloudDNS
+description: 'cert-manager configuration: ACME DNS-01 challenges using Google CloudDNS'
+---
+
+This guide explains how to set up an `Issuer`, or `ClusterIssuer`, to use Google
+CloudDNS to solve DNS01 ACME challenges. It's advised you read the [DNS01
+Challenge Provider](./README.md) page first for a more general understanding of
+how cert-manager handles DNS01 challenges.
+
+This guide assumes that your cluster is hosted on Google Cloud Platform (GCP)
+and that you already have a domain set up with CloudDNS.
+
+You'll need to be using a **Public DNS Zone**, so that the ACME challenge checker
+is able to access the DNS records that cert-manager will create.
+
+## Set up a Service Account
+
+cert-manager needs to be able to add records to CloudDNS in order to solve the
+DNS01 challenge. To enable this, a GCP service account must be created with the
+`dns.admin` role.
+
+> Note: For this guide the `gcloud` command will be used to set up the service
+> account. Ensure that `gcloud` is using the correct project and zone before
+> entering the commands. These steps could also be completed using the Cloud
+> Console.
+
+```bash
+PROJECT_ID=myproject-id
+gcloud iam service-accounts create dns01-solver --display-name "dns01-solver"
+```
+
+In the command above, replace `myproject-id` with the ID of your project.
+
+```bash
+gcloud projects add-iam-policy-binding $PROJECT_ID \
+ --member serviceAccount:dns01-solver@$PROJECT_ID.iam.gserviceaccount.com \
+ --role roles/dns.admin
+```
+
+> **Note**: The use of the `dns.admin` role in this example role is for convenience.
+> If you want to ensure cert-manager runs under a least privilege service account,
+> you will need to create a custom role with the following permissions:
+>
+> * `dns.resourceRecordSets.*`
+> * `dns.changes.*`
+> * `dns.managedZones.list`
+
+## Use Static Credentials
+
+Follow the instructions in the following sections to deploy cert-manager using
+static credentials for the service account you created. You should rotate these
+credentials periodically.
+
+### Create a Service Account Secret
+
+To access this service account, cert-manager uses a key stored in a Kubernetes
+`Secret`. First, create a key for the service account and download it as a JSON
+file, then create a `Secret` from this file.
+
+Keep the key file safe and do not share it, as it could be used to gain access
+access to your cloud resources. The key file can be deleted once it has been
+used to generate the `Secret`.
+
+If you did not create the service account `dns01-solver` before, you need to
+create it first.
+
+```bash
+gcloud iam service-accounts create dns01-solver
+```
+
+Replace instances of `$PROJECT_ID` with the ID of your project.
+```bash
+gcloud iam service-accounts keys create key.json \
+ --iam-account dns01-solver@$PROJECT_ID.iam.gserviceaccount.com
+kubectl create secret generic clouddns-dns01-solver-svc-acct \
+ --from-file=key.json
+```
+
+> Note: If you have already added the `Secret` but get an error: `...due to
+> error processing: error getting clouddns service account: secret "XXX" not
+> found`, the `Secret` may be in the wrong namespace. If you're configuring a
+> `ClusterIssuer`, move the `Secret` to the `Cluster Resource Namespace` which
+> is `cert-manager` by default. If you're configuring an `Issuer`, the `Secret`
+> should be stored in the same namespace as the `Issuer` resource.
+
+### Create an Issuer That Uses CloudDNS
+
+Next, create an `Issuer` (or `ClusterIssuer`) with a `cloudDNS` provider. An
+example `Issuer` manifest can be seen below with annotations.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudDNS:
+ # The ID of the GCP project
+ project: $PROJECT_ID
+ # This is the secret used to access the service account
+ serviceAccountSecretRef:
+ name: clouddns-dns01-solver-svc-acct
+ key: key.json
+```
+
+For more information about `Issuers` and `ClusterIssuers`, see
+[Configuration](../../README.md).
+
+Once an `Issuer` (or `ClusterIssuer`) has been created successfully, a
+`Certificate` can then be added to verify that everything works.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com
+ namespace: default
+spec:
+ secretName: example-com-tls
+ issuerRef:
+ # The issuer created previously
+ name: example-issuer
+ dnsNames:
+ - example.com
+ - www.example.com
+```
+
+For more details about `Certificates`, see [Usage](../../../usage/README.md).
+
+## GKE Workload Identity
+
+If you are deploying cert-manager into a [Google Container Engine (GKE)
+cluster](https://cloud.google.com/kubernetes-engine/) with workload identity
+enabled, you can leverage workload identity to avoid creating and managing
+static service account credentials. The [workload identity
+how-to](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
+provides more detail on how workload identity functions, but briefly workload
+identity allows you to link a Google service accounts (GSA) to Kubernetes
+service accounts (KSA). This GSA/KSA linking is two-way, i.e., you must
+establish the link in GCP _and_ Kubernetes. Once configured, workload identity
+allows Kubernetes pods running under a KSA to access the GCP APIs with the
+permissions of the linked GSA. The workload identity how-to also provides
+detailed instructions on how to enable workload identity in your GKE cluster.
+The instructions in the following sections assume you are deploying cert-manager
+to a GKE cluster with workload identity already enabled.
+
+### Enable Ambient Credential Usage
+
+'Ambient Credentials' are credentials drawn from the environment, metadata services, or local files which are not explicitly configured in the ClusterIssuer API object. When this flag is enabled Cert-Manager will access the GKE Metadata server for credentials. By default this is enabled for ClusterIssuer resources but is disabled for Issuer resources. To enable it for Issuer resources set the `--issuer-ambient-credentials` flag.
+
+### Link KSA to GSA in GCP
+
+The cert-manager component that needs to modify DNS records is the pod created
+as part of the cert-manager deployment. The [standard methods for deploying
+cert-manager to Kubernetes](../../../installation/README.md) create the
+cert-manager deployment in the cert-manager namespace and its pod spec specifies
+it runs under the cert-manager service account. To link the GSA you created
+above to the cert-manager KSA in the cert-manager namespace in your GKE cluster,
+run the following command.
+
+```bash
+gcloud iam service-accounts add-iam-policy-binding \
+ --role roles/iam.workloadIdentityUser \
+ --member "serviceAccount:$PROJECT_ID.svc.id.goog[cert-manager/cert-manager]" \
+ dns01-solver@$PROJECT_ID.iam.gserviceaccount.com
+```
+
+If your cert-manager pods are running under a different service account, replace
+`goog[cert-manager/cert-manager]` with `goog[NAMESPACE/SERVICE_ACCOUNT]`, where
+`NAMESPACE` is the namespace of the service account and `SERVICE_ACCOUNT` is the
+name of the service account.
+
+### Link KSA to GSA in Kubernetes
+
+After deploying cert-manager, add the proper workload identity annotation to the
+cert-manager service account.
+
+```bash
+kubectl annotate serviceaccount --namespace=cert-manager cert-manager \
+ "iam.gke.io/gcp-service-account=dns01-solver@$PROJECT_ID.iam.gserviceaccount.com"
+```
+
+Again, if your cert-manager pods are running under a different service account,
+replace `--namespace=cert-manager cert-manager` with `--namespace=NAMESPACE
+SERVICE_ACCOUNT`, where `NAMESPACE` is the namespace of the service account and
+`SERVICE_ACCOUNT` is the name of the service account.
+
+If you are deploying cert-manager using its helm chart, you can use the
+`serviceAccount.annotations` configuration parameter to add the above workload
+identity annotation to the cert-manager KSA.
+
+### Create an Issuer That Uses CloudDNS
+
+Next, create an `Issuer` (or `ClusterIssuer`) with a `clouddns` provider. An
+example `Issuer` manifest can be seen below with annotations. Note that the
+issuer does not include a `serviceAccountSecretRef` property. Excluding this
+instructs cert-manager to use the default credentials provided by GKE workload
+identity.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ cloudDNS:
+ # The ID of the GCP project
+ project: $PROJECT_ID
+```
+
+For more information about `Issuers` and `ClusterIssuers`, see
+[Configuration](../../README.md).
+
+Once an `Issuer` (or `ClusterIssuer`) has been created successfully, a
+`Certificate` can then be added to verify that everything works.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com
+ namespace: default
+spec:
+ secretName: example-com-tls
+ issuerRef:
+ # The issuer created previously
+ name: example-issuer
+ dnsNames:
+ - example.com
+ - www.example.com
+```
+
+For more details about `Certificates`, see [Usage](../../../usage/README.md).
diff --git a/content/v1.13-docs/configuration/acme/dns01/rfc2136.md b/content/v1.13-docs/configuration/acme/dns01/rfc2136.md
new file mode 100644
index 0000000000..86e9dd32df
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/rfc2136.md
@@ -0,0 +1,207 @@
+---
+title: RFC-2136
+description: 'cert-manager configuration: ACME DNS-01 challenges using RFC2136-compliant DNS providers'
+---
+
+The goal of this document is to provide a configuration overview of the various
+facilities required to deploy cert-manager against a RFC2136 compliant DNS
+server such as BIND `named`. This capability is also commonly known as “dynamic
+DNS”.
+
+Unlike the peer of other cert-manager DNS integrations, `named` is a bit of a
+“Swiss Army Knife” of domain name servers. Over the years, it has been highly
+optimized to provide maximal vertical scalability for a single node, as well as
+horizontal scalability with service provider interfaces. This flexibility makes
+it impossible to go into every possible `named` deployment that a user may run
+in to though. Instead, this document will try to make sure your server is ready
+to accept requests from cert-manager using command line tools, then get on to
+the making the two work together.
+
+## Transaction Signatures ⇒ TSIG
+
+Dynamic DNS updates are essentially server queries which otherwise might return
+resource records (RRs). Since DNS servers are commonly exposed to the public
+internet, being able to push an unauthenticated update to any server that
+responds to queries would be immediately untenable.
+
+In the eyes of the `named` architects, the generic solution to this problem
+space was twofold. The first is to require manual enablement of updates at a
+zone level, such as `example.com`. In a naive network, there is no requirement
+that zone updates have any security to them, and clients can be configured such
+that they can provide updates without any authentication. An example of where
+this is useful is for machines booting using DHCP, in this case the machines
+know about themselves and the DNS server can be configured to accept updates
+when they come from the address being configured.
+
+This clearly has limitations in situations such as cert-manager and the DNS01
+challenge. In this environment, a TXT RR must be created after coordination with
+the ACME server. After negotiating with the ACME server, a the TXT RR that is
+published on the domain validates that the domain is legitimately engaged with
+the process of creating a certificate for it. In the bigger picture of DNS, this
+means that an arbitrary actor (cert-manager, in this case) must be able to add
+one of these KV mappings to the domain and delete it after the certificate has
+been issued. `cert-manager` does not have a convenient physical characteristic
+such as a DHCP allocation to validate it's requests.
+
+For cases like this, we need to be able to sign a request that is being sent to
+the DNS server. We do that through TSIGs, or Transaction SIGnatures.
+
+### Configuration Step 1 - Set up your DNS server for secure dynamic updates
+
+There are many excellent tutorials on the net that walk through
+preparing a basic `named` server for dynamic updates:
+
+- https://www.cyberciti.biz/faq/unix-linux-bind-named-configuring-tsig/
+- https://tomthorp.me/blog/using-tsig-enable-secure-zone-transfers-between-bind-9x-servers
+
+More complex `name` deployments will not use text files, but rather may use LDAP
+or SQL for a database for resource records. An additional wrinkle is metadata
+configuration, such as for zone metadata like enabling dynamic updates or access
+control lists (ACLs) for a zone. There are too many configurations to go into
+here, but you should be able to find the documentation to do so.
+
+Whatever your deployment is, the goal at this stage has nothing to do with
+cert-manager and everything to do with a tool called `nsupdate` generating
+updates signed with TSIG. Once this is out of the way, you can attack the
+cert-manager configuration with far greater confidence.
+
+#### Using `nsupdate`
+
+Most paths to configuring BIND `named` will go through using `dnssec-keygen`.
+This command-line tool generates a named private key that is used for signing
+TSIG requests. When a request is signed, both the signature and the name of the
+private key are attached to the request in an unencrypted form. In this manner,
+when the request is received, the name of the private key can be used to by the
+recipient to find the private key itself, build a new signature with it, and
+compare the two for acceptance.
+
+Since there are dozens of ways to have your `named` server misconfigured, we’ll
+use `nsupdate` to test that the server behaves as expected before we get there.
+`https://debian-administration.org/article/591/Using_the_dynamic_DNS_editor_nsupdate`
+is a solid breakdown of how to use the tool.
+
+To get started, we’ll simply run `nsupdate -k ` where `keyID` is the value
+returned from `dnssec-keygen`. This will read the key from disk and provide a
+command prompt to issue commands. In general, we want to write a simple TXT RR
+and make sure we can delete it.
+
+```bash
+$ nsupdate -k
+update add www1.example.com 60 txt testing
+send
+… test here with `nslookup`
+update delete www1.example.com txt
+send
+… test here with `nslookup`
+```
+
+Any failures to write, read or delete the record will mean that cert-manager
+will not be able to do so either, no matter how well it is configured.
+
+### Configuration Step 2 - Set up cert-manager
+
+Now we get to the fun stuff, seeing everything work. Remember that we need to
+set up the ACME DNS01 issuer and challenge mechanism as well as the `rfc2136`
+provider. Since the documentation covers the other parts sufficiently, let’s
+focus on the provider here.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ rfc2136:
+ nameserver:
+ tsigKeyName:
+ tsigAlgorithm: HMACSHA512 // should be matched to the algo you chose in `dnssec-keygen`
+ tsigSecretSecretRef:
+ name:
+ key:
+```
+
+For example:
+
+```yaml
+ rfc2136:
+ nameserver: 1.2.3.4:53
+ tsigKeyName: example-com-secret
+ tsigAlgorithm: HMACSHA512
+ tsigSecretSecretRef:
+ name: tsig-secret
+ key: tsig-secret-key
+```
+
+For this example configuration, we’ll need the following two commands. The
+first, on your `named` server generates the key. Note how `example-com-secret`
+is both in the `tsigKeyName` above and the `dnssec-keygen` command that follows.
+
+```bash
+$ dnssec-keygen -r /dev/urandom -a HMAC-SHA512 -b 512 -n HOST example-com-secret
+```
+
+Also note how the `tsigAlgorithm` is provided in both the configuration and the
+`keygen` command. They are listed at
+`https://github.com/miekg/dns/blob/v1.0.12/tsig.go#L18-L23`.
+
+The second bit of configuration you need on the Kubernetes side is to create a
+secret. Pulling the secret key string from the `.private` file generated
+above, use the secret in the placeholder below:
+
+```bash
+$ kubectl -n cert-manager create secret generic tsig-secret --from-literal=tsig-secret-key=
+```
+
+Note how the `tsig-secret` and `tsig-secret-key` match the configuration in the
+`tsigSecretSecretRef` above.
+
+## Rate Limits
+
+The `rfc2136` provider waits until *all* nameservers to in your domain's SOA RR
+respond with the same result before it contacts Let's Encrypt to complete the
+challenge process. This is because the challenge server contacts a
+non-authoritative DNS server that does a recursive query (a query for records it
+does not maintain locally). If the servers in the SOA do not contain the correct
+values, it's likely that the non-authoritative server will have bad information
+as well, causing the request to go against rate limits and eventually locking
+the process out.
+
+This process is in place to protect users from server misconfiguration creating
+a more subtle lockout that persists after the server configuration has been
+repaired.
+
+As documented elsewhere, it is prudent to fully debug configurations using the
+ACME staging servers before using the production servers. The staging servers
+have less aggressive rate limits, but the certificates they issue are not signed
+with a root certificate trusted by browsers.
+
+## What’s next?
+
+This configuration so far will actually do nothing. You still have to request a
+certificate as described [here](../../../usage/README.md). Once a certificate is
+requested, the provider will begin processing the request.
+
+## Troubleshooting
+
+- Be sure that you have fully tested the DNS server updates using `nsupdate`
+ first. Ideally, this is done from a pod in the same namespace as the `rfc2136`
+ provider to ensure there are no firewall issues.
+- The logs for the `cert-manager` pod are your friend. Additional logs can be
+ generated by adding the `--v=5` argument to the container launch.
+- The TSIG key is encoded with `base64`, but the Kubernetes API server also
+ expects that key literals will be decoded before they are stored. In some
+ cases, a key must be double-encoded. (If you've tested using `nsupdate`, it's
+ pretty easy to spot when you are running into this.)
+- Pay attention to the refresh time of the zone you are working with. For zones
+ with low traffic, it will not make a significant difference to reduce the
+ refresh time down to about five minutes while getting initial certificates.
+ Once the process is working, the beauty of `cert-manager` is it doesn't matter
+ if a renewal takes hours due to refresh times, it's all automated!
+- Compared to the other providers that often use REST APIs to modify DNS RRs,
+ this provider can take a little longer. You can `watch kubectl certificate
+ yourcert` to get a display of what's going on. It's not uncommon for the process
+ to take five minutes in total.
\ No newline at end of file
diff --git a/content/v1.13-docs/configuration/acme/dns01/route53.md b/content/v1.13-docs/configuration/acme/dns01/route53.md
new file mode 100644
index 0000000000..e441b3b0c3
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/route53.md
@@ -0,0 +1,259 @@
+---
+title: Route53
+description: 'cert-manager configuration: ACME DNS-01 challenges using Amazon AWS Route53 DNS'
+---
+
+This guide explains how to set up an `Issuer`, or `ClusterIssuer`, to use Amazon
+Route53 to solve DNS01 ACME challenges. It's advised you read the [DNS01
+Challenge Provider](./README.md) page first for a more general understanding of
+how cert-manager handles DNS01 challenges.
+
+> Note: This guide assumes that your cluster is hosted on Amazon Web Services
+> (AWS) and that you already have a hosted zone in Route53.
+
+## Set up an IAM Role
+
+cert-manager needs to be able to add records to Route53 in order to solve the
+DNS01 challenge. To enable this, create a IAM policy with the following
+permissions:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "route53:GetChange",
+ "Resource": "arn:aws:route53:::change/*"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "route53:ChangeResourceRecordSets",
+ "route53:ListResourceRecordSets"
+ ],
+ "Resource": "arn:aws:route53:::hostedzone/*"
+ },
+ {
+ "Effect": "Allow",
+ "Action": "route53:ListHostedZonesByName",
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+> Note: The `route53:ListHostedZonesByName` statement can be removed if you
+> specify the (optional) `hostedZoneID`. You can further tighten the policy by
+> limiting the hosted zone that cert-manager has access to (e.g.
+> `arn:aws:route53:::hostedzone/DIKER8JEXAMPLE`).
+
+## Credentials
+
+You have two options for the set up - either create a user or a role and attach
+that policy from above. Using a role is considered best practice because you do
+not have to store permanent credentials in a secret.
+
+cert-manager supports two ways of specifying credentials:
+
+- explicit by providing an `accessKeyID` or an `accessKeyIDSecretRef`, and a `secretAccessKeySecretRef`
+- or implicit (using [metadata
+ service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)
+ or [environment variables or credentials
+ file](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials).
+
+cert-manager also supports specifying a `role` to enable cross-account access
+and/or limit the access of cert-manager. Integration with
+[`kiam`](https://github.com/uswitch/kiam) and
+[`kube2iam`](https://github.com/jtblin/kube2iam) should work out of the box.
+
+
+## Cross Account Access
+
+Example: Account Y manages Route53 DNS Zones. Now you want cert-manager running in Account X (or many other accounts) to be able to manage records in Route53 zones hosted in Account Y.
+
+First, create a role with the permissions policy above (let's call the role `dns-manager`)
+in Account Y, and attach a trust relationship like the one below.
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::XXXXXXXXXXX:role/cert-manager"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+
+Bear in mind, that you won't be able to define this policy until `cert-manager` role on account Y is created. If you are setting this up using a configuration language, you may want to define principal as:
+
+```json
+"Principal": {
+ "AWS": "XXXXXXXXXXX"
+ }
+```
+And restrict it, in a future step, after all the roles are created.
+
+This allows the role `cert-manager` in Account X to assume the `dns-manager` role in Account Y to manage the Route53 DNS zones in Account Y. For more information visit the [official
+documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html).
+
+Second, create the cert-manager role in Account X; this will be used as a credentials source for the cert-manager pods running in Account X. Attach to the role the following **permissions** policy:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Resource": "arn:aws:iam::YYYYYYYYYYYY:role/dns-manager",
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+
+And the following trust relationship (Add AWS `Service`s as needed):
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "ec2.amazonaws.com"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+}
+```
+
+## Creating an Issuer (or `ClusterIssuer`)
+
+Here is an example configuration for a `ClusterIssuer`:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-prod
+spec:
+ acme:
+ ...
+ solvers:
+
+ # example: cross-account zone management for example.com
+ # this solver uses ambient credentials (i.e. inferred from the environment or EC2 Metadata Service)
+ # to assume a role in a different account
+ - selector:
+ dnsZones:
+ - "example.com"
+ dns01:
+ route53:
+ region: us-east-1
+ hostedZoneID: DIKER8JEXAMPLE # optional, see policy above
+ role: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager
+
+ # this solver handles example.org challenges
+ # and uses explicit credentials
+ - selector:
+ dnsZones:
+ - "example.org"
+ dns01:
+ route53:
+ region: eu-central-1
+ # The AWS access key ID can be specified using the literal accessKeyID parameter
+ # or retrieved from a secret using the accessKeyIDSecretRef
+ # If using accessKeyID, omit the accessKeyIDSecretRef parameter and vice-versa
+ accessKeyID: AKIAIOSFODNN7EXAMPLE
+ accessKeyIDSecretRef:
+ name: prod-route53-credentials-secret
+ key: access-key-id
+ secretAccessKeySecretRef:
+ name: prod-route53-credentials-secret
+ key: secret-access-key
+ # you can also assume a role with these credentials
+ role: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager
+```
+
+Note that, as mentioned above, the pod is using `arn:aws:iam::XXXXXXXXXXX:role/cert-manager` as a credentials source in Account X, but the `ClusterIssuer` ultimately assumes the `arn:aws:iam::YYYYYYYYYYYY:role/dns-manager` role to actually make changes in Route53 zones located in Account Y.
+
+## EKS IAM Role for Service Accounts (IRSA)
+
+While [`kiam`](https://github.com/uswitch/kiam) / [`kube2iam`](https://github.com/jtblin/kube2iam) work directly with cert-manager, some special attention is needed for using the [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) feature available on EKS.
+
+### OIDC provider
+
+First follow the AWS documentation [Enabling IAM roles for service accounts on your cluster](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html) to ensure that the OIDC provider for the EKS cluster is enabled. The OIDC information is needed to create the trust relationship for the cert-manager role below.
+
+### IAM role trust policy
+
+The cert-manager role needs the following trust relationship attached to the role in order to use the IRSA method. Replace the following:
+
+- `` with the AWS account ID of the EKS cluster.
+- `` with the region where the EKS cluster is located.
+- `` with the hash in the EKS API URL; this will be a random 32 character hex string (example: `45DABD88EEE3A227AF0FA468BE4EF0B5`)
+- `` with the namespace where cert-manager is running.
+- `` with the name of the `ServiceAccount` object created by cert-manager.
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRoleWithWebIdentity",
+ "Principal": {
+ "Federated": "arn:aws:iam:::oidc-provider/oidc.eks..amazonaws.com/id/"
+ },
+ "Condition": {
+ "StringEquals": {
+ "oidc.eks..amazonaws.com/id/:sub": "system:serviceaccount::"
+ }
+ }
+ }
+ ]
+}
+```
+
+**Note:** If you're following the Cross Account example above, this trust policy is attached to the cert-manager role in Account X with ARN `arn:aws:iam::XXXXXXXXXXX:role/cert-manager`. The permissions policy is the same as above.
+
+### Service annotation
+
+Annotate the `ServiceAccount` created by cert-manager:
+
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ annotations:
+ eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager
+```
+
+You will also need to modify the cert-manager `Deployment` with the correct file system permissions, so the `ServiceAccount` token can be read.
+
+```yaml
+spec:
+ template:
+ spec:
+ securityContext:
+ fsGroup: 1001
+```
+
+The cert-manager Helm chart provides a variable for injecting annotations into cert-manager's `ServiceAccount` and `Deployment` object like so:
+
+```yaml
+serviceAccount:
+ annotations:
+ eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager
+securityContext:
+ fsGroup: 1001
+```
+
+**Note:** If you're following the Cross Account example above, modify the `ClusterIssuer` in the same way as above with the role from Account Y.
diff --git a/content/v1.13-docs/configuration/acme/dns01/webhook.md b/content/v1.13-docs/configuration/acme/dns01/webhook.md
new file mode 100644
index 0000000000..d9a4339e39
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/dns01/webhook.md
@@ -0,0 +1,32 @@
+---
+title: Webhook
+description: 'cert-manager configuration: ACME DNS-01 challenges using External Webhook Solvers'
+---
+
+The webhook `Issuer` is a generic ACME solver. The actual work is done by an
+external service. Look at the respective documentation of
+[`dns-providers`](../../../contributing/dns-providers.md).
+
+View more webhook solvers at https://github.com/topics/cert-manager-webhook.
+
+Here is an example of how webhook providers are to be configured. All `DNS01`
+providers will contain their own specific configuration however all require a
+`groupName` and `solverName` field.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ ...
+ solvers:
+ - dns01:
+ webhook:
+ groupName: $WEBHOOK_GROUP_NAME
+ solverName: $WEBHOOK_SOLVER_NAME
+ config:
+ ...
+
+```
diff --git a/content/v1.13-docs/configuration/acme/http01/README.md b/content/v1.13-docs/configuration/acme/http01/README.md
new file mode 100644
index 0000000000..2e3e8242af
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/http01/README.md
@@ -0,0 +1,393 @@
+---
+title: HTTP01
+description: 'cert-manager configuration: ACME HTTP-01 challenges'
+---
+
+
+
+📌 This page focuses on solving ACME HTTP-01 challenges. If you are looking for
+how to automatically create Certificate resources by annotating Ingress or
+Gateway resources, see [Securing Ingress Resources](../../../usage/ingress.md) and
+[Securing Gateway Resources](../../../usage/gateway.md).
+
+
+
+cert-manager uses your existing Ingress or Gateway configuration in order to
+solve HTTP01 challenges.
+
+
+## Configuring the HTTP01 Ingress solver
+
+This page contains details on the different options available on the `Issuer`
+resource's HTTP01 challenge solver configuration. For more information on
+configuring ACME issuers and their API format, read the [ACME Issuers](../README.md)
+documentation.
+
+You can read about how the HTTP01 challenge type works on the [Let's Encrypt
+challenge types
+page](https://letsencrypt.org/docs/challenge-types/#http-01-challenge).
+
+Here is an example of a simple `HTTP01` ACME issuer with more options for
+configuration below:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: example-issuer
+spec:
+ acme:
+ server: https://acme-staging-v02.api.letsencrypt.org/directory
+ privateKeySecretRef:
+ name: example-issuer-account-key
+ solvers:
+ - http01:
+ ingress:
+ ingressClassName: nginx
+```
+
+## Options
+
+The HTTP01 Issuer supports a number of additional options. For full details on
+the range of options available, read the [reference
+documentation](../../../reference/api-docs.md#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01).
+
+### `ingressClassName`
+
+
+
+📌 The field `ingressClassName` was added in cert-manager 1.12.
+
+
+
+If the `ingressClassName` field is specified, cert-manager will create new
+`Ingress` resources in order to route traffic to the `acmesolver` pods, which
+are responsible for responding to ACME challenge validation requests.
+
+This is the recommended way of configuring the Ingress controller. Most Ingress
+controllers support `ingressClassName`, with the notable exception of
+ingress-gce (as per the page [Configure Ingress for external load
+balancing](https://cloud.google.com/kubernetes-engine/docs/how-to/load-balance-ingress)).
+
+### `class`
+
+If the `class` field is specified, a new Ingress resource with a randomly
+generated name will be created in order to solve the challenge. This new
+resource will have an annotation with key `kubernetes.io/ingress.class` and
+value set to the value of the `class` field.
+
+This field is only recommended with ingress-gce. ingress-gce [doesn't support the
+`ingressClassName` field](https://cloud.google.com/kubernetes-engine/docs/how-to/load-balance-ingress).
+
+### `name`
+
+If the `name` field is specified, cert-manager will edit the named
+ingress resource in order to solve HTTP01 challenges.
+
+This is useful for compatibility with ingress controllers such as `ingress-gce`,
+which utilize a unique IP address for each `Ingress` resource created.
+
+This mode should be avoided when using ingress controllers that expose a single
+IP for all ingress resources, as it can create compatibility problems with
+certain ingress-controller specific annotations.
+
+
+
+If `class` and `ingressClassName` are not specified, and `name` is also not
+specified, cert-manager will default to create *new* `Ingress` resources but
+will **not** set the ingress class on these resources, meaning *all* ingress
+controllers installed in your cluster will serve traffic for the challenge
+solver, potentially incurring additional cost.
+
+
+
+
+### `serviceType`
+
+In rare cases it might be not possible/desired to use `NodePort` as type for the
+HTTP01 challenge response service, e.g. because of Kubernetes limit
+restrictions. To define which Kubernetes service type to use during challenge
+response specify the following HTTP01 configuration:
+
+```yaml
+ http01:
+ ingress:
+ # Valid values are ClusterIP and NodePort
+ serviceType: ClusterIP
+```
+
+By default, type `NodePort` will be used when you don't set HTTP01 or when you set
+`serviceType` to an empty string. Normally there's no need to change this.
+
+
+### `podTemplate`
+
+You may wish to change or add to the labels and annotations of solver pods.
+These can be configured under the `metadata` field under `podTemplate`.
+
+Similarly, you can set the `nodeSelector`, tolerations and affinity of solver
+pods by configuring under the `spec` field of the `podTemplate`. No other
+spec fields can be edited.
+
+An example of how you could configure the template is as so:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: ...
+spec:
+ acme:
+ server: ...
+ privateKeySecretRef:
+ name: ...
+ solvers:
+ - http01:
+ ingress:
+ podTemplate:
+ metadata:
+ labels:
+ foo: "bar"
+ env: "prod"
+ spec:
+ nodeSelector:
+ bar: baz
+```
+
+The added labels and annotations will merge on top of the cert-manager defaults,
+overriding entries with the same key.
+
+No other fields of the `podTemplate` exist.
+
+### `ingressTemplate`
+
+It is possible to add labels and annotations to the solver ingress resources.
+It can be really useful when you are managing several Ingress Controllers across your cluster and you want to make sure that the right one will pick up and expose the solver (for the upcoming challenge to resolve).
+These can be configured under the `metadata` field under `ingressTemplate`:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: ...
+spec:
+ acme:
+ server: ...
+ privateKeySecretRef:
+ name: ...
+ solvers:
+ - http01:
+ ingress:
+ ingressTemplate:
+ metadata:
+ labels:
+ foo: "bar"
+ annotations:
+ "nginx.ingress.kubernetes.io/whitelist-source-range": "0.0.0.0/0,::/0"
+ "nginx.org/mergeable-ingress-type": "minion"
+ "traefik.ingress.kubernetes.io/frontend-entry-points": "http"
+```
+
+The added labels and annotations will merge on top of the cert-manager defaults,
+overriding entries with the same key.
+
+No other fields of the ingress can be edited.
+
+## Configuring the HTTP-01 Gateway API solver
+
+**FEATURE STATE**: cert-manager 1.5 [alpha]
+
+The Gateway and HTTPRoute resources are part of the [Gateway API][gwapi], a set
+of CRDs that you install on your Kubernetes cluster that provide various
+improvements over the Ingress API.
+
+[gwapi]: https://gateway-api.sigs.k8s.io
+
+
+
+📌 This feature requires the installation of the [Gateway API bundle](https://gateway-api.sigs.k8s.io/guides/#installing-a-gateway-controller) and passing a
+feature flag to the cert-manager controller.
+
+To install v1.5.1 Gateway API bundle (Gateway CRDs and webhook), run the following command:
+
+```sh
+kubectl apply -f "https://github.com/kubernetes-sigs/gateway-api/releases/download/v0.5.1/standard-install.yaml"
+```
+
+To enable the feature in cert-manager, turn on the `GatewayAPI` feature gate:
+
+- If you are using Helm:
+
+ ```sh
+ helm upgrade --install cert-manager jetstack/cert-manager --namespace cert-manager \
+ --set "extraArgs={--feature-gates=ExperimentalGatewayAPISupport=true}"
+ ```
+
+- If you are using the raw cert-manager manifests, add the following flag to the
+ cert-manager controller Deployment:
+
+ ```yaml
+ args:
+ - --feature-gates=ExperimentalGatewayAPISupport=true
+ ```
+
+The Gateway API CRDs should either be installed before cert-manager starts or
+the cert-manager Deployment should be restarted after installing the Gateway API
+CRDs. This is important because some of the cert-manager components only perform
+the Gateway API check on startup. You can restart cert-manager with the
+following command:
+
+```sh
+kubectl rollout restart deployment cert-manager -n cert-manager
+```
+
+
+
+
+
+
+🚧 cert-manager 1.8+ is tested with v1alpha2 Kubernetes Gateway API. It should also work
+with v1beta1 because of resource conversion, but has not been tested with it.
+
+
+The Gateway API HTTPRoute HTTP-01 solver creates a temporary HTTPRoute using the
+given labels. These labels must match a Gateway that contains a listener on port
+80.
+
+Here is an example of a HTTP-01 ACME Issuer using the Gateway API:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: letsencrypt
+ namespace: default
+spec:
+ acme:
+ solvers:
+ - http01:
+ gatewayHTTPRoute:
+ parentRefs:
+ - name: traefik
+ namespace: traefik
+ kind: Gateway
+```
+
+The Issuer relies on an existing Gateway present on the cluster. cert-manager
+does not edit Gateway resources.
+
+For example, the following Gateway will allow the Issuer to solve the challenge:
+
+```yaml
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: Gateway
+metadata:
+ name: traefik
+ namespace: traefik
+spec:
+ gatewayClassName: traefik
+ listeners:
+ - name: http
+ protocol: HTTP
+ port: 80
+ allowedRoutes:
+ namespaces:
+ from: All
+```
+
+In the above example, the Gateway has been specifically created for the purpose
+of solving HTTP-01 challenges, but you can also choose to re-use your existing
+Gateway, as long as it has a listener on port 80.
+
+The `labels` on your Issuer may reference a Gateway that is on a separate
+namespace, as long as the Gateway's port 80 listener is configured with `from:
+All`. Note that the Certificate will still be created on the same namespace as
+the Issuer, which means that you won't be able to reference this Secret in the
+above-mentioned Gateway.
+
+When the above Issuer is presented with a Certificate, cert-manager creates the
+temporary HTTPRoute. For example, with the following Certificate:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-tls
+ namespace: default
+spec:
+ issuerRef:
+ name: letsencrypt
+ dnsNames:
+ - example.net
+```
+
+You will see an HTTPRoute appear:
+
+```yaml
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: HTTPRoute
+metadata:
+ name: cm-acme-http-solver-gdhvg
+ namespace: default
+spec:
+ parentRefs:
+ - name: traefik
+ namespace: traefik
+ kind: Gateway
+ hostnames:
+ - example.net
+ rules:
+ - forwardTo:
+ - port: 8089
+ serviceName: cm-acme-http-solver-gdhvg
+ weight: 1
+ matches:
+ - path:
+ type: Exact
+ value: /.well-known/acme-challenge/YadC4gaAzqEPU1Yea0D2MrzvNRWiBCtUizCtpiRQZqI
+```
+
+After the Certificate is issued, the HTTPRoute is deleted.
+
+
+### `labels`
+
+These labels are copied into the temporary HTTPRoute created by cert-manager for
+solving the HTTP-01 challenge. These labels must match one of the Gateway
+resources on your cluster. The matched Gateway have a listener on port 80.
+
+Note that when the labels do not match any Gateway on your cluster, cert-manager
+will create the temporary HTTPRoute challenge and nothing will happen.
+
+
+### `serviceType`
+
+This field has the same meaning as the
+[`http01.ingress.serviceType`](#ingress-service-type).
+
+
+## Setting Nameservers for HTTP-01 solver propagation checks
+
+cert-manager will perform reachability tests before attempting a HTT01
+challenge. By default cert-manager will use the recursive nameservers taken
+from `/etc/resolv.conf` to query the challenge URL.
+
+If this is not desired (for example with split-horizon DNS), the cert-manager
+controller exposes a flag that allows you alter this behavior:
+
+`--acme-http01-solver-nameservers` Comma separated string with host and port of the
+recursive nameservers cert-manager should query.
+
+
+Example usage:
+```bash
+--acme-http01-solver-nameservers="8.8.8.8:53,1.1.1.1:53"
+```
+
+If you're using the `cert-manager` helm chart, you can set recursive nameservers
+through `.Values.extraArgs` or at the command at helm install/upgrade time
+with `--set`:
+
+```bash
+--set 'extraArgs={--acme-http01-solver-nameservers=8.8.8.8:53\,1.1.1.1:53}'
+```
diff --git a/content/v1.13-docs/configuration/acme/http01/externalloadbalancer.md b/content/v1.13-docs/configuration/acme/http01/externalloadbalancer.md
new file mode 100644
index 0000000000..a85966bd29
--- /dev/null
+++ b/content/v1.13-docs/configuration/acme/http01/externalloadbalancer.md
@@ -0,0 +1,34 @@
+---
+title: External Load Balancer
+description: 'cert-manager configuration: ACME HTTP-01 challenges using External Load Balancers'
+---
+
+When you are using an external load balancer provided by any host, you can face several configuration issues to get it work with cert-manager.
+
+This documentation is intended to help configure the HTTP-01 challenge type for instances behind external load balancer.
+
+## NAT Loopback / Hairpin
+
+The first configuration point is NAT loopback. You can face check issues due to Load Balancer preventing instances behind it to access its external interface.
+
+Some Network Load Balancer have this kind of limitation for several reasons. It can be configured through `iptables` rerouting configuration known as `NAT loopback`.
+
+To check if you are facing this problem :
+
+1. Check that the endpoint of the challenge is accessible to the public : `curl `
+2. Check that the challenge endpoint is NOT accessible from inside behind the Load Balancer: use SSH to open a session on a node places behind the LB; then launch the same command than before : `curl `
+
+The `HTTP-01` challenge's endpoint can be found in the logs when the `pre-check` fails. If it does not appear in the logs, you can check the challenge URL by `kubectl`command.
+
+`` is the URL used to test the HTTP-01 from the certificate `Issuer`. For Let's Encrypt for example, the URL is formed like `/.well-known/acme-challenge/`
+
+
+## Load Balancer HTTP endpoints
+
+If you are using a Load Balancer (outside a managed Kubernetes service), you should be able to configure the Load Balancer protocol as HTTP, HTTPS, TCP, UDP. Several Load Balancer now offer free TLS certificates with Let's Encrypt.
+
+When using HTTP(s) protocols for your Load Balancer, it can intercept the challenge URL to replace the response's verification hash with their hash.
+
+In this case, cert-manager will fail `did not get expected response when querying endpoint, expected 'xxxx' but got: yyyy (truncated)`.
+
+This kind of error can be thrown for multiple reasons. This case shows a correctly formatted response, but not the expected one. The solution is to configure the Load Balancer with TCP protocol so that the HTTP request will not be intercepted by the host.
\ No newline at end of file
diff --git a/content/v1.13-docs/configuration/ca.md b/content/v1.13-docs/configuration/ca.md
new file mode 100644
index 0000000000..fffb6f2401
--- /dev/null
+++ b/content/v1.13-docs/configuration/ca.md
@@ -0,0 +1,94 @@
+---
+title: CA
+description: 'cert-manager configuration: CA Issuers'
+---
+
+⚠️ CA issuers are generally either for trying cert-manager out or else for advanced users with
+a good idea of how to run a PKI. To be used safely in production, CA issuers introduce 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 CA issuer represents a Certificate Authority whose certificate and
+private key are stored inside the cluster as a Kubernetes `Secret`.
+
+Certificates issued by a CA issuer will not be publicly trusted and so are unlikely to be trusted
+by your applications without further configuration.
+
+Consider [trust-manager](../projects/trust-manager/README.md) for distributing your CA certificate safely
+across your cluster!
+
+## Deployment
+
+CA Issuers must be configured with a certificate and private key stored in a Kubernetes
+secret. You can create this externally if you wish, or you could bootstrap a root certificate
+using a [`SelfSigned` issuer](./selfsigned.md#bootstrapping-ca-issuers).
+
+Your certificate's secret should reside in the same namespace as the `Issuer`, or otherwise
+in the `Cluster Resource Namespace` in the case of a `ClusterIssuer`.
+
+The `Cluster Resource Namespace` is defaulted as being the `cert-manager` namespace, but
+can be configured using the `--cluster-resource-namespace` flag on the cert-manager controller.
+
+Below is an example of a secret resource that will be used for signing. Take
+note of the index keys used for each field as these are required in order for
+cert-manager to find the certificate and key. Also note that, like all secrets,
+data must be base64 encoded. The command `$ cat crt.pem | base64 -w0` should help you
+on GNU-based systems (Debian, Ubuntu, etc.) and `$ cat crt.pem | base64 -b0` on BSD-based
+systems (most notably macOS).
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: ca-key-pair
+ namespace: sandbox
+data:
+ tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMrVENDQWVHZ0F3SUJBZ0lKQUtQR3dLRGwvNUhuTUEwR0NTcUdTSWIzRFFFQkN3VUFNQk14RVRBUEJnTlYKQkFNTUNHcHZjMmgyWVc1c01CNFhEVEU1TURneU1qRTJNRFUxT0ZvWERUSTVNRGd4T1RFMk1EVTFPRm93RXpFUgpNQThHQTFVRUF3d0lhbTl6YUhaaGJtd3dnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCCkFRQ3doU0IvcVc2L2tMYjJ6cHUrRUp2RDl3SEZhcStRQS8wSkgvTGxseW83ekFGeCtISHErQ09BYmsrQzhCNHQKL0hVRXNuczVSTDA5Q1orWDRqNnBiSkZkS2R1UHhYdTVaVllua3hZcFVEVTd5ZzdPU0tTWnpUbklaNzIzc01zMApSNmpZbi9Ecmo0eFhNSkVmSFVEcVllU1dsWnIzcWkxRUZhMGM3ZlZEeEgrNHh0WnROTkZPakg3YzZEL3ZXa0lnCldRVXhpd3Vzc2U2S01PV2pEbnYvNFZyamVsMlFnVVlVYkhDeWVaSG1jdGkrSzBMV0Nmby9SZzZQdWx3cmJEa2gKam1PZ1l0MzBwZGhYME9aa0F1a2xmVURIZnA4YmpiQ29JMnRhWUFCQTZBS2pLc08zNUxBRVU3OUNMMW1MVkh1WgpBQ0k1VWppamEzVlBXVkhTd21KUEp5dXhBZ01CQUFHalVEQk9NQjBHQTFVZERnUVdCQlFtbDVkVEFaaXhGS2hqCjkzd3VjUldoYW8vdFFqQWZCZ05WSFNNRUdEQVdnQlFtbDVkVEFaaXhGS2hqOTN3dWNSV2hhby90UWpBTUJnTlYKSFJNRUJUQURBUUgvTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFCK2tsa1JOSlVLQkxYOHlZa3l1VTJSSGNCdgpHaG1tRGpKSXNPSkhac29ZWGRMbEcxcFpORmpqUGFPTDh2aDQ0Vmw5OFJoRVpCSHNMVDFLTWJwMXN1NkNxajByClVHMWtwUkJlZitJT01UNE1VN3ZSSUNpN1VPbFJMcDFXcDBGOGxhM2hQT2NSYjJ5T2ZGcVhYeVpXWGY0dDBCNDUKdEhpK1pDTkhCOUZ4alNSeWNiR1lWaytUS3B2aEphU1lOTUdKM2R4REthUDcrRHgzWGNLNnNBbklBa2h5SThhagpOVSttdzgvdG1Sa1A0SW4va1hBUitSaTBxVW1Iai92d3ZuazRLbTdaVXkxRllIOERNZVM1TmtzbisvdUhsUnhSClY3RG5uMDM5VFJtZ0tiQXFONzJnS05MbzVjWit5L1lxREFZSFlybjk4U1FUOUpEZ3RJL0svQVRwVzhkWAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
+ tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBc0lVZ2Y2bHV2NUMyOXM2YnZoQ2J3L2NCeFdxdmtBUDlDUi95NVpjcU84d0JjZmh4CjZ2Z2pnRzVQZ3ZBZUxmeDFCTEo3T1VTOVBRbWZsK0krcVd5UlhTbmJqOFY3dVdWV0o1TVdLVkExTzhvT3praWsKbWMwNXlHZTl0N0RMTkVlbzJKL3c2NCtNVnpDUkh4MUE2bUhrbHBXYTk2b3RSQld0SE8zMVE4Ui91TWJXYlRUUgpUb3grM09nLzcxcENJRmtGTVlzTHJMSHVpakRsb3c1Ny8rRmE0M3Bka0lGR0ZHeHdzbm1SNW5MWXZpdEMxZ242ClAwWU9qN3BjSzJ3NUlZNWpvR0xkOUtYWVY5RG1aQUxwSlgxQXgzNmZHNDJ3cUNOcldtQUFRT2dDb3lyRHQrU3cKQkZPL1FpOVppMVI3bVFBaU9WSTRvMnQxVDFsUjBzSmlUeWNyc1FJREFRQUJBb0lCQUNFTkhET3JGdGg1a1RpUApJT3dxa2UvVVhSbUl5MHlNNHFFRndXWXBzcmUxa0FPMkFDWjl4YS96ZDZITnNlanNYMEM4NW9PbmtrTk9mUHBrClcxVS94Y3dLM1ZpRElwSnBIZ09VNzg1V2ZWRXZtU3dZdi9Fb1V3eHFHRVMvcnB5Z1drWU5WSC9XeGZGQlg3clMKc0dmeVltbXJvM09DQXEyLzNVVVFiUjcrT09md3kzSHdUdTBRdW5FSnBFbWU2RXdzdWIwZzhTTGp2cEpjSHZTbQpPQlNKSXJyL1RjcFRITjVPc1h1Vm5FTlVqV3BBUmRQT1NrRFZHbWtCbnkyaVZURElST3NGbmV1RUZ1NitXOWpqCmhlb1hNN2czbkE0NmlLenUzR0YwRWhLOFkzWjRmeE42NERkbWNBWnphaU1vMFJVaktWTFVqbVlQSEUxWWZVK3AKMkNYb3dNRUNnWUVBMTgyaU52UEkwVVlWaUh5blhKclNzd1YrcTlTRStvVi90U2ZSUUNGU2xsV0d3KzYyblRiVwpvNXpoL1RDQW9VTVNSbUFPZ0xKWU1LZUZ1SWdvTEoxN1pvWjN0U1czTlVtMmRpT0lPSHorcTQxQzM5MDRrUzM5CjkrYkFtVmtaSFA5VktLOEMraS9tek5mSkdHZEJadGIweWtTM2t3OUIxTHdnT3o3MDhFeXFSQ2tDZ1lFQTBXWlAKbzF2MThnV2tMK2FnUDFvOE13eDRPZlpTN3dKY3E0Z0xnUWhjYS9pSkttY0x0RFN4cUJHckJ4UVo0WTIyazlzdQpzTFVrNEJobGlVM29iUUJNaUdtMGtITHVBSEFRNmJvdWZBMUJwZjN2VFdHSkhSRjRMeFJsNzc2akw4UXI4VnpxClpURVBtY0R0T0hpYjdwb2I1Z2IzSDhiVGhYeUhmdGZxRW55alhFa0NnWUVBdk9DdDZZclZhTlQrWThjMmRFYk4Kd3dJOExBaUZtdjdkRjZFUjlCODJPWDRCeGR0WTJhRDFtNTNqN2NaVnpzNzFYOE1TN25FcDN1dkFqaElkbDI3KwpZbTJ1dUUyYVhIbDN5VTZ3RzBETFpUcnVIU0Z5TVI4ZithbHRTTXBDd0s1NXluSGpHVFp6dXpYaVBBbWpwRzdmCk1XbVRncE1IK3puc3UrNE9VNFBHUW9FQ2dZQWNqdUdKbS84YzlOd0JsR2lDZTJIK2JGTHhSTURteStHcm16QkcKZHNkMENqOWF3eGI3aXJ3MytjRGpoRUJMWExKcjA5YTRUdHdxbStrdElxenlRTG92V0l0QnNBcjVrRThlTVVBcAp0djBmRUZUVXJ0cXVWaldYNWlaSTNpMFBWS2ZSa1NSK2pJUmVLY3V3aWZKcVJpWkw1dU5KT0NxYzUvRHF3Yk93CnRjTHAwUUtCZ0VwdEw1SU10Sk5EQnBXbllmN0F5QVBhc0RWRE9aTEhNUGRpL2dvNitjSmdpUmtMYWt3eUpjV3IKU25QSG1TbFE0aEluNGMrNW1lbHBDWFdJaklLRCtjcTlxT2xmQmRtaWtYb2RVQ2pqWUJjNnVGQ1QrNWRkMWM4RwpiUkJQOUNtWk9GL0hOcHN0MEgxenhNd1crUHk5Q2VnR3hhZ0ZCekxzVW84N0xWR2h0VFFZCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
+```
+
+> Note: If your issuer represents an intermediate, ensure that `tls.crt` contains
+> the issuer's full chain in the correct order: `issuer -> intermediate(s) -> root`.
+> The root (self-signed) CA certificate is optional, but adding it will ensure that
+> the correct CA certificate is stored in the secrets for issued `Certificate`s under
+> the `ca.crt` key. If you fail to provide a complete chain, it might not be possible
+> for consumers of issued `Certificate`s to verify whether they're trusted.
+
+Next is to deploy the CA issuer which references this `Secret`. This is done by
+referencing the secret name under the `ca` stanza in the `Issuer` spec.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: ca-issuer
+ namespace: sandbox
+spec:
+ ca:
+ secretName: ca-key-pair
+```
+
+Optionally, you can specify [CRL](https://en.wikipedia.org/wiki/Certificate_revocation_list) Distribution Points; an array of strings each of which identifies the location of the CRL from which the revocation of this certificate can be checked.
+
+```yaml
+...
+spec:
+ ca:
+ secretName: ca-key-pair
+ crlDistributionPoints:
+ - "http://example.com"
+```
+
+Once deployed, you can then check that the issuer has been successfully
+configured by checking the ready status of the certificate. Replace `issuers`
+here with `clusterissuers` if that is what has been deployed.
+
+```bash
+$ kubectl get issuers ca-issuer -n sandbox -o wide
+NAME READY STATUS AGE
+ca-issuer True Signing CA verified 2m
+```
+
+Certificates are now ready to be requested by using the CA `Issuer` named
+`ca-issuer` within the `sandbox` namespace.
diff --git a/content/v1.13-docs/configuration/external.md b/content/v1.13-docs/configuration/external.md
new file mode 100644
index 0000000000..d4bc78088f
--- /dev/null
+++ b/content/v1.13-docs/configuration/external.md
@@ -0,0 +1,51 @@
+---
+title: External
+description: 'cert-manager configuration: External Issuers'
+---
+
+cert-manager supports external `Issuer` types. While external issuers are not
+implemented in the main cert-manager repository, they are otherwise treated the
+same as any other issuer.
+
+External issuers are typically deployed as a pod which is configured
+to watch for `CertificateRequest` resources in the cluster whose `issuerRef`
+matches the name of the issuer. External issuers exist outside of the
+`cert-manager.io` group.
+
+Installation for each issuer may differ; check the documentation for each
+external issuer for more details on installing, configuring and using it.
+
+## Known External Issuers
+
+If you've created an external issuer which you'd like to share,
+[raise a Pull Request](https://github.com/cert-manager/website/pulls) to have
+it added here!
+
+These external issuers are known to support and honor [approval](https://cert-manager.io/docs/concepts/certificaterequest/#approval).
+
+- [kms-issuer](https://github.com/Skyscanner/kms-issuer): Requests
+ certificates signed using an [AWS KMS](https://aws.amazon.com/kms/) asymmetric key.
+- [aws-privateca-issuer](https://github.com/cert-manager/aws-privateca-issuer): Requests
+ certificates from [AWS Private Certificate Authority](https://aws.amazon.com/certificate-manager/private-certificate-authority/)
+ for cloud native/hybrid environments.
+- [google-cas-issuer](https://github.com/jetstack/google-cas-issuer): Used
+ to request certificates signed by private CAs managed by the
+ [Google Cloud Certificate Authority Service](https://cloud.google.com/certificate-authority-service/).
+- [origin-ca-issuer](https://github.com/cloudflare/origin-ca-issuer): Used
+ to request certificates signed by
+ [Cloudflare Origin CA](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca)
+ to enable TLS between Cloudflare edge and your Kubernetes workloads.
+- [step-issuer](https://github.com/smallstep/step-issuer): Requests
+ certificates from the [Smallstep](https://smallstep.com) [Certificate Authority server](https://github.com/smallstep/certificates).
+- [freeipa-issuer](https://github.com/guilhem/freeipa-issuer): Requests
+ certificates signed by [FreeIPA](https://www.freeipa.org).
+- [ADCS Issuer](https://github.com/nokia/adcs-issuer): Requests
+ certificates signed by [Microsoft Active Directory Certificate Service](https://docs.microsoft.com/en-us/windows-server/networking/core-network-guide/cncg/server-certs/install-the-certification-authority).
+ [NOT MAINTAINED]
+- [CFSSL Issuer](https://gerrit.wikimedia.org/r/plugins/gitiles/operations/software/cfssl-issuer/): Request certificates signed by a [CFSSL](https://github.com/cloudflare/cfssl) `multirootca` instance.
+- [ncm-issuer](https://github.com/nokia/ncm-issuer): Requests certificates from the [Nokia](https://www.nokia.com/) [Netguard Certificate Manager](https://www.nokia.com/networks/security-portfolio/netguard/certificate-manager)
+- [tcs-issuer](https://github.com/intel/trusted-certificate-issuer) Requests certificates signed securely using [Intel's SGX technology](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/overview.html).
+
+## Building New External Issuers
+
+If you're interested in building a new external issuer, check the [development documentation](../contributing/external-issuers.md).
diff --git a/content/v1.13-docs/configuration/selfsigned.md b/content/v1.13-docs/configuration/selfsigned.md
new file mode 100644
index 0000000000..bfc2b39b2b
--- /dev/null
+++ b/content/v1.13-docs/configuration/selfsigned.md
@@ -0,0 +1,171 @@
+---
+title: SelfSigned
+description: 'cert-manager configuration: SelfSigned Issuers'
+---
+
+⚠️ `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](#caveats) - including security issues - to
+consider with `SelfSigned` issuers; in general you'd likely want to use a
+[`CA`](./ca.md) issuer rather than a `SelfSigned` issuer. That said,
+`SelfSigned` issuers are really useful for initially [bootstrapping](#bootstrapping-ca-issuers)
+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:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: selfsigned-issuer
+ namespace: sandbox
+spec:
+ selfSigned: {}
+```
+
+```yaml
+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:
+
+```bash
+$ 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`](./ca.md)
+issuer.
+
+The YAML below will create a `SelfSigned` issuer, issue a root certificate and
+use that root as a `CA` issuer:
+
+```yaml
+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
+```
+
+### CRL Distribution Points
+
+You may also optionally specify [CRL](https://en.wikipedia.org/wiki/Certificate_revocation_list)
+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:
+
+```yaml
+...
+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](../projects/trust-manager/README.md) 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](https://tools.ietf.org/html/rfc5280#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](https://github.com/cert-manager/cert-manager/blob/45befd86966c563663d18848943a1066d9681bf8/pkg/controller/certificaterequests/selfsigned/selfsigned.go#L140)
+of type `BadConfig` if it detects that a certificate is being created
+by a `SelfSigned` issuer which has an empty Issuer DN.
diff --git a/content/v1.13-docs/configuration/vault.md b/content/v1.13-docs/configuration/vault.md
new file mode 100644
index 0000000000..f2b15b5435
--- /dev/null
+++ b/content/v1.13-docs/configuration/vault.md
@@ -0,0 +1,387 @@
+---
+title: Vault
+description: 'cert-manager configuration: Vault Issuers'
+---
+
+The `Vault` `Issuer` represents the certificate authority
+[Vault](https://www.vaultproject.io/) - a multi-purpose secret store that can be
+used to sign certificates for your Public Key Infrastructure (PKI). Vault is an
+external project to cert-manager and as such, this guide will assume it has been
+configured and deployed correctly, ready for signing. You can read more on how
+to configure Vault as a certificate authority
+[here](https://www.vaultproject.io/docs/secrets/pki/).
+
+This `Issuer` type is typically used when Vault is already being used within
+your infrastructure, or you would like to make use of its feature set where the
+CA issuer alone cannot provide.
+
+## Deployment
+
+All Vault issuers share common configuration for requesting certificates,
+namely the server, path, and CA bundle:
+
+- Server is the URL whereby Vault is reachable.
+- Path is the Vault path that will be used for signing. Note that the path
+ *must* use the `sign` endpoint.
+- CA bundle denotes an optional field containing a base64 encoded string of the
+ Certificate Authority to trust the Vault connection. This is typically
+ _always_ required when using an `https` URL.
+
+Below is an example of a configuration to connect a Vault server.
+
+> **Warning**: This configuration is incomplete as no authentication methods have
+> been added.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vault-issuer
+ namespace: sandbox
+spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ ...
+```
+
+## Authenticating
+
+In order to request signing of certificates by Vault, the issuer must be able to
+properly authenticate against it. cert-manager provides multiple approaches to
+authenticating to Vault which are detailed below.
+
+### Authenticating via an AppRole
+
+An [AppRole](https://www.vaultproject.io/docs/auth/approle.html) is a method of
+authenticating to Vault through use of its internal role policy system. This
+authentication method requires that the issuer has possession of the `SecretID`
+secret key, the `RoleID` of the role to assume, and the app role path. Firstly,
+the secret ID key must be stored within a Kubernetes `Secret` that resides in the
+same namespace as the `Issuer`, or otherwise inside the `Cluster Resource
+Namespace` in the case of a `ClusterIssuer`.
+
+```yaml
+apiVersion: v1
+kind: Secret
+type: Opaque
+metadata:
+ name: cert-manager-vault-approle
+ namespace: sandbox
+data:
+ secretId: "MDI..."
+```
+
+Once the `Secret` has been created, the `Issuer` is ready to be deployed which
+references this `Secret`, as well as the data key of the field that stores the
+secret ID.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vault-issuer
+ namespace: sandbox
+spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ appRole:
+ path: approle
+ roleId: "291b9d21-8ff5-..."
+ secretRef:
+ name: cert-manager-vault-approle
+ key: secretId
+```
+
+### Authenticating with a Token
+
+This method of authentication uses a token string that has been generated from
+one of the many authentication backends that Vault supports. These tokens have
+an expiry and so need to be periodically refreshed. You can read more on Vault
+tokens [here](https://www.vaultproject.io/docs/concepts/tokens.html).
+
+> **Note**: cert-manager does not refresh these token automatically and so another
+> process must be put in place to do this.
+
+Firstly, the token is be stored inside a Kubernetes `Secret` inside the same
+namespace as the `Issuer` or otherwise in the `Cluster Resource Namespace` in
+the case of using a `ClusterIssuer`.
+
+```yaml
+apiVersion: v1
+kind: Secret
+type: Opaque
+metadata:
+ name: cert-manager-vault-token
+ namespace: sandbox
+data:
+ token: "MjI..."
+```
+
+Once submitted, the Vault issuer is able to be created using token
+authentication by referencing this `Secret` along with the key of the field the
+token data is stored at.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vault-issuer
+ namespace: sandbox
+spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ tokenSecretRef:
+ name: cert-manager-vault-token
+ key: token
+```
+
+
+
+### Authenticating with Kubernetes Service Accounts
+
+The [Vault Kubernetes
+Auth](https://developer.hashicorp.com/vault/docs/auth/kubernetes) allows
+cert-manager to authenticate to Vault using a Kubernetes Service Account Token
+in order to issue certificates using Vault as a certification authority. The
+Kubernetes service account token can be provided in two ways:
+
+- [Secretless Authentication with a Service Account](#secretless-authentication-with-a-service-account) (recommended),
+- [Authentication with a Static Service Account Token](#static-service-account-token).
+
+#### Secretless Authentication with a Service Account
+
+ℹ️ This feature is available in cert-manager >= v1.12.0.
+
+With the secretless authentication with a service account, cert-manager creates
+an ephemeral service account token using the TokenRequest API and uses it to
+authenticate with Vault. These tokens are short-lived (10 minutes) and are
+never stored to disk.
+
+This is the recommended authentication method because it does not rely on the
+deprecated static service account tokens. The static service account tokens pose
+a threat due to their infinite lifetime. Static service account tokens have been
+disabled by default on Kubernetes 1.24.
+
+The first step is to create a `ServiceAccount` resource:
+
+```sh
+kubectl create serviceaccount -n sandbox vault-issuer
+```
+
+Then add an RBAC Role so that cert-manager can get tokens for the
+ServiceAccount:
+
+```yaml
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: vault-issuer
+ namespace: sandbox
+rules:
+ - apiGroups: ['']
+ resources: ['serviceaccounts/token']
+ resourceNames: ['vault-issuer']
+ verbs: ['create']
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: vault-issuer
+ namespace: sandbox
+subjects:
+ - kind: ServiceAccount
+ name: cert-manager
+ namespace: cert-manager
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: vault-issuer
+```
+
+Finally, create the Issuer resource:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vault-issuer
+ namespace: sandbox
+spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ auth:
+ kubernetes:
+ role: my-app-1
+ mountPath: /v1/auth/kubernetes
+ serviceAccountRef:
+ name: vault-issuer
+```
+
+> **Issuer vs. ClusterIssuer:** With an Issuer resource, you can only refer to a
+> service account located in the same namespace as the Issuer. With a
+> ClusterIssuer, the service account must be located in the namespace that is
+> configured by the flag `--cluster-resource-namespace`.
+
+To create the role in Vault, you can use the following command:
+
+```bash
+vault write auth/kubernetes/role/vault-issuer \
+ bound_service_account_names=vault-issuer \
+ bound_service_account_namespaces=sandbox \
+ audience="vault://sandbox/vault-issuer" \
+ policies=vault-issuer \
+ ttl=1m
+```
+
+It is recommended to use a different Vault role each per Issuer or
+ClusterIssuer. The `audience` allows you to restrict the Vault role to a single
+Issuer or ClusterIssuer. The syntax is the following:
+
+```yaml
+"vault:///" # For an Issuer.
+"vault://" # For a ClusterIssuer.
+```
+
+The expiration duration for the Kubernetes tokens that are requested is
+hard-coded to 10 minutes (that's the minimum accepted). The `ttl` field can be
+as short as possible, since cert-manager requests a new token every time it
+needs to talks to Vault.
+
+Although it is not recommended, you can also use the same Vault role for all of
+your Issuers and ClusterIssuers by omitting the `audience` field and re-using
+the same service account.
+
+
+#### Authentication with a Static Service Account Token
+
+For the Vault issuer to use this authentication, cert-manager must get access to
+the token that is stored in a Kubernetes `Secret`. Kubernetes Service Account
+Tokens are already stored in `Secret` resources however, you must ensure that
+it is present in the same namespace as the `Issuer`, or otherwise in the
+`Cluster Resource Namespace` in the case of using a `ClusterIssuer`.
+
+> **Note**: In Kubernetes 1.24 onwards, the token secret is no longer created
+> by default for the Service Account. In this case you need to manually create
+> the secret resource. See [this guide](https://kubernetes.io/docs/concepts/configuration/secret/#service-account-token-secrets)
+> for more details.
+
+This authentication method also expects a `role` field which is the Vault role
+that the Service Account is to assume, as well as an optional `mountPath` field which
+is the authentication mount path, defaulting to `kubernetes`.
+
+#### Kubernetes version less than 1.24
+
+The following example will be making use of the Service Account
+`my-service-account`. The secret data field key will be `token` if the `Secret`
+has been created by Kubernetes. The Vault role used is `my-app-1`, using the
+default mount path of `/v1/auth/kubernetes`
+
+1) Create the Service Account:
+
+ ```shell
+ kubectl create serviceaccount -n sandbox vault-issuer
+ ```
+
+1) Get the auto-generated Secret name:
+
+ ```shell
+ kubectl get secret -o json | jq -r '.items[] | select(.metadata.annotations["kubernetes.io/service-account.name"] == "vault-issuer") | .metadata.name'
+ ```
+
+1) Create the Issuer using that Secret name retrieved from the previous step:
+
+ ```yaml
+ apiVersion: cert-manager.io/v1
+ kind: Issuer
+ metadata:
+ name: vault-issuer
+ namespace: sandbox
+ spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ kubernetes:
+ role: my-app-1
+ mountPath: /v1/auth/kubernetes
+ secretRef:
+ name:
+ key: token
+ ```
+
+#### Kubernetes version 1.24 and greater
+
+This example is almost the same as above but adjusted for the change in
+Kubernetes 1.24 and above.
+
+1) Create the Service Account:
+
+ ```shell
+ kubectl create serviceaccount -n sandbox vault-issuer
+ ```
+
+1) Create the Secret resource for Kubernetes to populate the `token` value:
+
+ ```yaml
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ name: vault-issuer-token
+ annotations:
+ kubernetes.io/service-account.name: "vault-issuer"
+ type: kubernetes.io/service-account-token
+ data: {}
+ ```
+
+1) Create the Issuer resource referencing the Secret resource:
+
+ ```yaml
+ apiVersion: cert-manager.io/v1
+ kind: Issuer
+ metadata:
+ name: vault-issuer
+ namespace: sandbox
+ spec:
+ vault:
+ path: pki_int/sign/example-dot-com
+ server: https://vault.local
+ caBundle:
+ auth:
+ kubernetes:
+ role: my-app-1
+ mountPath: /v1/auth/kubernetes
+ secretRef:
+ name: vault-issuer-token
+ key: token
+ ```
+
+## Verifying the issuer Deployment
+
+Once the Vault issuer has been deployed, it will be marked as ready if the
+configuration is valid. Replace `issuers` below with `clusterissuers` if that is what has
+been deployed.
+
+The Vault issuer tests your Vault instance by querying the `v1/sys/health`
+endpoint, to ensure your Vault instance is unsealed and initialized before
+requesting certificates. The result of that query will populate the `STATUS`
+column.
+
+```bash
+$ kubectl get issuers vault-issuer -n sandbox -o wide
+NAME READY STATUS AGE
+vault-issuer True Vault verified 2m
+```
+
+Certificates are now ready to be requested by using the Vault issuer named
+`vault-issuer` within the `sandbox` namespace.
diff --git a/content/v1.13-docs/configuration/venafi.md b/content/v1.13-docs/configuration/venafi.md
new file mode 100644
index 0000000000..29cbbd04c7
--- /dev/null
+++ b/content/v1.13-docs/configuration/venafi.md
@@ -0,0 +1,282 @@
+---
+title: Venafi
+description: 'cert-manager configuration: Venafi Issuers'
+---
+
+## Introduction
+
+The Venafi `Issuer` types allows you to obtain certificates from [Venafi
+as a Service (VaaS)](https://vaas.venafi.com/jetstack) and [Venafi Trust Protection
+Platform (TPP)](https://www.venafi.com/platform/tls-protect) instances.
+
+You can have multiple different Venafi `Issuer` types installed within the same
+cluster, including mixtures of Venafi as a Service and TPP issuer types. This allows
+you to be flexible with the types of Venafi account you use.
+
+Automated certificate renewal and management are provided for `Certificates`
+using the Venafi `Issuer`.
+
+A single Venafi `Issuer` represents a single Venafi 'zone' so you must create one
+`Issuer` resource for each zone you want to use. A zone is a single entity that
+combines the policy that governs certificate issuance with information about how
+certificates are organized in Venafi to identify the business application and
+establish ownership.
+
+You can configure your `Issuer` resource to either issue certificates only
+within a single namespace, or cluster-wide (using a `ClusterIssuer` resource).
+For more information on the distinction between `Issuer` and `ClusterIssuer`
+resources, read the [Namespaces](../concepts/issuer.md#namespaces) section.
+
+## Creating a Venafi as a Service Issuer
+
+If you haven't already done so, create your Venafi as a Service account on this
+[page](https://vaas.venafi.com/jetstack) and copy the API key from your user
+preferences. Then you may want to create a custom CA Account and Issuing Template
+or choose instead to use defaults that are automatically created for testing
+("Built-in CA" and "Default", respectively). Lastly you'll need to create an
+Application for establishing ownership of all the certificates requested by your
+cert-manager Issuer, and assign to it the Issuing Template.
+
+> Make a note of the Application name and API alias of the Issuing Template because
+> together they comprise the 'zone' you will need for your `Issuer` configuration.
+
+In order to set up a Venafi as a Service `Issuer`, you must first create a Kubernetes
+`Secret` resource containing your Venafi as a Service API credentials:
+
+```bash
+$ kubectl create secret generic \
+ vaas-secret \
+ --namespace='NAMESPACE OF YOUR ISSUER RESOURCE' \
+ --from-literal=apikey='YOUR_VAAS_API_KEY_HERE'
+```
+
+> **Note**: If you are configuring your issuer as a `ClusterIssuer` resource in
+> order to serve `Certificates` across your whole cluster, you must set the
+> `--namespace` parameter to `cert-manager`, which is the default `Cluster
+> Resource Namespace`. The `Cluster Resource Namespace` can be configured
+> through the `--cluster-resource-namespace` flag on the cert-manager controller
+> component.
+
+This API key will be used by cert-manager to interact with Venafi as a Service
+on your behalf.
+
+Once the API key `Secret` has been created, you can create your `Issuer` or
+`ClusterIssuer` resource. If you are creating a `ClusterIssuer` resource, you
+must change the `kind` field to `ClusterIssuer` and remove the
+`metadata.namespace` field.
+
+Save the below content after making your amendments to a file named
+`vaas-issuer.yaml`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vaas-issuer
+ namespace:
+spec:
+ venafi:
+ zone: "My Application\My CIT" # Set this to \
+ cloud:
+ apiTokenSecretRef:
+ name: vaas-secret
+ key: apikey
+```
+
+You can then create the Issuer using `kubectl create`.
+
+```bash
+$ kubectl create -f vaas-issuer.yaml
+```
+
+Verify the `Issuer` has been initialized correctly using `kubectl describe`.
+
+```bash
+$ kubectl get issuer vaas-issuer --namespace='NAMESPACE OF YOUR ISSUER RESOURCE' -o wide
+NAME READY STATUS AGE
+vaas-issuer True Venafi issuer started 2m
+```
+
+You are now ready to issue certificates using the newly provisioned Venafi
+`Issuer` and Venafi as a Service.
+
+Read the [Requesting Certificates](../usage/certificate.md) document for
+more information on how to create Certificate resources.
+
+
+## Creating a Venafi Trust Protection Platform Issuer
+
+The Venafi Trust Protection Platform integration allows you to obtain certificates
+from a properly configured Venafi TPP instance.
+
+The setup is similar to the Venafi as a Service configuration above, however some
+of the connection parameters are slightly different.
+
+> **Note**: You *must* allow "User Provided CSRs" as part of your TPP policy, as
+> this is the only type supported by cert-manager at this time.
+>
+> More specifically, the valid configurations of the "CSR handling" are:
+>
+> - "User Provided CSRs" selected and unlocked,
+> - "User Provided CSRs" selected and locked,
+> - "Service Generated CSRs" selected and unlocked.
+>
+> When using "Service Generated CSRs" selected and unlocked, the default CSR
+> configuration present in your policy folder will override the configuration of
+> your Certificate resource. The subject DN, key algorithm, and key size will be
+> overridden by the values set in the policy folder.
+>
+> With "Service Generated CSRs" selected and locked, the certificate issuance
+> will systematically fail with the following message:
+>
+> ```plain
+> 400 PKCS#10 data will not be processed. Policy "\VED\Policy\foo" is locked to a Server Generated CSR.
+> ```
+
+In order to set up a Venafi Trust Protection Platform `Issuer`, you must first
+create a Kubernetes `Secret` resource containing your Venafi TPP API
+credentials.
+
+### Access Token Authentication
+
+1. [Set up token authentication](https://docs.venafi.com/Docs/23.1/TopNav/Content/SDK/AuthSDK/t-SDKa-Setup-OAuth.php).
+
+ NOTE: Do not select "Refresh Token Enabled" and set a *long* "Token Validity (days)".
+
+2. Create a new user with sufficient privileges to manage and revoke certificates in a particular policy folder (zone).
+
+ E.g. `k8s-xyz-automation`
+
+3. [Create a new application integration](https://docs.venafi.com/Docs/21.4/TopNav/Content/API-ApplicationIntegration/t-APIAppIntegrations-creatingNew-Aperture.php)
+
+ Create an application integration with name and ID `cert-manager`.
+ Set the "API Access Settings" to `Certificates: Read,Manage,Revoke`.
+
+ "Edit Access" to the new application integration, and allow it to be used by the user you created earlier.
+
+4. [Generate an access token](https://github.com/Venafi/vcert/blob/master/README-CLI-PLATFORM.md#obtaining-an-authorization-token)
+
+ ```
+ vcert getcred \
+ --username k8s-xyz-automation \
+ --password somepassword \
+ -u https://tpp.example.com/vedsdk \
+ --client-id cert-manager \
+ --scope "certificate:manage,revoke"
+ ```
+
+ This will print an access-token to `stdout`. E.g.
+
+ ```
+ vCert: 2020/10/07 16:34:27 Getting credentials
+ access_token: I69n.............y1VjNJT3o9U0Wko19g==
+ access_token_expires: 2021-01-05T15:34:30Z
+ ```
+
+5. Save the access-token to a Secret in the Kubernetes cluster
+
+```bash
+$ kubectl create secret generic \
+ tpp-secret \
+ --namespace= \
+ --from-literal=access-token='YOUR_TPP_ACCESS_TOKEN'
+```
+
+### Username / Password Authentication
+
+> ⚠️ When you supply a Venafi TPP username and password,
+> cert-manager uses an older authentication method which is called "API Keys",
+> which has been deprecated since Venafi TPP `19.2`.
+>
+> Beginning in Venafi TPP `22.2`, "API Keys" are disabled by default.
+> You will need to contact Venafi customer support for a special license key which will allow you to re-enable the "API Keys" feature,
+> so that you can continue to use username and password authentication with cert-manager.
+>
+> In Venafi TPP `22.3`, the "API Keys" feature will be permanently removed,
+> and you will need to use access-token authentication instead.
+>
+> 📖 Read [Deprecated functionality from Venafi Platform](https://docs.venafi.com/22.3/deprecation-list-current)
+> and [Functionality Scheduled for Deprecation](https://support.venafi.com/hc/en-us/articles/115001662292) for more information.
+
+```bash
+$ kubectl create secret generic \
+ tpp-secret \
+ --namespace= \
+ --from-literal=username='YOUR_TPP_USERNAME_HERE' \
+ --from-literal=password='YOUR_TPP_PASSWORD_HERE'
+```
+
+> Note: If you are configuring your issuer as a `ClusterIssuer` resource in
+> order to issue `Certificates` across your whole cluster, you must set the
+> `--namespace` parameter to `cert-manager`, which is the default `Cluster
+> Resource Namespace`. The `Cluster Resource Namespace` can be configured
+> through the `--cluster-resource-namespace` flag on the cert-manager controller
+> component.
+
+These credentials will be used by cert-manager to interact with your Venafi TPP
+instance. Username attribute must be adhere to the `:` format. For example: `local:admin`.
+
+Once the Secret containing credentials has been created, you can create your
+`Issuer` or `ClusterIssuer` resource. If you are creating a `ClusterIssuer`
+resource, you must change the `kind` field to `ClusterIssuer` and remove the
+`metadata.namespace` field.
+
+Save the below content after making your amendments to a file named
+`tpp-issuer.yaml`.
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: tpp-issuer
+ namespace:
+spec:
+ venafi:
+ zone: \VED\Policy\devops\cert-manager # Set this to the Venafi policy folder you want to use
+ tpp:
+ url: https://tpp.venafi.example/vedsdk # Change this to the URL of your TPP instance
+ caBundle:
+ credentialsRef:
+ name: tpp-secret
+```
+
+You can then create the `Issuer` using `kubectl create -f`.
+
+```bash
+$ kubectl create -f tpp-issuer.yaml
+```
+
+Verify the `Issuer` has been initialized correctly using `kubectl describe`.
+
+```bash
+$ kubectl describe issuer tpp-issuer --namespace='NAMESPACE OF YOUR ISSUER RESOURCE'
+```
+
+You are now ready to issue certificates using the newly provisioned Venafi
+`Issuer` and Trust Protection Platform.
+
+Read the [Requesting Certificates](../usage/certificate.md) document for
+more information on how to create Certificate resources.
+
+## Issuer specific annotations
+
+### Custom Fields
+
+Starting `v0.14` you can pass custom fields to Venafi (TPP version `v19.2` and higher) using the `venafi.cert-manager.io/custom-fields` annotation on Certificate resources.
+The value is a JSON encoded array of custom field objects having a `name` and `value` key.
+For example:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: example-com-certificate
+ annotations:
+ venafi.cert-manager.io/custom-fields: |-
+ [
+ {"name": "field-name", "value": "field value"},
+ {"name": "field-name-2", "value": "field value 2"}
+ ]
+...
+```
diff --git a/content/v1.13-docs/faq/README.md b/content/v1.13-docs/faq/README.md
new file mode 100644
index 0000000000..6f885591a7
--- /dev/null
+++ b/content/v1.13-docs/faq/README.md
@@ -0,0 +1,180 @@
+---
+title: Frequently Asked Questions (FAQ)
+description: Find answers to some frequently asked questions about cert-manager
+---
+
+On this page you will find answers to some frequently asked questions about cert-manager.
+
+## Terminology
+
+### What does `publicly trusted` and `self-signed` mean?
+
+These terms are defined in the [TLS Terminology page](../reference/tls-terminology.md).
+
+### What do the terms `root`, `intermediate` and `leaf` _certificate_ mean?
+
+These terms are defined in the [TLS Terminology page](../reference/tls-terminology.md).
+
+## Certificates
+
+### Can I trigger a renewal from cert-manager at will?
+
+This is a feature in cert-manager starting in `v0.16` using the `cmctl` CLI. More information can be found on [the renew command's page](../reference/cmctl.md#renew)
+
+### When do certs get re-issued?
+
+To determine if a certificate needs to be re-issued, cert-manager looks at the the spec of `Certificate` resource and latest `CertificateRequest`s as well as the data in `Secret` containing the X.509 certificate.
+
+The issuance process will always get triggered if the:
+
+- `Secret` named on `Certificate`'s spec, does not exist, is missing private key or certificate data or contains corrupt data
+- private key stored in the `Secret` does not match the private key spec on `Certificate`
+- public key of the issued certificate does not match the private key stored in the `Secret`
+- cert-manager issuer annotations on the `Secret` do not match the issuer specified on the `Certificate`
+- DNS names, IP addresses, URLS or email addresses on the issued certificate do not match those on the `Certificate` spec
+- certificate needs to be renewed (because it has expired or the renewal time is now or in the past)
+- certificate has been marked for renewal manually [using `cmctl`](../reference/cmctl.md#renew)
+
+Additionally, if the latest `CertificateRequest` for the `Certificate` is found, cert-manager will also re-issue if:
+
+- the common name on the CSR found on the `CertificateRequest` does not match that on the `Certificate` spec
+- the subject fields on the CSR found on the `CertificateRequest` do not match the subject fields of the `Certificate` spec
+- the duration on the `CertificateRequest` does not match the duration on the `Certificate` spec
+- `isCA` field value on the `Certificate` spec does not match that on the `CertificateRequest`
+- the DNS names, IP addresses, URLS or email addresses on the `CertificateRequest` spec do not match those on the `Certificate` spec
+- key usages on the `CertificateRequest` spec do not match those on the `Certificate` spec
+
+Note that for certain fields re-issuance on change gets triggered only if there
+is a `CertificateRequest` that cert-manager can use to determine whether
+`Certificate`'s spec has changed since the previous issuance. This is because
+some issuers may not respect the requested values for these fields, so we cannot
+rely on the values in the issued X.509 certificates. One such field is
+`.spec.duration`- change to this field will only trigger re-issuance if there is
+a `CertificateRequest` to compare with. In case where you need to re-issue, but
+re-issuance does not get triggered automatically due to there being no
+`CertificateRequest` (i.e after backup and restore), you can use [`cmctl
+renew`](../reference/cmctl.md#renew) to trigger it manually.
+
+### Why isn't my root certificate in my issued Secret's `tls.crt`?
+
+Occasionally, people work with systems which have made a flawed choice regarding TLS chains. The [TLS spec](https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.2)
+has the following section for the "Server Certificate" section of the TLS handshake:
+
+> This is a sequence (chain) of certificates. The sender's
+> certificate MUST come first in the list. Each following
+> certificate MUST directly certify the one preceding it. Because
+> certificate validation requires that root keys be distributed
+> independently, the self-signed certificate that specifies the root
+> certificate authority MAY be omitted from the chain, under the
+> assumption that the remote end must already possess it in order to
+> validate it in any case.
+
+In a standard, secure and correctly configured TLS environment, adding a root certificate to the chain is
+almost always unnecessary and wasteful.
+
+There are two ways that a certificate can be trusted:
+
+- explicitly, by including it in a trust store.
+- through a signature, by following the certificate's chain back up to an explicitly trusted certificate.
+
+Crucially, root certificates are by definition self-signed and they cannot be validated through a signature.
+
+As such, if we have a client trying to validate the certificate chain sent by the server, the client must already have the
+root before the connection is started. If the client already has the root, there was no point in it being sent by the server!
+
+The same logic with not sending root certificates applies for servers trying to validate client certificates;
+the [same justification](https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.6) is given in the TLS RFC.
+
+### How can I see all the historic events related to a certificate object?
+
+cert-manager publishes all events to the Kubernetes events mechanism, you can get the events for your specific resources using `kubectl describe