How to use Wildcard certificates from Let’s Encrypt with cert-manager - kubernetes

I Created two files, one is for ClusterIssuer and the Second is for Certificate.
My Domain is an example.com and I need to create a new subdomain with wildcard *.testing.example.com and I already created an entry in Route53 called *.testing.example.com with A record and mapped with nlb.
Below are my profile and which good to me, but I am getting error " msg"="propagation check failed" "error"="DNS record for \"testing.example.com\" not yet propagated"
ClusterIssuer.yaml
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
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: devops#example.com
privateKeySecretRef:
name: letsencrypt-prod
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: ap-south-1
hostedZoneID: 71MYVttggee
role: arn:aws:iam::123456:role/dns-manager
Certificate.yaml
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: example-cert
spec:
secretName: acme-crt
issuerRef:
kind: ClusterIssuer
name: letsencrypt-prod
commonName: testing.example.com
dnsNames:
- '*.testing.example.com'
acme:
config:
- dns01:
provider: route53
domains:
- '*.testing.example.com'

What you have is correct, you just need to wait for DNS propagation so that the verification records can be checked by LetsEncrypt.

You have to use the method of DNS-01 for verification auth.
You can use the issuer
https://cert-manager.io/docs/configuration/acme/dns01/
however, you also have to create one another YAML for certificate
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: le-crt
spec:
secretName: tls-secret
issuerRef:
kind: Issuer
name: letsencrypt-prod
commonName: "*.example.in"
dnsNames:
- "*.example.in"
above yaml certificate will point to issuer that you created and as you get the certificate it will be get stored into the kubernetes secret name as : tls-secret
You can inject or use this secret on the ingress.
Also if you are facing the 403 error of CAA record please add the CAA record in the DNS zone first same we add the A or CNAME record.
For more ref : https://stackoverflow.com/a/68476135/5525824

Related

Letsencrypt certificate READY is False and the STATUS is 'Issuing certificate as Secret does not exist'

I am trying to configure tls for my Kubernetes cluster using cert-manager and lets encrypt but seems to be running into a problem that I cannot seem to resolve.
I have installed cert-manager using the following command
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.1/cert-manager.yaml
And have configured cluster issuer with the yaml file below
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: tardis
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: adamlee#tardistechnology.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
And I have tried issuing a certificate with the yaml file below
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: home.tardis.kr
namespace: tardis
spec:
secretName: home.tardis.kr-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
commonName: home.tardis.kr
dnsNames:
- home.tardis.kr
However, when I get the status of the certificate, it seems to be 'False' and the status seems to be 'Issuing certificate as Secret does not exist'
Some of the solutions that I have found seems to indicate that this is due to the fact that the fact that the domain listed on the ingress is not connected properly, but this does not seem to be the case for me, and the domain seems to be connected fine.
It would be deeply appreciated if anyone could provide any feedback on this matter.
Thank you in advance!
I was applying certificate instead of secret. I changed the ingress so that it will apply the secret and the problem was solved

Why my "Certificate" object and "Ingress" both are creating Certificates?

Why my "Certificate" object and "Ingress" both are creating Certificates ?
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: blog-app-crt
spec:
secretName: blog-app-crt-sec
issuerRef:
kind: ClusterIssuer
name: letsencrypt-prod
commonName: blog.mydomain.com
dnsNames:
- blog.mydomain.com
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# Email address used for ACME registration
email: myemailid#gmail.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Name of a secret used to store the ACME account private key
name: letsencrypt-production-private-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: nginx
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
spec:
tls:
- hosts:
- blog.mydomain.com
secretName: blog-app-crt-sec
rules:
- host: blog.mydomain.com
http:
paths:
- pathType: Prefix
path: "/?(.*)"
backend:
service:
name: app-1-endpoint
port:
number: 5000
- pathType: Prefix
path: "/tribute/?(.*)"
backend:
service:
name: app-2-endpoint
port:
number: 5001
When I create above objects, it is creating 2 Certificate ojects, both pointing to same secret.
blog-app-crt-sec
blog-app-crt
How can I create Only 1 Certificate ? If I create only a ClusterIssuer without any custom certificate, then of course that will solve the issue, but I want to create a Custom certificate to control the renewal stuff.
There is a component of cert-manager called ingress-shim that watches Ingress resources and automatically creates Certificate objects for you when some annotations are present. This way, you wouldn’t even need to create the Certificate object on your own.
Please check your ingress definition for corresponding cert-manager.io scoped annotations and either use those or the manually created certificate. I assume you refer to the secret named blog-app-crt in your ingress definition. This needs to match what is defined in the cert spec secretName if you don’t use the automated creation!
For details on automatic certificate creation, please check the cert-manager docs on ingress: https://cert-manager.io/docs/usage/ingress/
In your case:
Annotation cert-manager.io/cluster-issuer tells that Ingress for generating certificates to your host (annotation on Ingress configuration plays a big role in the background).
That certificate configuration with kind: Certificate is also telling you to generate the certificate for your host.
You can either choose one of them on your configuration.
The best one for you is to drop that kind: Certificate configuration.
When do we drop the annotation and use the certificate?
For example, you have a.host.com, b.host.com, c.host.com and want to generate a single certificate and use it in multiple places, i.e. either in Ingress or in other TCP SSL configurations.

cert-manager: no configured challenge solvers can be used for this challenge

I followed this instruction to set up a cert manager on my EKS cluster https://cert-manager.io/docs/tutorials/acme/ingress/.
here is my ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/issuer: "letsencrypt-staging"
spec:
tls:
- hosts:
- '*.test.com'
secretName: test-tls
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: test-service
port:
number: 80
Here is the issuer. I just copied the config from the instruction
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: info#test.com
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
class: nginx
After deployment, I found the certificate ready state is false
kubectl get certificate
NAME READY SECRET AGE
test-tls False test-tls 2m45s
Then I followed this to troubleshoot https://cert-manager.io/docs/faq/troubleshooting/
I ran kubectl describe certificaterequest <request name>, found error Waiting on certificate issuance from order test-tls-xxx: "pending"
then ran kubectl describe order test-tls-xxx, found error
Warning Solver 20m cert-manager Failed to determine a valid solver configuration for the set of domains on the Order: no configured challenge solvers can be used for this challenge.
Any idea why it couldn't determine a valid solver? how do I test if solver is working?
It's not working due you are using the staging URL in cluster issuer to verify the image.
Please try with the Production URL.
here a simple and proper example of Clusterissuer and ingress YAML (do note you were trying with staging API https://acme-staging-v02.api.letsencrypt.org/directory if possible use the production server address so it works properly with all browsers)
Example:
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: cluster-issuer-name
namespace: development
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: harsh#example.com
privateKeySecretRef:
name: secret-name
solvers:
- http01:
ingress:
class: nginx-class-name
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx-class-name
cert-manager.io/cluster-issuer: cluster-issuer-name
nginx.ingress.kubernetes.io/rewrite-target: /
name: example-ingress
spec:
rules:
- host: sub.example.com
http:
paths:
- path: /api
backend:
serviceName: service-name
servicePort: 80
tls:
- hosts:
- sub.example.com
secretName: secret-name
Note : When you are trying again please try deleting the old objects like ingress, Clusterissuer first.
Issuer vs ClusterIssuer
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.
Ref : https://cert-manager.io/docs/concepts/issuer/
Wildcard cert
You can use as per requirement, if you are using issuer you can update the ingress annotation line like
cert-manager.io/issuer: issuer-name
If you are trying to get the wildcard * certificate you won't be able to get it using HTTP auth method
solvers:
- http01:
ingress:
class: nginx-class-name
instead of this you have to use the DNS-auth method for wildcard cert.
solvers:
- dns01:
cloudDNS:
project: my-project
serviceAccountSecretRef:
name: prod-clouddns-svc-acct-secret
key: service-account.json
Read more at : https://cert-manager.io/docs/configuration/acme/dns01/
Ref article to get the wildcard cert : https://medium.com/#harsh.manvar111/wild-card-certificate-using-cert-manager-in-kubernetes-3406b042d5a2

Ingress nginx cert-manager certificate invalid on browser

I am experiencing a rather weird issue and have been stuck on this for 2 days. I have a kubernetes cluster running nginx-ingress and cert-manager. Everything seems to be working fine though when visiting my website through HTTPS, it gives the following error (in chromium edge):
NET::ERR_CERT_AUTHORITY_INVALID
If I continue anyways, it loads the site normally but without the certificate.
The certificate is properly being given, secret created, no errors anywhere.
I have the following annotations in my ingress resource:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: "letsencrypt-production"
ingress.kubernetes.io/ssl-redirect: "true"
My cluster issuer:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-production
spec:
acme:
# The ACME production api URL
server: https://acme-staging-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: *********
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-production
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
The certificate resource returns:
Normal Issuing 108s cert-manager The certificate has been successfully issued
I am relatively new to kubernetes so let me know if there are any other debugging steps I can take.
You are using acme staging server: https://acme-staging-v02.api.letsencrypt.org/directory server which does not provide valid certificate.
To get valid certificate you have to use acme production server server: https://acme-v02.api.letsencrypt.org/directory.
you can try this.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-production
spec:
acme:
# The ACME production api URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: *********
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-production
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx

Kubernetes - cert-manager - Hashicorp Vault - Ready status of certificate is blank

I have created Clusterissuer that uses Vault and then issued certificate through it but the Ready status of the certificate is blank. There is nothing appearing in the events and cert-manager pod logs. It has not created a secret as well.
kubectl get cert
NAMESPACE NAME READY SECRET AGE
default example-com example-com 139m
clusterissuer.yaml
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: vault-clusterissuer
spec:
vault:
path: pki_int/sign/<role name>
server: https://vault-cluster.example.com:8200
caBundle: <base64 encoded cabundle pem>
auth:
appRole:
path: approle
roleId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
secretRef:
name: cert-manager-vault-approle
key: secretId
The role name mentioned in the Path is the same as the role created in the Vault under pki_init.
certificate.yaml
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: example-com
spec:
secretName: example-com
issuerRef:
name: vault-clusterissuer
kind: ClusterIssuer
commonName: abc.example.com
dnsNames:
- abc.example.com
Since it is not generating any message or logs so I am not sure from where to start troubleshooting.
Does the value of path in clusterissuer.yaml looks right to you..?
Thank you in advance
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
I think the issue is in wrong dnsNames defined in certificate.yaml file:
Your certificate configuration file:
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: example-com
spec:
secretName: example-com
issuerRef:
name: vault-clusterissuer
kind: ClusterIssuer
commonName: abc.example.com
dnsNames:
- abc.example.com
dnsNames field should have value: www.abc.example.com not abc.example.com
Final version should looks like:
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: example-com
spec:
secretName: example-com
issuerRef:
name: vault-clusterissuer
kind: ClusterIssuer
commonName: abc.example.com
dnsNames:
- www.abc.example.com
Also remember that path field is the Vault role path of the PKI backend and server is the Vault server base URL. The path MUST USE the vault sign endpoint.
Please take a look: issuer-vault-setup, cert-clusterissuer.