惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Project Zero
Project Zero
T
The Exploit Database - CXSecurity.com
G
GRAHAM CLULEY
T
Threatpost
A
Arctic Wolf
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Scott Helme
Scott Helme
Simon Willison's Weblog
Simon Willison's Weblog
P
Proofpoint News Feed
C
Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
Kaspersky official blog
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threat Research - Cisco Blogs
The Hacker News
The Hacker News
T
Tor Project blog
NISL@THU
NISL@THU
The GitHub Blog
The GitHub Blog
Security Latest
Security Latest
aimingoo的专栏
aimingoo的专栏
C
CERT Recently Published Vulnerability Notes
Recorded Future
Recorded Future
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
Martin Fowler
Martin Fowler
N
News | PayPal Newsroom
P
Privacy & Cybersecurity Law Blog
MyScale Blog
MyScale Blog
G
Google Developers Blog
V
V2EX
V
Visual Studio Blog
P
Privacy International News Feed
Google Online Security Blog
Google Online Security Blog
Microsoft Azure Blog
Microsoft Azure Blog
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
L
LINUX DO - 热门话题
MongoDB | Blog
MongoDB | Blog
腾讯CDC
J
Java Code Geeks
The Last Watchdog
The Last Watchdog
L
Lohrmann on Cybersecurity
Cyberwarzone
Cyberwarzone
博客园 - 聂微东
Webroot Blog
Webroot Blog
S
Secure Thoughts

A cup of coffee

Karpenter + Cluster API Kloak: kernel-space secret injection via eBPF on Kubernetes talosctl-oidc: adding SSO to Talos Linux Kairos, the immutable OS for deploying Kubernetes Bootc and OSTree: Modernizing Linux System Deployment Kubernetes API-Server with Multiple IdPs (and Github Actions) SPIFFE and mTLS with cert-manager Customizing Talos with Extensions Omni and Kubevirt Cluster API + Talos + Proxmox = ❤️ GoAuthentik from A to Y Istio from A to Y Awtrix Ulanzi + Domotic = ❤️ Falco from A to Y Yubikey and GPG: Securing Your Communications ArgoCD from A to Y Talos - An Immutable OS for Kubernetes Loki from A to Y Vault from A to Z Creating your MicroVM cloud at home? How to manage secrets in Kubernetes with Sealed-Secret Prometheus from A to Y Getting Started with Tmux IPFS - A protocol for archiving and sharing files Dagger.io, a Universal CI Curriculum Vitae Documentations Liste des pages Archives
Cert-Manager
2023-03-08 · via A cup of coffee

Introduction

Usually, when I start writing documentation, I always begin with a definition (often sourced from Wikipedia). Since the Wikipedia page for cert-manager is not very comprehensive (and also to be trendy and mention it at least once), I will ask ChatGPT to write this definition for me.

Cert-manager is a certificate management tool for Kubernetes. It automates the generation, renewal, and management of SSL/TLS certificates for your applications on the cluster. Cert-manager supports multiple certificate providers such as Let’s Encrypt, Vault, etc. By using Cert-manager, you can declare the need for a certificate for a specific application through a Kubernetes object called “Certificate” or “Issuer”. Cert-manager then takes care of generating or renewing the certificate according to the specifications defined in the object. Cert-manager is a key component to ensure the security and confidentiality of data in applications on Kubernetes. It simplifies certificate management for cluster administrators, avoiding human errors and ensuring a constant availability of valid certificates for applications. In summary, Cert-manager is a powerful tool for managing SSL/TLS certificates in a Kubernetes environment, enabling more efficient and secure certificate management for your applications.

cert-manager diagram

Until now, I was using Traefik as an Ingress. It generated the certificates and stored them in a text file located in a Longhorn volume. (knowing full well that it wasn’t very clean)

Today, it’s time for cleanliness… we switch to Cert-Manager!

Meme incredible to talk about cleanliness

Install Cert-Manager

As of the day I write this page, we are at version v1.11.0.

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml

Warning

Make sure to get the latest version of cert-manager. You can find the available versions here

How Cert-Manager Works

The installation of Cert-Manager involves different objects. The ones that interest us are:

  • Issuers
  • Certificates

Issuers are the certificate providers. Cert-Manager is compatible with the following providers:

  • ACME HTTP/DNS (compatible with letsencrypt)
  • Self-signed (I recommend generating your own CA instead)
  • Custom CA
  • Vault
  • Venafi

For now, only the LetsEncrypt provider interests us. (We may see the CA case someday)

Add a provider (Issuer)

ACME via HTTP challenge

The most common case when generating a certificate is to use LetsEncrypt with an HTTP challenge. (e.g., CertBot) Its configuration is quite quick, here is the manifest to add the LetsEncrypt ACME. (Remember to replace ‘istio’ with your IngressClass)

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: votre_email@ici.tld
    privateKeySecretRef:
      name: letsencrypt
    solvers:
    - selector: {}
      http01:
        ingress:
          class: istio

Key takeaways:

  • Make sure to provide the used ingress, as the challenge needs to be done on port 80 over HTTP.
  • The provided email will be used by LetsEncrypt to notify you when the certificate needs to be renewed.

Tip

If you fail too many challenges (or generate the same certificate too many times), you may be blocked by LetsEncrypt. When you just want to test the procedures, you can use the staging API (which has no rate limits).

The certificates will not be accepted by your browser, but for testing purposes, it’s ideal.

Simply replace the URL with https://acme-staging-v02.api.letsencrypt.org/directory

You can verify that the Issuer is present using the following command:

➜  kubectl describe issuers.cert-manager.io letsencrypt

Status:
  Acme:
    Last Registered Email:  redacted
    Uri:                    https://acme-v02.api.letsencrypt.org/acme/acct/941914187
  Conditions:
    Last Transition Time:  2023-01-31T10:05:12Z
    Message:               The ACME account was registered with the ACME server
    Observed Generation:   1
    Reason:                ACMEAccountRegistered
    Status:                True
    Type:                  Ready
Events:                    <none>

ACME via DNS challenge

First of all, not all providers are compatible with this method. I am using CloudFlare which (thanks to its API) allows us to create entries in your domain to solve the challenge. This method has some advantages, such as not having to open a port to solve the challenge.

To use the API, you need to create a token to authenticate our request. Go to this page to create your token. The necessary permissions are:

  • Zone.Zone READ
  • Zone.DNS WRITE

Génération Token

With the token, create this secret:

apiVersion: v1
kind: Secret
metadata:
  name: cloudflare-api-token-secret
type: Opaque
stringData:
  api-token: aaaaaabbbbbbbcccccccdddddd

And add our Cloudflare provider. (This will use our secret)

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: cloudflare
spec:
  acme:
    email: votre_email@ici.tld
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: cloudflare
    solvers:
    - dns01:
        cloudflare:
          apiTokenSecretRef:
            name: cloudflare-api-token-secret
            key: api-token

Create an Issuer for all namespaces

We previously created an Issuer for the current namespace (which means we can only create certificates with this Issuer in this namespace).

But we rarely have only one namespace, and when we need to update the configuration of our Issuer, we have to do it in all namespaces (which is quite cumbersome and error-prone).

That’s why it is possible to create a valid Issuer across all namespaces: the ClusterIssuer.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: cloudflare
spec:
  acme:
    email: votre_email@ici.tld
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: cloudflare
    solvers:
    - dns01:
        cloudflare:
          apiTokenSecretRef:
            name: cloudflare-api-token-secret
            key: api-token

The ClusterIssuer has exactly the same parameters as the Issuer. The only change to consider is that the cloudflare-api-token-secret secret should be in the cert-manager namespace instead of the current namespace.

Create a certificate

With the provider configured, it is now possible to create our certificate. I will generate mine for my domain test.a-cup-of.coffee.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: test-coffee
spec:
  secretName: test-coffee-tls
  issuerRef:
    name: letsencrypt
  commonName: test.a-cup-of.coffee
  dnsNames:
  - test.a-cup-of.coffee

Info

If you are using the ClusterIssuer object, make sure to specify the kind in the issuerRef:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: test-coffee
spec:
  secretName: test-coffee-tls
  issuerRef:
    name: letsencrypt
    kind: ClusterIssuer
  commonName: test.a-cup-of.coffee
  dnsNames:
  - test.a-cup-of.coffee

Make sure that the certificate is generated and available.

➜  kubectl describe certificate test-coffee
Events:
  Type    Reason     Age    From                                       Message
  ----    ------     ----   ----                                       -------
  Normal  Issuing    7m9s   cert-manager-certificates-trigger          Issuing certificate as Secret was previously issued by Issuer.cert-manager.io/letsencrypt
  Normal  Reused     7m9s   cert-manager-certificates-key-manager      Reusing private key stored in existing Secret resource "test-coffee-tls"
  Normal  Requested  7m8s   cert-manager-certificates-request-manager  Created new CertificateRequest resource "test-coffee-j8x9j"
  Normal  Issuing    5m46s  cert-manager-certificates-issuing          The certificate has been successfully issued

And make sure that the secret is created successfully:

➜  kubectl get secret test-coffee-tls
NAME                      TYPE                DATA   AGE
test-coffee-tls   kubernetes.io/tls   2      169m

Create a wildcard certificate

A wildcard certificate is a certificate that secures a domain and all its subdomains. (e.g., *.a-cup-of.coffee). You will need to use DNS verification to generate this certificate.

The process of generating a wildcard certificate is the same as generating a regular certificate, except that you add a * before the domain name.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: wildcard-coffee
  namespace: default
spec:
  secretName: wildcard-coffee
  issuerRef:
    name: cloudflare
    kind: ClusterIssuer
  commonName: "*.a-cup-of.coffee"
  dnsNames:
  - "a-cup-of.coffee"
  - "*.a-cup-of.coffee"

Using a Certificate

Here is an example of YAML code to generate an Ingress using the secret.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-coffee
  annotations:
    kubernetes.io/ingress.class: "istio"
spec:
  tls:
  - hosts:
    - test.a-cup-of.coffee
    secretName: test-coffee-tls
  rules:
  - host: "test.a-cup-of.coffee"
    http:
      paths:
        - pathType: Prefix
          path: "/"
          backend:
            service:
              name: srvc-coffee
              port:
                number: 80

Or with an IngressRoute object if (like me) you are using Traefik.

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: test-coffee
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`test.a-cup-of.coffee`)
      kind: Rule
      services:
        - name: srvc-coffee
          port: 80
  tls:
    secretName: test-coffee-tls