<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RSA on Digi Hunch</title><link>https://static.digihunch.com/tag/rsa/</link><description>Recent content in RSA on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Wed, 02 Apr 2025 13:22:24 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/rsa/index.xml" rel="self" type="application/rss+xml"/><item><title>Creating X.509 TLS certificate for workload on Kubernetes</title><link>https://static.digihunch.com/2021/08/creating-tls-certificate-kubernetes/</link><pubDate>Sun, 29 Aug 2021 23:19:00 -0400</pubDate><guid>https://static.digihunch.com/2021/08/creating-tls-certificate-kubernetes/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-k8s-x509.webp" alt="Featured image of post Creating X.509 TLS certificate for workload on Kubernetes" /&gt;&lt;p class="wp-block-paragraph"&gt;In deployment automation, I often had to create self-signed X.509 certificate for testing TLS traffic into Kubernetes. Sometimes self-signed, sometimes signed by a CA. This post summarized the approaches I&amp;#8217;ve taken.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="create-self-signed-certificate-with-openssl"&gt;Create self-signed certificate with OpenSSL&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Traditionally, this is done in three OpenSSL commands:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days &lt;span style="color:#ae81ff"&gt;356&lt;/span&gt; -nodes -subj &lt;span style="color:#e6db74"&gt;&amp;#39;/CN=Health Certificate Authority&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj &lt;span style="color:#e6db74"&gt;&amp;#39;/CN=*.orthweb.com&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl x509 -req -sha256 -days &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; -in server.csr -CA ca.crt -CAkey ca.key -set_serial &lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; -out server.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;I have an older post to cover the basics of cryptography in TLS certificate and PKI. In the three commands above, the first produces a private key and self-signed certificate for a CA. The second creates a private key and a CSR for the web site. The third one uses the CA&amp;#8217;s signing private key to sign the CSR from the website. The output is the certificate for the website. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Workloads running in Kubernetes typically consume certificates stored in Kubernetes Secret. The cons of this approach is that it usually requires an extra step to import the certificate files into Kubernetes Secret. For example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl create -n orthweb secret generic orthweb-cred --from-file&lt;span style="color:#f92672"&gt;=&lt;/span&gt;tls.key&lt;span style="color:#f92672"&gt;=&lt;/span&gt;server.key --from-file&lt;span style="color:#f92672"&gt;=&lt;/span&gt;tls.crt&lt;span style="color:#f92672"&gt;=&lt;/span&gt;server.crt --from-file&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ca.crt&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ca.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Note, people use the term self-signed certificate loosely. It sometimes means literally a certificate that is self-signed, like the one generated above. Sometimes, I had to self-sign a CA, then use the CA to sign one certificate for the server and one for the client. Because the application being tested requires that the client and server&amp;#8217;s certificates both under the same CA. This would involve a few more commands, for example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Self-sign a CA&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl req -x509 -sha256 -newkey rsa:4096 -days &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; -nodes -subj /C&lt;span style="color:#f92672"&gt;=&lt;/span&gt;CA/ST&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Ontario/L&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Waterloo/O&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Digihunch/OU&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Imaging/CN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;issuer.digihunch.com/emailAddress&lt;span style="color:#f92672"&gt;=&lt;/span&gt;info@www.digihunch.com -keyout /tmp/ca.key -out /tmp/ca.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Generate a CSR for server&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl req -new -newkey rsa:4096 -nodes -subj /C&lt;span style="color:#f92672"&gt;=&lt;/span&gt;CA/ST&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Ontario/L&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Waterloo/O&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Digihunch/OU&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Imaging/CN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;server.digihunch.com/emailAddress&lt;span style="color:#f92672"&gt;=&lt;/span&gt;orthweb@www.digihunch.com -addext extendedKeyUsage&lt;span style="color:#f92672"&gt;=&lt;/span&gt;serverAuth -addext subjectAltName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;DNS:orthweb.digihunch.com,DNS:server2.digihunch.com -keyout /tmp/server.key -out /tmp/server.csr&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Use the self-signed CA to issue a certificate to the server&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl x509 -req -sha256 -days &lt;span style="color:#ae81ff"&gt;3650&lt;/span&gt; -in /tmp/server.csr -CA /tmp/ca.crt -CAkey /tmp/ca.key -set_serial &lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; -out /tmp/server.crt -extfile &amp;lt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;echo subjectAltName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;DNS:orthweb.digihunch.com,DNS:server2.digihunch.com&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Generate a CSR for clietn&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl req -new -newkey rsa:4096 -nodes -subj /C&lt;span style="color:#f92672"&gt;=&lt;/span&gt;CA/ST&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Ontario/L&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Waterloo/O&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Digihunch/OU&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Imaging/CN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;client.digihunch.com/emailAddress&lt;span style="color:#f92672"&gt;=&lt;/span&gt;client@www.digihunch.com -keyout /tmp/client.key -out /tmp/client.csr&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Use the self-signed CA to issue a certificate to the client&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl x509 -req -sha256 -days &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; -in /tmp/client.csr -CA /tmp/ca.crt -CAkey /tmp/ca.key -set_serial &lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; -out /tmp/client.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;In the example above, it is important to note that even though the server&amp;#8217;s CSR contains subject alternative name (SAN), I still have to specify the SAN again when signing the certificate for the server. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Similar to OpenSSL there are other toolkits such as CFSSL that supports specifying configuration files. However, the steps in Shell command are generally not always easy to automate.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="create-self-signed-certificate-with-helm"&gt;Create self-signed certificate with Helm&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Moving to the context of workload deployment in Kubernetes, running openSSL command isn&amp;#8217;t always a viable option. For example, generating a certificate in the middle of deployment using a Helm Chart. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In &lt;a href="https://static.digihunch.com/2021/07/helm-configuration-management-for-kubernetes-resources/"&gt;Helm&lt;/a&gt;, template functions is for this purpose. In my Korthweb &lt;a href="https://github.com/digihunch/korthweb/blob/6480dad21490c0bfae27316093e533d68ecf04a2/orthanc/templates/tls-secrets.yaml#L4"&gt;project&lt;/a&gt; I used genSignedCert to create self-signed certificate and then store the key, certificate and CA certificate as Kubernetes Secret:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;{{&lt;/span&gt;- $dbtlscert :&lt;span style="color:#f92672"&gt;=&lt;/span&gt; genSignedCert .Values.dbtls.certCommonName nil &lt;span style="color:#f92672"&gt;(&lt;/span&gt;list .Values.dbtls.certCommonName&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; $ca &lt;span style="color:#f92672"&gt;}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: Secret&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: &lt;span style="color:#f92672"&gt;{{&lt;/span&gt; .Values.dbtls.certCommonName | quote &lt;span style="color:#f92672"&gt;}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; namespace: &lt;span style="color:#f92672"&gt;{{&lt;/span&gt; $.Release.Namespace | quote &lt;span style="color:#f92672"&gt;}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;type: kubernetes.io/tls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;data:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tls.crt: &lt;span style="color:#f92672"&gt;{{&lt;/span&gt; $dbtlscert.Cert | b64enc | quote &lt;span style="color:#f92672"&gt;}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tls.key: &lt;span style="color:#f92672"&gt;{{&lt;/span&gt; $dbtlscert.Key | b64enc | quote &lt;span style="color:#f92672"&gt;}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ca.crt: &lt;span style="color:#f92672"&gt;{{&lt;/span&gt; $ca.Cert | b64enc | quote &lt;span style="color:#f92672"&gt;}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;{{&lt;/span&gt;- end &lt;span style="color:#f92672"&gt;}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The cons of this approach is that the syntax is not straightforward. As indicated in Helm &lt;a href="https://helm.sh/docs/topics/charts/#templates-and-values"&gt;documentation&lt;/a&gt;: Helm Chart templates are written in the&amp;nbsp;&lt;a href="https://golang.org/pkg/text/template/" target="_blank" rel="noreferrer noopener"&gt;Go template language&lt;/a&gt;, with the addition of 50 or so add-on template functions&amp;nbsp;&lt;a href="https://github.com/Masterminds/sprig" target="_blank" rel="noreferrer noopener"&gt;from the Sprig library&lt;/a&gt;&amp;nbsp;and a few other&amp;nbsp;&lt;a href="https://helm.sh/docs/howto/charts_tips_and_tricks/"&gt;specialized functions&lt;/a&gt;. While we talk about the &amp;#8220;&lt;a href="https://helm.sh/docs/chart_template_guide/functions_and_pipelines/#helm"&gt;Helm template language&lt;/a&gt;&amp;#8221; as if it is Helm-specific, it is actually a combination of the Go template language, some extra functions, and a variety of wrappers to expose certain objects to the templates. Many resources on Go templates may be helpful as you learn about templating.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="create-self-signed-certificate-with-cert-manager"&gt;Create self-signed certificate with Cert-Manager&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;a href="https://cert-manager.io/docs/"&gt;Cert Manager&lt;/a&gt; project is very popular to produce X.509 certificates directly in Kubernetes secret. We can install cert manager using Helm:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl create namespace cert-manager&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo add jetstack https://charts.jetstack.io&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.0.3 --set installCRDs&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get pods -n cert-manager&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get crd | grep cert-manager.io&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Alternatively, FluxCD&amp;#8217;s documentation on &lt;a href="https://fluxcd.io/docs/components/kustomize/kustomization/#kustomization-dependencies"&gt;Kustomization dependency&lt;/a&gt; uses Cert Manager as an example. It is a good way of installing cert-manager if you have GitOps pattern.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Creating self-signed certificate for website is fairly simple. It starts with &lt;a href="https://cert-manager.io/docs/configuration/selfsigned/#bootstrapping-ca-issuers"&gt;bootstrapping&lt;/a&gt; a CA issuer. Take the manifest below as an example. When creating the first certificate, make sure to specify isCA=true, so it stores the signing private key along with its own certificate in the ca-secret. Then use the newly created CA as issuer to create the X.509 certificate for the website.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cert-manager.io/v1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ClusterIssuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;selfsigned-issuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;selfSigned&lt;/span&gt;: {}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cert-manager.io/v1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Certificate&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-ca&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;orthweb&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;isCA&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;commonName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-ca&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;secretName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ca-secret&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;privateKey&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;algorithm&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ECDSA&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;256&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;issuerRef&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;selfsigned-issuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ClusterIssuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;group&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cert-manager.io&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cert-manager.io/v1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Issuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-ca-issuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;orthweb&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ca&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;secretName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ca-secret&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cert-manager.io/v1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Certificate&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;orthweb-cert&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;orthweb&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;commonName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;orthweb.com&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;secretName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;orthweb-secret&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;duration&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2160h&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;renewBefore&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;72h&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;subject&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;organizations&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;digihunch&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;dnsNames&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;web.orthweb.com&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;dcm.orthweb.com&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;privateKey&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;algorithm&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ECDSA&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;256&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;issuerRef&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-ca-issuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Issuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;group&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cert-manager.io&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The site certificate is directly stored in Kubernetes Secret as specified in the secretName field. To fetch the certificate text, we need to decode the secret entry, for example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl -n orthweb get secret orthweb-secret -o jsonpath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;{.data.ca\.crt}&amp;#39;&lt;/span&gt; | base64 -d&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Note that the example above uses ECDSA algorithm with size 256 for private key and certificate. It requires that the TLS client to support ECDSA algorithm as well. For more supportability, you can use RSA algorithm (2048 or 4096 size).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In addition to creating self-signed certificate, Cert Manager supports a number of other issuer types. For example, the support of &lt;a href="https://cert-manager.io/docs/configuration/acme/"&gt;ACME&lt;/a&gt; issuer type enables integration with Let&amp;#8217;s Encrypt. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Cert Manager can secure Kubernetes Ingress resources with a sub-component called &lt;strong&gt;ingress-shim&lt;/strong&gt;. It is configured via annotation on the &lt;a href="https://cert-manager.io/docs/usage/ingress/"&gt;Ingress&lt;/a&gt; resource.&lt;/p&gt;&#10;&lt;figure class="wp-block-image is-resized"&gt;&lt;img decoding="async" src="https://cert-manager.io/images/high-level-overview.svg" alt="High level overview diagram explaining cert-manager architecture" style="width:752px;height:432px"/&gt;&lt;figcaption class="wp-element-caption"&gt;Cert Manager&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h2 class="wp-block-heading" id="create-ca-signed-certificate-manually"&gt;Create CA-signed certificate manually&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For a certificate signed by a CA, there are may paid options, from manual, to self-help, to automated. The classic manual way is using OpenSSL, generating key, CSR. The CA takes CSR to sign a X.509 certificate returned to the website administration.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Many CA websites charges for a fee and makes it easy. For example, this site currently uses certificate from SSLs.com. Apart from the fee-for-cert option, there is a website named &amp;#8220;&lt;a href="https://www.sslforfree.com/"&gt;SSL for free&lt;/a&gt;&amp;#8220;, a CA with free option for 90-day single-domain, non-wildcard certificate and we can request it simply on their website, with proof of domain ownership. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The other popular free option is Let&amp;#8217;s Encrypt, which also employs &lt;a href="https://static.digihunch.com/2021/04/public-key-infrastructure-pki/"&gt;ACME&lt;/a&gt; protocol. The protocol requires ACME challenges to be satisfied in order to proof domain ownership. There are a few types of &lt;a href="https://letsencrypt.org/docs/challenge-types/"&gt;challenges&lt;/a&gt;: &lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;HTTP-01 challenge &lt;/li&gt;&#10;&lt;li&gt;DNS-01 challenge&lt;/li&gt;&#10;&lt;li&gt;TLS-SNI-01 challenge&lt;/li&gt;&#10;&lt;li&gt;TLS-ALPN-01 challenge&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I have used the HTTP-01 and DNS-01 challenges. The DNS-01 challenge requires adding TXT records to DNS configuration. The HTTP-01 challenge requires adding a DNS A-record to resolve to the server, then two URIs with pre-defined value.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When I first set up this site I used certbot (the client program for letsencrypt) to create certificate every 90 days from the wordpress server, following &lt;a href="https://lightsail.aws.amazon.com/ls/docs/en_us/articles/amazon-lightsail-using-lets-encrypt-certificates-with-wordpress"&gt;this&lt;/a&gt; guide, including solving DNS-01 challenges.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="create-ca-signed-certificate-automatically-with-cert-manager-and-letsencrypt"&gt;Create CA-signed certificate automatically with cert manager and letsencrypt&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With Kubernetes, &lt;a href="https://cert-manager.io/docs/"&gt;cert-manager&lt;/a&gt; has the ability to integrate with let&amp;#8217;s encrypt for full automation. &lt;a href="https://medium.com/@rd.petrusek/kubernetes-istio-cert-manager-and-lets-encrypt-c3e0822a3aaf"&gt;Here&lt;/a&gt; is a good blog post on this. &lt;span style="text-decoration: underline;"&gt;Domain verification is still required&lt;/span&gt; but it can be done automatically. We first need to register an A record that resolves host name to the Ingress IP to enable this automation. The domain ownership validation may use the ACME protocol. This should also work on private networks with private DNS and ACME protocol using a private boulder server.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Take domain name demo1.digihunch.com for example, if ingress exposes a public IP address which the domain name resolves to, then we can configure certificate with the following manifest:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;IngressClass&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;controller&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio.io/ingress-controller&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cert-manager.io/v1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ClusterIssuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;letsencrypt&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;acme&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;privateKeySecretRef&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;letsencrypt&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;server&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;https://acme-staging-v02.api.letsencrypt.org/directory&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;solvers&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;http01&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ingress&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;class&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cert-manager.io/v1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Certificate&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;demo&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;dnsNames&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;demo1.digihunch.com&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;issuerRef&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ClusterIssuer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;letsencrypt&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;secretName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;demo-tls&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This example uses Istio as ingress controller but the method works regardless of the controller technology behind Ingress. In the ClusterIssuer object, we&amp;#8217;re telling it to use the staging server from letsencrypt. We also specify http01 as challenge type, and that the ingress type is istio. In the Certificate object, we provided dnsName and specified ClusterIssuser. We also tell it to store the credentials to a secret named &lt;em&gt;demo-tls&lt;/em&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When we apply the resources above, the ClusterIssuer connects to letsencrypt server via ACME protocol. Since the DNS name already resolves to the Public IP that the ingress is hosting, the ClusterIssuer configures the required Ingress, Services and Pods accordingly so the &lt;a href="https://letsencrypt.org/docs/challenge-types/#http-01-challenge"&gt;token&lt;/a&gt; to satisfy the challenge is presented at the designated URI. Instead of a staging server, we can also use production ACME server for production deployment. Note that the production ACME endpoint has a stricter rate limit.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When the ACME validation is in progress, it is important to ensure that port 80 is open and there is no other mechanism (such as routing rule, authorization requirement, mandatory redirect to 443) that blocks access from letsencrypt server.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="bottom-line"&gt;Bottom line&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Cert Manager is deployed in Kubernetes, supporting a variety of issuer types. As a Kubernetes-native tool, it is a no-brainer for Kubernetes workload for X.509 certificate. Compared with using template function in Helm, it is not dependent on template function and the syntax is consistent (YAML). Compared with OpenSSL or other binary tools, it is easy to integrate with the platform.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/08/docker-desktop-a-single-node-kubernetes-cluster/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Single-node Kubernetes cluster – docker desktop&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/09/log-shipping-in-kubernetes-with-efk/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Log Shipping in Kubernetes with EFK stack&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>