Search code examples
kubernetesssl-certificatewindows-subsystem-for-linuxcert-managermkcert

Generating certificate for local dev environment in WSL2


Having difficulty getting a certificate installed in a local development environment that is isolated to WSL2. I've done the exact same steps in macOS and Linux, and have had zero issues.

The steps are the following:

# Download and install mkcert
if [[ `uname` = "Darwin" ]] then
    brew install mkcert
    brew install nss
else
    curl -Lo mkcert https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-amd64 && \
        sudo install mkcert /usr/local/bin/
fi

# Installing tls certificate
mkcert -install

# Installing tls certificate
mkcert localhost 127.0.0.1 ::1

# Installing cert-manager locally
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.2.0/cert-manager.yaml

# Add the certificates to secrets
kubectl create secret tls tls-localhost-dev --key=localhost+2-key.pem --cert=localhost+2.pem -n dev

# Create the tls service that will attach to ingress-nginx
kubectl apply -f k8s/dev/tls.yaml
# k8s/dev/tls.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-dev-issuer
  namespace: cert-manager
spec:
  ca:
    secretName: tls-localhost-dev
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: letsencrypt-dev-certificate
  namespace: cert-manager
spec:
  secretName: tls-localhost-dev
  dnsNames:
    - localhost
  issuerRef:
    name: letsencrypt-dev-issuer
    kind: Issuer
# k8s/dev/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-dev"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  name: ingress-dev
  namespace: dev
spec:
  tls:
    - hosts:
        - localhost
      secretName: tls-localhost-dev
  rules:
    - host: localhost
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: client-cluster-ip-service-dev
                port:
                  number: 3000

After all of that, you can navigate to localhost and see it has a certificate... on Linux and macOS.

In WSL2, I can't get the certificates working even though there are no errors except for when I describe some of the resources:

$ kubectl describe issuer letsencrypt-dev-issuer -n cert-manager
Name:         letsencrypt-dev-issuer
Namespace:    cert-manager
Labels:       <none>
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         Issuer
Metadata:
  Creation Timestamp:  2021-03-04T01:33:06Z
  Generation:          1
  Managed Fields:
    API Version:  cert-manager.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:status:
        .:
        f:conditions:
    Manager:      controller
    Operation:    Update
    Time:         2021-03-04T01:33:06Z
    API Version:  cert-manager.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .:
          f:kubectl.kubernetes.io/last-applied-configuration:
      f:spec:
        .:
        f:ca:
          .:
          f:secretName:
    Manager:         kubectl-client-side-apply
    Operation:       Update
    Time:            2021-03-04T01:33:06Z
  Resource Version:  800
  Self Link:         /apis/cert-manager.io/v1/namespaces/cert-manager/issuers/letsencrypt-dev-issuer
  UID:               ebad4607-afe7-480a-8107-1c27fa8c2e8d
Spec:
  Ca:
    Secret Name:  tls-localhost-dev
Status:
  Conditions:
    Last Transition Time:  2021-03-04T01:33:06Z
    Message:               Error getting keypair for CA issuer: secret "tls-localhost-dev" not found
    Reason:                ErrGetKeyPair
    Status:                False
    Type:                  Ready
Events:
  Type     Reason         Age                  From          Message
  ----     ------         ----                 ----          -------
  Warning  ErrGetKeyPair  4m30s (x9 over 19m)  cert-manager  Error getting keypair for CA issuer: secret "tls-localhost-dev" not found
  Warning  ErrInitIssuer  4m30s (x9 over 19m)  cert-manager  Error initializing issuer: secret "tls-localhost-dev" not found
$ kubectl describe certificate tls-localhost-dev -n dev
Name:         tls-localhost-dev
Namespace:    dev
Labels:       app.kubernetes.io/managed-by=skaffold
              skaffold.dev/run-id=a853f8d6-f192-465c-a43f-4369d5c5a636
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         Certificate
Metadata:
  Creation Timestamp:  2021-03-04T01:38:18Z
  Generation:          1
  Managed Fields:
    API Version:  cert-manager.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:labels:
          .:
          f:app.kubernetes.io/managed-by:
          f:skaffold.dev/run-id:
        f:ownerReferences:
          .:
          k:{"uid":"d596b83b-95eb-46f6-941f-0f6cef0a76d8"}:
            .:
            f:apiVersion:
            f:blockOwnerDeletion:
            f:controller:
            f:kind:
            f:name:
            f:uid:
      f:spec:
        .:
        f:dnsNames:
        f:issuerRef:
          .:
          f:group:
          f:kind:
          f:name:
        f:secretName:
        f:usages:
      f:status:
        .:
        f:conditions:
        f:nextPrivateKeySecretName:
        f:notAfter:
        f:notBefore:
        f:renewalTime:
    Manager:    controller
    Operation:  Update
    Time:       2021-03-04T01:38:18Z
  Owner References:
    API Version:           networking.k8s.io/v1beta1
    Block Owner Deletion:  true
    Controller:            true
    Kind:                  Ingress
    Name:                  ingress-dev
    UID:                   d596b83b-95eb-46f6-941f-0f6cef0a76d8
  Resource Version:        1312
  Self Link:               /apis/cert-manager.io/v1/namespaces/dev/certificates/tls-localhost-dev
  UID:                     12d0f503-928b-4aaf-b691-3e6ed6e76e39
Spec:
  Dns Names:
    localhost
  Issuer Ref:
    Group:      cert-manager.io
    Kind:       ClusterIssuer
    Name:       letsencrypt-dev
  Secret Name:  tls-localhost-dev
  Usages:
    digital signature
    key encipherment
Status:
  Conditions:
    Last Transition Time:        2021-03-04T01:38:18Z
    Message:                     Issuing certificate as Secret was previously issued by Issuer.cert-manager.io/
    Reason:                      IncorrectIssuer
    Status:                      True
    Type:                        Issuing
    Last Transition Time:        2021-03-04T01:38:18Z
    Message:                     Existing issued Secret is not up to date for spec: [spec.ipAddresses]
    Reason:                      SecretMismatch
    Status:                      False
    Type:                        Ready
  Next Private Key Secret Name:  tls-localhost-dev-zqwpw
  Not After:                     2023-06-04T00:32:33Z
  Not Before:                    2021-03-04T01:32:33Z
  Renewal Time:                  2023-05-05T00:32:33Z
Events:
  Type    Reason     Age   From          Message
  ----    ------     ----  ----          -------
  Normal  Issuing    15m   cert-manager  Issuing certificate as Secret was previously issued by Issuer.cert-manager.io/
  Normal  Reused     15m   cert-manager  Reusing private key stored in existing Secret resource "tls-localhost-dev"
  Normal  Requested  15m   cert-manager  Created new CertificateRequest resource "tls-localhost-dev-4xrv9"
$ kubectl describe secret tls-localhost-dev -n dev
Name:         tls-localhost-dev
Namespace:    dev
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1521 bytes
tls.key:  1708 bytes

Basically says something isn't there that is quite clearly there.

Any suggestions for how to resolve this?


Solution

  • Ok, got this figured out with some help:

    This is what worked for my use case. Granted, I didn't test it without installing mkcert into WSL, so that step may not be necessary:

    1. Use choco to install mkcert: choco install -y mkcert
    2. In Windows, mkcert -install
    3. WSL install mkcert (again, not 100% sure this is necessary):
      curl -Lo mkcert https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-amd64 &&
         sudo install mkcert /usr/local/bin/
      
    4. In WSL, mkcert -install (again, not 100% sure this is necessary)
    5. In Windows:
      mkcert localhost 127.0.0.1 ::1
      
    6. This will generate them in your C:\Users\<user>\ directory by default
    7. Copy them into WSL, which for my use case is the root of my project
    8. Then for my use case I run:
      kubectl create secret tls tls-localhost-dev --key=localhost+2-key.pem --cert=localhost+2.pem -n dev 
      
    9. For my use case, I then run kubectl apply -f k8s/dev/tls.yaml which contains:
       apiVersion: cert-manager.io/v1
       kind: Issuer
       metadata:
         name: letsencrypt-dev-issuer
         namespace: cert-manager
       spec:
         ca:
           secretName: tls-localhost-dev
       ---
       apiVersion: cert-manager.io/v1
       kind: Certificate
       metadata:
         name: letsencrypt-dev-certificate
         namespace: cert-manager
       spec:
         secretName: tls-localhost-dev
         dnsNames:
           - localhost
         issuerRef:
           name: letsencrypt-dev-issuer
           kind: Issuer
      

    This time after running skaffold dev, and minikube tunnel, my app is running with the TLS certificates like it should be.