Private CA for mTLS with cert-manager

第一步,安装cert-manager:

https://cert-manager.io/docs/installation/kubernetes/

第二步,安装自签名ClusterIssuer(所有Namespace共用):

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: FooBarSelfSign
spec:
  selfSigned: {}

第三步,签发CA证书(Application Namespace自用):

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
 name: FooBarCACertificate
spec:
 secretName: FooBarCACertificate
 isCA: true
 issuerRef:
   name: FooBarSelfSign
   kind: ClusterIssuer
 commonName: "FooBar CA"

第四步,安装CA(Application Namespace自用):

apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
 name: FooBarCA
spec:
 ca:
   secretName: FooBarCACertificate

第五步,生成随机JKS密码(Application Namespace自用):

NOTE:如果不需要JKS可以省略这步。

apiVersion: v1
kind: Secret
metadata:
  name: FooBarJKSPassword
data:
  Password: {{ uuidv4 | b64enc }}

第六步,使用CA签发Application证书(Application Namespace自用):

NOTE:如果不需要JKS,可以省略keystores的部分

---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: FooBarServerCertificate
spec:
  secretName: FooBarServerCertificate
  duration: 2160h # 90d
  renewBefore: 360h # 15d
  keySize: 2048
  keyAlgorithm: rsa
  keyEncoding: pkcs1
  commonName: server.foobar.com
  keystores:
    jks:
      create: true
      passwordSecretRef:
        name: FooBarJKSPassword
        key: Password
  issuerRef:
    name: FooBarCA
    kind: Issuer
    group: cert-manager.io
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: FooBarClientCertificate
spec:
  secretName: FooBarClientCertificate
  duration: 2160h # 90d
  renewBefore: 360h # 15d
  keySize: 2048
  keyAlgorithm: rsa
  keyEncoding: pkcs1
  commonName: "FooBar Client"
  keystores:
    jks:
      create: true
      passwordSecretRef:
        name: FooBarJKSPassword
        key: Password
  issuerRef:
    name: FooBarCA
    kind: Issuer
    group: cert-manager.io

生成的FooBarServerCertificateFooBarClientCertificate包含以下内容:

  • tls.key – 证书私钥
  • tls.crt – 证书
  • ca.crt – CA证书
  • keystore.jks
  • truststore.jks

第七步,安装签发的证书到应用:

示例1 – Server Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: FooBarServer
spec:
  template:
    spec:
      containers:
        - name: FooBarServer
          volumeMounts:
            - name: tls
              mountPath: /var/ssl/private
              readOnly: true
      volumes:
        - name: tls
          secret:
            secretName: FooBarServerCertificate
            items:
              - key: truststore.jks
                path: foobar-truststore.jks
              - key: keystore.jks
                path: foobar-keystore.jks
...

示例2 – Ingress Client:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: FooBarIngress
  annotations:
    kubernetes.io/ingress.class: nginx

    # enable mTLS for frontend
    nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
    nginx.ingress.kubernetes.io/auth-tls-verify-depth: 2
    nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "false"
    # read the ca.crt part of the certificate
    nginx.ingress.kubernetes.io/auth-tls-secret: <another certificate for frontend>
    
    # enable mTLS for backend
    nginx.ingress.kubernetes.io/proxy-ssl-verify: "on"
    nginx.ingress.kubernetes.io/proxy-ssl-secret: FooBarClientCertificate
spec:
  rules:
    - host: server.foobar.com
      http:
        paths:
          - path: /xxx
            backend:
              serviceName: FooBarAppService
              servicePort: xxx
  tls:
    - hosts:
        - server.foobar.com
      # read the tls.key and tls.crt parts of the certificate
      secretName: <another certificate for frontend>
...