Certificate request seems stuck after storing new private key - kubernetes

I've been trying to roll out our an environment on Kubernetes using LetsEncrypt with CertManager to provision certificates.
However, it seems that the certificate, for whatever reason, can't be provided.
I've been going through the steps over at
https://cert-manager.io/docs/faq/troubleshooting/ but I get stuck on 'Stored new private key in temporary Secret Resource "xxx"', and I cannot find any troubleshooting steps to solve this.
The events list from my past few attempts to reset the certificate
My ingress.yaml looks as follows:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: myname-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
tls:
- hosts:
- app.mydomain.io
secretName: tls-secret
rules:
- host: app.mydomain.io
http:
paths:
- backend:
serviceName: mydomain-identity-v1
servicePort: 80
path: /login(/|$)(.*)
- backend:
serviceName: mydomain-account-v1
servicePort: 80
path: /account(/|$)(.*)
With the following cluster-issuer:
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ***
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
I have followed the following guide to get everything installed:
https://learn.microsoft.com/en-us/azure/aks/ingress-static-ip#create-a-ca-cluster-issuer
It is working on our development environment just fine, however for this new environment it seems to not want to issue an actual CertificateRequest. The ClusterIssuer resource is showing as ready
Has anyone encountered this before, or know what to do? My searches so far have yielded nothing.

I have done this implementation successfully in Azure AKS clusters, you can follow this way -
Install cert-manager from here
Then follow these steps from this stackoverflow post
Make one clusterIssuer or you can make individual issuer too, once you patch the hostname to ingress, then the tls-certificate in that namespace will be autogenerated by Jetstack after the acme-challenge validation
Kindly make sure to map the IP of loadbalancer nginx/traefik etc to DNS/hostname

I was using a newer version of cert-manager on this environment than I was on the other one. There must have been some mismatch between my kubernetes version and the version of cert-manager causing the issue. By reverting to the same cert-manager version the problem has resolved itself.

Related

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

How to deploy a letsencryp with cert-manager and HAProxy-ingress

Digging into www, didn't found an answer:
I want to know how I can use cert-manager with haproxy-ingress and lets encrypt.
Any documentation / guidelines?
Deploy Certmanager with:
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.4.0/cert-manager.yaml
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.4.0/cert-manager.crds.yaml
Deploy a ClusterIssuer (cluster issuers are namespace agnostic)
cat > prod-issuer.yaml <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: email#example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: haproxy
EOF
Apply the cluster issuer with kubectl apply -f prod-issuer.yaml
Create an Ingress Resource (namespace gnostic, this example is using Nginx backend service)
cat > nginx-ingress.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-router
namespace: production
annotations:
kubernetes.io/ingress.class: "haproxy"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- "example.com"
secretName: nginx-tls-secret
rules:
- host: example.com
http:
paths:
- pathType: ImplementationSpecific
path: "/"
backend:
service:
name: nginx
port:
number: 80
- host: www.example.com
http:
paths:
- pathType: ImplementationSpecific
path: "/"
backend:
service:
name: nginx
port:
number: 80
EOF
Apply the ingress recourse with kubectl apply -f nginx-ingress.yaml
The important piece of information here, is that the Haproxy controller does NOT need the annotation acme.cert-manager.io/http01-edit-in-place: "true"
that nginx-ingress controller does. It works as expected without any extra annotations.
When you apply the Ingress Resourse to the cluster, the certificate will be issued in 1-2 minutes tops.
Use kubectl describe certificate nginx-tls-secret -n production to check the status of the certificate, and look at the event to get the certificate.
For more debugging info incase something went wrong, refer here https://cert-manager.io/docs/faq/acme/
you can try installing cert manager provided by jetstack, can be found here and then you need to follow the steps mentioned in this stackoverflow post and this will get things sorted for you.
An internal acme-challenge will be done by cert manager and once you patch the secret name, mentioned in the certificate to the TLS of ingress then certificate status will get ready state, Note that the secret will get created automatically, you need not create it

What is correct way to configure https to my services (kubernetes, nginx-ingress, letsencrypt, cert-manager)?

I just will describe how it configured on my side. I've installed cert-manger on my Kubernetes by using this tutorial :
https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html
I've checked is it installed and it is :
Also I have ingress-resource with the next config:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
certmanager.k8s.io/acme-http01-edit-in-place: "true"
certmanager.k8s.io/cluster-issuer: letsencrypt-issuer
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
name: boonotes-ingress-resource
namespace: default
spec:
rules:
- host: www.bnsfun.com
http:
paths:
- backend:
serviceName: booknotes-front-end-service
servicePort: 80
path: /?(.*)
- host: www.bnsfun.com
http:
paths:
- backend:
serviceName: booknotes-back-end-service
servicePort: 3000
path: /api/?(.*)
tls:
- hosts:
- www.bnsfun.com
secretName: letsencrypt-certs
status:
loadBalancer:
ingress:
- ip: some ip
Also, I've configured the certificate :
kubectl describe certificate booknotes-certificate
Name: booknotes-certificate
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"certmanager.k8s.io/v1alpha1","kind":"Certificate","metadata":{"annotations":{},"name":"booknotes-certificate","namespace":"...
API Version: certmanager.k8s.io/v1alpha1
Kind: Certificate
Metadata:
Creation Timestamp: 2019-11-17T04:51:57Z
Generation: 2
Resource Version: 7257970
Self Link: /apis/certmanager.k8s.io/v1alpha1/namespaces/default/certificates/booknotes-certificate
UID: fbe1d9c0-08f5-11ea-82b3-42010a80017a
Spec:
Acme:
Config:
Domains:
www.bnsfun.com
http01:
Ingress: boonotes-ingress-resource
Common Name: www.bnsfun.com
Dns Names:
www.bnsfun.com
Issuer Ref:
Kind: ClusterIssuer
Name: letsencrypt-issuer
Secret Name: letsencrypt-certs
Events: <none>
I've also created a secret:
Here is my sevice & ingress section:
I've used this tutorial to configure it :
https://medium.com/#betandr/kubernetes-ingress-with-tls-on-gke-744efd37e49e
and official documentation of cert-manager to install cert managed. What do I wrong? How can I check why this doesn't work? I've tried a lot of stuff, but all doesn't work for me. For sure I do something wrong. But what? I've understood that I need cert-manager for updating my lets-encrypt certificate, also I need to create secret to store it, then I need configure my ingress in tls and annotaions. Pls could you help me to find out more what should happen there and what are the main steps to complete it? If you need more info , pls let me know
Here is my issuer:
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-issuer
spec:
acme:
email: email
http01: {}
privateKeySecretRef:
name: letsencrypt
server: "https://acme-v02.api.letsencrypt.org/directory"
let's take an another path, Letsencrypt official docs say that they won't be supporting any longer for below 0.8 versions, so I recommend you to install cert-manager provided by Jetstack, that you can find here, to install the helm chart for it.
The follow this stackoverflow post, for configurations, note that if the api version mentioned in that post doesn't support in case of cluster issuer, then rather use
apiVersion: cert-manager.io/v1alpha2
Note that , the tls secret name mentioned in the certificate will be auto-generated by cert-manager, and it automatically starts an acme-challenge to validate the domain, once you patch that secret name to the TLS in your ingress rule.
It shall solve the issue and the certificate's status will change to ready after the domain verification

How to disable http traffic and force https with kubernetes ingress on gcloud

Hi i tried the new annotation for ingress explained here
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ssl-iagree-ingress
annotations:
kubernetes.io/ingress.allowHTTP: "false"
spec:
tls:
- secretName: secret-cert-myown
backend:
serviceName: modcluster
servicePort: 80
but i can still access it trough http, this is my setup on gcloud ingress--apache:80
Well i was able to resolve the issue, thanks to Mr Danny, from this pull request here, there was a typo in
kubernetes.io/ingress.allowHTTP: "false"
change it to
kubernetes.io/ingress.allow-http: "false"
and it works fine now.
ps: only for master version 1.3.5