I am running Istio 1.5, where SDS is enabled by default apparently, and am trying to enable TLS on north-south traffic in my EKS cluster (v1.15) and I have done the following:
Followed steps here to set up a sample application https://istio.io/latest/docs/setup/getting-started/
Installed cert manager 0.15.1
Created a cluster issuer
Configured the cluster issuer to attempt to solve the DNS challenge by integrating it with AWS Route53
Generate a certificate using the cluster issuer and letsencrypt
Followed the steps here to configure the gateway and virtual service with the certificate created above https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/
I copied the root certificate of letsencrypt to pass through the curl command
Tried to curl to the IP of the loadbalancer and I get this error
Can anyone please guide me on how to resolve this?
There is related documentation about integration cert-menager and istio.
cert-manager
Configuration
Consult the cert-manager installation documentation to get started. No special changes are needed to work with Istio.
Usage
Istio Gateway
cert-manager can be used to write a secret to Kubernetes, which can then be referenced by a Gateway. To get started, configure a Certificate resource, following the cert-manager documentation. The Certificate should be created in the same namespace as the istio-ingressgateway deployment. For example, a Certificate may look like:
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: ingress-cert
namespace: istio-system
spec:
secretName: ingress-cert
commonName: my.example.com
dnsNames:
- my.example.com
...
Once we have the certificate created, we should see the secret created in the istio-system namespace. This can then be referenced in the tls config for a Gateway under credentialName:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: ingress-cert # This should match the Certifcate secretName
hosts:
- my.example.com # This should match a DNS name in the Certificate
Kubernetes Ingress
cert-manager provides direct integration with Kubernetes Ingress by configuring an annotation on the Ingress object. If this method is used, the Ingress must reside in the same namespace as the istio-ingressgateway deployment, as secrets will only be read within the same namespace.
Alternatively, a Certificate can be created as described in Istio Gateway, then referenced in the Ingress object:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
kubernetes.io/ingress.class: istio
spec:
rules:
- host: my.example.com
http: ...
tls:
- hosts:
- my.example.com # This should match a DNS name in the Certificate
secretName: ingress-cert # This should match the Certifcate secretName
Additionally there is full reproduction made by #chrisnyc with cert-menager and lets encrypt on istio discuss, which as #YYashwanth mentioned in comments solved his problem. So if you have similar issue take a look at above reproduction.
Related
We're making use of Istio and in the future we will use Cilium (so if you only know the answer using Cilium please share with me)!
By using Hashicorp Vault and Cert-manager I'm able to issue certificates using a simple deployment file like down here. Cert-manager will then create a Kubernetes secret after issuing the certificate correctly.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: hello-world
namespace: $NAMESPACE
spec:
secretName: hello-world-tls
issuerRef:
kind: ClusterIssuer
name: vault-issuer
commonName: hello-world-testing.intern.nl
dnsNames:
- hello-world-testing.intern.nl
At this moment the Istio Gateway deployment file looks like down here. So far we just added alternate DNS names to the certificate and updated the certificate into the tls-rancher-ingress secret. That means we were using one secret for like 30 to 40 applications. I don't think this is according to best practices, right?
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: istio-system-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- "*"
port:
number: 80
name: http
protocol: HTTP
tls:
httpsRedirect: true
- hosts:
- "*"
port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: tls-rancher-ingress
But since we've implemented Hashicorp Vault and Cert-manager we will get a separate tls kubernetes secret within the new certificate for each application. According to their documentation it's possible to add multiple TLS certificates for multiple hosts to add this in the deployment file above.
So this means we need to update the Gateway (showed above) every time if we need to deploy a new application. We want this to be as efficient as possible so we don't have to add manually the new host and tls kubernetes secret every time with minimal down-time.
My concrete question: Is there a service that automates the process of adding this new host in the gateway and referring to the correct tls kubernetes secret if deploying a new application with the new generated certificate? Or am I not thinking clearly and is there another (simpler) way to automate the tls termination when deploying a new application with a new tls certificate?
Is it possible to use cert-manager to generate a certificate for a workload only in a cluster with ACME server in one of the namespaces? As far I understood cert-manager tries to reach dns name via egressing the cluster and ingressing the cluster to make a http chalange, but what if I do not want to leave the cluster? I do not want cert-manager to create Ingress resource. Let the whole challenge takes place inside the cluster.
My case:
I've got ACME server (step-ca) inside one of my namespaces
I need to create certificate for my POD in another namespace, e.g. common name "${app}.${namespace}"
Remarks: In my case the problem is more complicated due to istio on board. For ingress traffic cert-manager works fine with internal ACME server but for egress traffic I need to go over stunnel (in each POD) to reach Squid outside and I need those certs for stunnel.
The only way I came up with:
Each app has it's own Issuer
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: k8s-acme-local
namespace: ${APP_NS}
spec:
acme:
email: some#email
privateKeySecretRef:
name: k8s-acme-local
server: https://${ACME_SVC}.${ACME_NS}/acme/acme/directory
solvers:
- http01:
ingress:
podTemplate:
metadata:
labels:
app: ${APP}
ingressTemplate: {}
serviceType: ClusterIP
Before creating Certificate resource I create Service to take over the traffic to ${APP}.{APP_NS}
apiVersion: v1
kind: Service
metadata:
name: ${APP}
namespace: ${APP_NS}
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8089
selector:
app: ${APP}
sessionAffinity: None
type: ClusterIP
And then the Certificate resource:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ${APP}
namespace: ${APP_NS}
spec:
secretName: ${APP}
issuerRef:
name: k8s-acme-local
kind: Issuer
group: cert-manager.io
commonName: ${APP}.${APP_NS}
dnsNames:
- ${APP}.${APP_NS}
Now Acme server will do the chalange over my Service not by Ingress (and cer-manager service) which stays unused. I don't like it but it works. This method has one critical drawback. Everyone in the cluster can do it and impersonate any existing or not existing app. I'm looking forward your opinions and tips.
I followed https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-letsencrypt-certificate-application-gateway and that all seems to be working, but I don't see how to add a HTTPS listener now to the application gateway? All is working on HTTP, but it's obviously not set up for HTTPS. I've tried to add it manually and through powershell but neither worked - manually it requires to upload an SSL certificate which I don't have, because it should be through cert-manager. What am I missing to do?
Screenshot:
Thanks!
Missing: For HTTPS on this application gateway, you will need a x509 certificate and its private key.
The article which you are following states the below in point 4:
Once your staging certificate is setup successfully you can switch to a production ACME server.
So, you could follow the below article to issue an ACME certificate:
https://cert-manager.io/docs/tutorials/acme/http-validation/
Or generate a self-signed certificate with openssl:
https://learn.microsoft.com/en-us/azure/aks/ingress-own-tls#generate-tls-certificates
NOTE : For production use, you should request a trusted, signed
certificate through a provider or your own certificate authority (CA).
Once the certificate is generated & updated, you can follow the below article to expose the service over HTTPS:
https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-expose-service-over-http-https#expose-services-over-https
For HTTPS you have to use the Cert-manager which basically manage the certificates SSL/TLS.
You can find the installation step here for kubernetes : https://cert-manager.io/docs/installation/kubernetes/
Cert manager requests and manger the certificate and store it inside the Kubernetes secret and ingress refer that certificate from the secret as per need.
It's easy to install setup the cert manager.
below are the YAML example you can apply once the cert-manager installation is complete and pods are up and running.
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
Replace the necessary values in above the YAML file. In ingress, you can see we are attaching the TLS part so that' secret name which will auto-generated by the cert-manager and HTTPS will be working on the domain.
I have a cluster in GKE and it is working, everything seems to be working. If I forward the ports I am able to see that the containers are working.
I am not able to setup a domain I own from namecheap.
These are the steps I followed
In Namecheap I setup a custom dns for the domain
ns-cloud-c1.googledomains.com.
ns-cloud-c2.googledomains.com.
ns-cloud-c3.googledomains.com.
ns-cloud-c3.googledomains.com.
I used the letter c because the cluster is in a c zone (I am not sure if this is right)
Because I am trying to setup as secure website I installed nginx ingress controller
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole cluster-admin \
--user $(gcloud config get-value account)
and
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.46.0/deploy/static/provider/cloud/deploy.yaml
I applied the issuer.yml
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: cert-manager
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: example#email.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
I applied ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
namespace: staging
name: ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- www.stagingmyappsrl.com
- api.stagingmyappsrl.com
secretName: stagingmyappsrl-tls
rules:
- host: wwwstaging.myappsrl.com
http:
paths:
- backend:
serviceName: myappcatalogo-svc
servicePort: 80
- host: apistaging.stagingmyappsrl.com
http:
paths:
- backend:
serviceName: myappnodeapi-svc
servicePort: 80
It seems that everything is created and working if I check in GKE website, but when I try to access I get DNS_PROBE_FINISHED_NXDOMAIN
I am not sure if I am missing an step or if I am setting up something wrong
GKE should have created a cloud load balancer for your ingress service. Depending on your config, the LB can be internal or external. You can get your LB information by looking at the services:
kubectl get svc -n ingress-nginx
Create a CNAME record in your DNS (namecheap) with the LB address and that should do it. Alternatively, if you have an IP address of the LB, create an A record in your DNS.
Cert-manager will create an ingress resource to resolve HTTPS01 challenges. Make sure your ingresses are reachable over the Internet for the HTTPS01 challenges to work. Alternatively, you could explore other solvers.
I have a EKS cluster configured with Iitio ingress gateway and my dns domain (test.com) is hosted in route53. I would like to generate the Letsencrypt certificate for my domain. I'm using the following version certmanager(0.14.1), Istio (1.6), Kubernetes (1.17). Can you please provide me the list of steps to be followed.
I am not much aware on how the setup has to be done for istio, but for ingress it's the following way, hope the same should work there too.
You can download the cert-manager helm chart from here and then you have to create the ingress rules for traffic routing, and for doing the TLS termination there you can follow this stackoverflow link
Kindly use
apiVersion: cert-manager.io/v1alpha2
in clusterissuer, if the apiVersion for clusterIssuer present in that stackoverflow post is not acceptable
There is related documentation about integration cert-menager and istio.
cert-manager
Configuration
Consult the cert-manager installation documentation to get started. No special changes are needed to work with Istio.
Usage
Istio Gateway
cert-manager can be used to write a secret to Kubernetes, which can then be referenced by a Gateway. To get started, configure a Certificate resource, following the cert-manager documentation. The Certificate should be created in the same namespace as the istio-ingressgateway deployment. For example, a Certificate may look like:
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: ingress-cert
namespace: istio-system
spec:
secretName: ingress-cert
commonName: my.example.com
dnsNames:
- my.example.com
...
Once we have the certificate created, we should see the secret created in the istio-system namespace. This can then be referenced in the tls config for a Gateway under credentialName:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: ingress-cert # This should match the Certifcate secretName
hosts:
- my.example.com # This should match a DNS name in the Certificate
Kubernetes Ingress
cert-manager provides direct integration with Kubernetes Ingress by configuring an annotation on the Ingress object. If this method is used, the Ingress must reside in the same namespace as the istio-ingressgateway deployment, as secrets will only be read within the same namespace.
Alternatively, a Certificate can be created as described in Istio Gateway, then referenced in the Ingress object:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
kubernetes.io/ingress.class: istio
spec:
rules:
- host: my.example.com
http: ...
tls:
- hosts:
- my.example.com # This should match a DNS name in the Certificate
secretName: ingress-cert # This should match the Certifcate secretName
Additionally there is an example made by #chrisnyc on istio discuss.
Hope you find this useful.