How to tell Traefik 2.1 to use a user-defined wildcard certificate for a router? - ssl

I'm trying to get Traefik to use a manually configured wildcard certificate for all routers that have a matching Host rule. I assumed Traefik would try to find a certificate based on the domains used in the Host rule, but it always uses the default generated certificate instead.
traefik.yml
global:
checkNewVersion: false
sendAnonymousUsage: false
log:
level: DEBUG
entryPoints:
web:
address: ":80"
web-secure:
address: ":443"
providers:
file:
directory: /etc/traefik/conf
watch: true
dynamic conf:
http:
routers:
test:
rule: "Host(`subdomain.wildcard.domain.tld`)"
entryPoints: ["web"]
service: service-test
middlewares: ["https_redirect"]
test-secure:
rule: "Host(`subdomain.wildcard.domain.tld`)"
entryPoints: ["web-secure"]
service: service-test
tls: {}
services:
service-test:
loadBalancer:
servers:
- url: "http://helloworld"
middlewares:
https_redirect:
redirectScheme:
scheme: https
permanent: true
Traefik is running inside a Docker container, based on the log it can see and use the mounted certificate files:
time="2020-03-04T10:44:13Z" level=debug msg="No store is defined to add the certificate <...>, it will be added to the default store."
time="2020-03-04T10:44:13Z" level=debug msg="Adding certificate for domain(s) wildcard.domain.tld,*.wildcard.domain.tld"
time="2020-03-04T10:44:13Z" level=debug msg="No default certificate, generating one"
However, when doing a curl request, the default certificate is used:
curl -k -v --header "Host: subdomain.wildcard.domain.tld" https://192.168.173.143/
* Server certificate:
* subject: CN=TRAEFIK DEFAULT CERT
* start date: Mar 4 10:44:13 2020 GMT
* expire date: Mar 4 10:44:13 2021 GMT
* issuer: CN=TRAEFIK DEFAULT CERT
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
When specifyng the certificate as the default certificate, Traefik does use it, making it more obvious that something is wrong when it tries to match the routers to fitting certificates.
tls:
certificates:
- certFile: /ssl/wildcard.crt
keyFile: /ssl/wildcard.key
stores:
default:
defaultCertificate:
certFile: /ssl/wildcard.crt
keyFile: /ssl/wildcard.key

Related

traefik Mtls problems with configuration

I have a problem with mtls in traefik,
I need to enter traefik as a client with mtls but the configuration that I tried is not working for me since it enters the link without any certificate
http:
routers:
crypto-router:
tls:
options: testmtls
rule: "PathPrefix(`/CryptoTest`)"
entryPoints:
- websecure
service: cryptoTest-service
middlewares:
- cryptoTest-stripprefix
tls:
options:
testmtls:
clientAuth:
caFiles:
- /etc/traefik/cryptolocal.crt
clientAuthType: RequireAndVerifyClientCert
I expected that it would give me some error when connecting the request without a certificate but this not happens and I need only requests with client certificates to entry

Traefik 2.0 TLS TCP passthrough

I have a VM0 where Traefik is running as a docker and two target system VM1 and VM2 which both have a webserver running.
All domainA.com requests should go to VM1 via TCP router and tls passthrough, because this webservice is handling the certificates itself.
All domainB.com requests should go to VM2 via http router and Traefik should generate the tls certs for this domain.
My problem now is, as soon as I add any tls config to the http router, it seems tcp passthrough doesn't work anymore. In the logs I see this messages:
time="2020-03-15T21:46:18Z" level=debug msg="Serving default certificate for request: \"subdomain.DomainA.com\""
time="2020-03-15T21:46:18Z" level=debug msg="http: TLS handshake error from 192.168.1.116:55103: remote error: tls: unknown certificate"
time="2020-03-15T21:46:18Z" level=debug msg="Serving default certificate for request: \"subdomain.DomainA.com\""
time="2020-03-15T21:46:18Z" level=debug msg="http: TLS handshake error from 192.168.1.116:55104: remote error: tls: unknown certificate"
And if I visit the website through Traefik, it shows me a self signed certificate from Traefik.
If I remove then all tls settings under the http router, passthrough is working again.
My Dynamic File:
http:
routers:
HTTProuter0:
rule: "HostRegexp(`{subdomain:[a-z]+}.domainA.com`)"
service: "domainA"
entryPoints:
- "websecure"
tls:
certResolver: "myresolver"
domains:
- main: "domainA.com"
sans:
- "*.domainA.com"
services:
domainA:
loadBalancer:
servers:
- url: "https://192.168.1.13:4433"
tcp:
routers:
TCProuter0:
rule: "HostSNI(`*`)"
service: "domainB"
entryPoints:
- "websecure"
tls:
passthrough: true
services:
domainB:
loadBalancer:
servers:
- address: "192.168.1.11:443"
My static file:
serversTransport:
insecureSkipVerify: true
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
spain:
address: ":4443"
certificatesResolvers:
myresolver:
acme:
email: email#email.com
storage: /etc/traefik/acme/acme.json
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 60
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
api:
insecure: true
dashboard: true
providers:
docker: {}
file:
directory: /etc/traefik/config
watch: true
log:
filePath: /etc/traefik/traefik.log
level: DEBUG
I'm stuck at this problem now for hours. I am not sure if it is a bug or if I do something wrong?
Any help would be very appreciated!
Thanks a lot
I found the problem. Unbelievable I wasted so much time for this...
It seems Traefik does not support wildcards in combination with domains in HostSNI.
HostSNI(`*`) => Works
HostSNI(`*.mydomain.com`) => DOESN'T WORK !!!!
HostSNI(`www.mydomain.com`,`web.mydomain.com`) => Work
So I added every domain explicit and now it works.

How to use digicert with nginx-ingress to enable https

I'm trying to use the certificates obtained through digicert to enable https on my nginx-ingress. We've obtained a wildcard certificate and I have the following files.
domain_name_2019-2021.csr
domain_name_2019-2021.key
domain_name_2019-2021.pem
DigiCertCA2_2019-2021.pem
star_domain_name_2019_2021.pem
TrustedRoot.pem
I've created the tls secrets by running the following commands
kubectl create secret tls tls-secret --key ${KEY_FILE} --cert ${CERT_FILE}
And used these secrets in my ingress configuration like so
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
tls:
- hosts:
- {{ .Values.host }}
secretName: tls-secret
rules:
- host: {{ .Values.host }}
http:
paths:
- path: /
backend:
serviceName: service_name
servicePort: 443
However when browse to subdomain.domain_name.com I get an invalid certificate with an error of This certificate has not been verified by a third party. And the certificate its using says Kubernetes Ingress Controller Fake Certificate
you can follow this, to install Jetstack cert-manager, once you make this installed, please follow this stackoverflow post.
It will solve your query.
The current certificates created by you are not necessary for this, here the certificate will be automatically created by jetstack once it would be able to get the acme challenge verified, for that verification sake you need to map the DNS or hostname to the Load balancer IP of nginx.
This should solve your purpose to get http to https conversion

Ingress TLS routes with cert-manager not applied

I have a K8s cluster (v1.12.8-gke.10) in GKE and have a nginx ingress with hosts rules. I am trying to enable TLS using cert-manager for ingress routes. I am using a selfsign cluster issuer. But, when I access the site over HTTPS, I am still getting the default K8s certificate. (The certificate is only valid for the following names: kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: test
name: test
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/rewrite-target: /
certmanager.k8s.io/cluster-issuer: selfsign
spec:
tls:
- secretName: test
hosts:
- test.example.com
rules:
- host: test.example.com
http:
paths:
- path: /
backend:
serviceName: test
servicePort: 80
I have checked the following and is working fine:
A cluster issuer named "selfsign"
A valid self-signed certificate backed by a secret "test"
A healthy and running nginx ingress deployment
A healthy and running ingress service of type load-balancer
I think it's issue of clusterissuer
Just have a look at my cluster issuer and check
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: prod
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: it-support#something.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: prod
# Enable the HTTP-01 challenge provider
http01: {}
Check for the right url to get production-grade certificates:
server: https://acme-v02.api.letsencrypt.org/directory
If your server url is something like this :
server: https://acme-staging-v02.api.letsencrypt.org/directory
which means you are applying for the staging certificate which may occur the error.
I've followed the tutorial from Digital Ocean and was able to enable TLS using cert-manager for ingress routes using Helm, Tiller, Letsencrypt and Nginx Ingress controller in GKE.
Instead of host test-example.com, I used my own domain name and spun up dummy backend services (echo1 and echo2) for testing purposes.
After followed the tutorial and to verify that HTTPS is working correctly, try to curl the host:
$ curl test.example.com
you should see a 308 http response (Permanent Redirect). This indicates that HTTP requests are being redirected to use HTTPS.
On the other hand, try running curl on:
$ curl https://test.example.com
Should show you the site response.
You can run the previous commands with the verbose -v flag to check into the certificate handshake and to verify the certificate information.

How do I use Search Domains with Kubernetes

I have an application deployment at foo.example.com running on Kubernetes (GKE). The ingress definition looks like this:
spec:
tls:
- hosts:
- "foo.example.com"
secretName: foo-example-com
rules:
- host: "foo.example.com"
http:
paths:
- path: /*
backend:
serviceName: web
servicePort: 80
When I navigate to http://foo.example.com/ I get (correctly) redirected to https://foo.example.com/ with the proper certificate in place.
However, I have example.com in my Search Domains. So a ping foo correctly resolves to the Kubernetes ingress.
But when I go to https://foo/ in my browser, I get the following error message in Chrome:
Your connection is not private
Attackers might be trying to steal your information from foo (for example, passwords, messages, or credit cards). Learn more
NET::ERR_CERT_AUTHORITY_INVALID
Subject: Kubernetes Ingress Controller Fake Certificate
Issuer: Kubernetes Ingress Controller Fake Certificate
Expires on: Oct 1, 2019
Current date: Oct 9, 2018
How would you get this working?
Obviously, I can't get a certificate for foo without some self-signing hackery, which I'd rather not attempt.
This will work the same even outside of the Kubernetes.
First of all each web browser (including Chrome) has a list of Authorities out of the box:
and so on.
Your CA certs (in your Secret) are self-signed by your own Certificate Authority , which is not trusted for Chrome, that's why you see the error. You probably can import your CA to Chrome, and your Chrome instance will trust it, but...
as you know TLS (SSL) certificate usually issued for a particular domain or a wildcard (CN), so foo likely won't match the wildcard expression of your certificate and you will see another SSL error:NET::ERR_CERT_COMMON_NAME_INVALID.
So, you will have to use rewrite rule to make it work.
So the way I solved this was to add a redirect ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: redirect-ingress
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "false"
ingress.kubernetes.io/configuration-snippet: |
if ($host ~ ^foo$) {
return 301 https://foo.example.com$request_uri;
}
spec:
rules:
- host: "foo"
http:
paths:
- backend:
serviceName: web
servicePort: 80
I'm not sure if it's optimal, but it did work.