Setting up Traefik to require client side certificates with Let's Encrypt using CLI only - traefik

I am trying to setup Traefik to do SSL client certificates much like how I used to do it with Apache. But I can't seem to get it working correctly. I'm using Docker as well, here's the command parameters
command:
- --defaultEntryPoints=http,https
- --insecureSkipVerify
- "--entryPoints=Name:http Address::80 Compress:true Redirect.entryPoint:https"
# This one works with no authentication
- "--entryPoints=Name:https Address::443 Compress:true TLS"
# These don't seem to do anything
- "--entryPoints=Name:https Address::443 Compress:true TLS CA.Optional:false CA:/run/secrets/CA"
- --ping
- --docker
- --docker.endpoint=tcp://daemon:2375
- --docker.exposedByDefault=false
- --docker.swarmMode
- --docker.watch
- --acme
- --acme.email=REDACTED#trajano.net
- --acme.onhostrule
- --acme.entrypoint=https
- --acme.httpchallenge
- --acme.httpchallenge.entrypoint=http
- --zookeeper.endpoint=zookeeper:2181
- --zookeeper.prefix=traefik
- --acme.storage=traefik/acme/acme.json

Actually it was CA.Optional and CA after all. I was using Firefox which auto-selected the certificate and when I was using Chrome, it was using the cached content. So when I cleared the browser cache things started working.
Note this approach only validates that the Client cert was signed by the CA, but does not perform any extra checks like what is the subject being used. That's a limitation of Traefik 1.7 at the moment from what I understand.

Related

Unable To Renew Subdomain's SSL Certificate via LetsEncrypt & Certbot

Really appreciate any help with this.
I have a DO droplet (running on OpenLiteSpeed Server with Ubunto 20.04) that is hosting the main domain + 2 subdomains. In that droplet, there are 3 separate folders, each made for each website. For example:
maindomain (wordpress)
subdomain1 (wordpress)
subdomain2 (standalone application, not sure if there is a server setup since it was setup by a developer)
SSL certificate is valid for /maindomain and /subdomain1. However, /subdomain2 was setup much later and for whatever reason the SSL certificate expired only for this subdomain.
I SSH'd into the server and found that certbot is installed and the existing config file for the SSL certificate looked good, so I went ahead and ran the following command:
certbot renew
I got the following error
The following certs are not due for renewal yet:
/etc/letsencrypt/live/subdomain1.domain.com/fullchain.pem expires on 2022-05-30 (skipped)
/etc/letsencrypt/live/domain.com/fullchain.pem expires on 2022-05-30 (skipped)
All renewal attempts failed. The following certs could not be renewed:
/etc/letsencrypt/live/subdomain2.domain.com/fullchain.pem (failure)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1 renew failure(s), 0 parse failure(s)
IMPORTANT NOTES:
- The following errors were reported by the server:
Domain: subdomain2.domain.com
Type: unauthorized
Detail: Invalid response from
http://subdomain2.domain.com/.well-known/acme-challenge/RaedorbX25N5YA123TXeUAy43Rsp42_eJmwPYuVfQR8
[IP_ADDRESS]: 404
To fix these errors, please make sure that your domain name was
entered correctly and the DNS A/AAAA record(s) for that domain
contain(s) the right IP address.
I went head and checked the A record and its pointing to the correct IP.
I think easiest solution would be to get a new certificate and install it, instead of renewing the existing one, however I am not sure how to do that and only on that /subdomain2
I tried to run the following in the root
certbot certonly --standalone -d subdomain2.domain.com
and got the following error
Performing the following challenges:
http-01 challenge for subdomain2.domain.com
Cleaning up challenges
Problem binding to port 80: Could not bind to IPv4 or IPv6.
Thank you for your help in advance

Minio does not seem to recognize TLS/https certificates

Im search now for hours to make minio work with self-signed tls certs using docker.
accroding to the documentation certs just need to be placed at /root/.minio/certs/CAs or /root/.minio/ inside the minio container
I tried both with no success
This is how I start minio (using saltstack):
minio:
docker_container.running:
- order: 10
- hostname: backup
- container_name: backup
- binds:
- /root/backup:/data
- /srv/salt/minio/certs:/root/.minio
- image: minio/minio:latest
- port_bindings:
- 10.10.10.1:9000:443
- environment:
- MINIO_BROWSER=off
- MINIO_ACCESS_KEY=BlaBlaBla
- MINIO_SECRET_KEY=BlaBlaBla
- privileged: false
- entrypoint: sh
- command: -c 'mkdir -p /data/backup && /usr/bin/minio server --address ":443" /data'
- restart_policy: always
If I do "docker logs minio" I just get to see http instead of https:
Endpoint: http://172.17.0.3:443 http://127.0.0.1:443
Both keys public and privat are mounted at the correct location inside the container but they not seem to recognize ...
can smb help, do I need to add some extra parameter here?
Thanks in advance
Per the docs (https://docs.minio.io/docs/how-to-secure-access-to-minio-server-with-tls.html), your keys must be named public.crt and private.key, respectively, and mounted at ~/.minio/certs (e.g. /root/.minio/certs). The CA's directory is for public certs of other servers you want to trust, for example in a distributed setup.
you doesn't need to setup cert in minio. Use nginx server then reverse proxy minio port as like 127.0.0.1:9000 port . then use cert file in nginx server block . your all problem solved

How to monitor ssl certificates with Datadog?

I have an nginx-pod which redirects traffic into Kubernetes services and stores related certificates insides its volume. I want to monitor these certificates - mainly their expiration.
I found out that there is a TLS integration in Datadog (we use Datadog in our cluster): https://docs.datadoghq.com/integrations/tls/?tab=host.
They provide sample file, which can be found here: https://github.com/DataDog/integrations-core/blob/master/tls/datadog_checks/tls/data/conf.yaml.example
To be honest, I am completely lost and do not understand comments of the sample file - such as:
## #param server - string - required
## The hostname or IP address with which to connect.
I want to monitor certificates that are stored in the pod, does it mean this value should be localhost or do I need to somehow iterate over all the certificates that are stored using this value (such as server_names in nginx.conf)?
If anyone could help me with setting sample configuration, I would be really grateful - if there are any more details I should provide, that is not a problem at all.
TLS Setup on Host
You can use a host type of instance to track all your certificate expiration dates
1- Install TLS Integration from datadog UI
2- Create instance and install datadog agent in there.
3- Create a /etc/datadog/conf.d/tls.d/conf.yaml
4- Edit following template for your need
init_config:
instances:
## #param server - string - required
## The hostname or IP address with which to connect.
#
- server: https://yourDNS1.com/
tags:
- dns:yourDNS.com
- server: https://yourDNS2.com/
tags:
- dns:yourDNS2
- server: yourDNS3.com
tags:
- dns:yourDNS3
- server: https://yourDNS4.com/
tags:
- dns:yourDNS4.com
- server: https://yourDNS5.com/
tags:
- dns:yourDNS5.com
- server: https://yourDNS6.com/
tags:
- dns:yourDNS6.com
5- Restart datadog-agent
systemctl restart datadog-agent
6- Check status if you see the tls is running successfully
watch systemctl status datadog-agent
8- Create a TLS Overview Dashboard
9- Create a Monitor for getting alert on expiration dates
TLS Setup on Kubernetes
1- Create a ConfigMap and attach that as a Volume
https://docs.datadoghq.com/agent/kubernetes/integrations/?tab=configmap

Automated way to add a alternative name to a letsencrypt Cert

I am looking for an automated way to add a new domain.
I would like to add erzgebirgstraverse.de
From https://certbot.eff.org/docs/using.html#changing-a-certificate-s-domains :
... to expand the set of domains a certificate contains ...
certbot certonly --cert-name example.com -d example.org,www.example.org
I found a way to list all existing certs:
hz1:/etc/apache2# certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: hz1.yz.to
Serial Number: 345a3c36ff032d325e78120c98d8ddc71f7
Domains: hz1.yz.to thomas-guettler.de
Expiry Date: 2021-03-23 09:19:00+00:00 (VALID: 80 days)
Certificate Path: /etc/letsencrypt/live/hz1.yz.to/fullchain.pem
Private Key Path: /etc/letsencrypt/live/hz1.yz.to/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Now I see the existing domains, and could add erzgebirgstraverse.de with the -d flag:
hz1:/etc/apache2# certbot certonly --cert-name hz1.yz.to -d hz1.yz.to,thomas-guettler.de,erzgebirgstraverse.de
But now an interactive script starts:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Apache Web Server plugin (apache)
2: Spin up a temporary webserver (standalone)
3: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-3] then [enter] (press 'c' to cancel):
systemctl reload apache2
Is there a way to add a new domain (alternative name) but non-interactive?
By default, Certbot will try to assist you in the process of generating the certificates. In addition, it will prompt you for information to help installing them in your Apache/Nginx setup.
To skip this installation step, simply use certbot certonly ... subcommand. According to the CLI manpages: Obtain or renew a certificate, but do not install it
Alternatively, you can use the flag -n/--non-interactive to make sure certbot will process without prompting anything. In such case, you must ensure all needed information is passed through the command-line. In particular, you must ensure you already agreed to the Terms & Conditions, (--agree-tos) and you provided a valid contact email (-m email#domain). Example:
certbot certonly --agree-tos -m contact&mydomain.com --cert-name hz1.yz.to -d hz1.yz.to,thomas-guettler.de,erzgebirgstraverse.de
In your questions, you were prompted for authentication method. You must understand that let's encrypt must validate the server you are executing the client can correctly be associated with the domain(s) you are trying to generate your certs. Available methods are:
Apache Web Server plugin (apache) -> certbot will create apache settings so the HTTP challenge can be used to validate the domains are actually associated with your server
Spin up a temporary webserver (standalone) -> Certbot will run its own webserver to perform the HTTP challenge. This can work only if no other webserver is listening on port 80 (apache & nginx will listen on that addresse). This method is probably useless in most server
Place files in webroot directory (webroot) -> If you already have a HTTP server listening on port 80, you can instruct certbot to put a file in the webroot directory so the HTTP challenge can be used.
To pre-select one of the 3 available methods from the command line (and avoid interactive prompt), use option --apache (1), --standalone (2) or --webroot (3).
Keep in mind that HTTP challenge is not the only solution to validate your server/domains coherence. DNS and TLS based challenges can be very useful: https://letsencrypt.org/docs/challenge-types/ I'm not sure certbot implements such challenges natively, but you can find third-party plugins that will.
In addition, think that certbot is NOT the only let's encrypt client available to generate your certificates. There is plenty clients available: https://letsencrypt.org/docs/client-options/
You'll need a minimum of: --non-interactive, --agree-tos, and -m 'you#your-email.com'. That will allow certbot to run without any interaction.
In addition it may be useful to specify the --nginx or --apache if that's appropriate for your configuration (didn't specify what webserver type this is), or certonly --manual if you actually just need the certificate.
An example of a finished command to do what you're looking for (assuming nginx here) is: certbot --nginx --non-interactive --agree-tos -m 'you#your-email.com' -d 'erzgebirgstraverse.de'
Note that all this is specified (in a somewhat roundabout way) in https://certbot.eff.org/docs/using.html

Traefik: "No ACME certificate generation required for domains" in the logs while using the default cert

I'm struggling with Let's Encrypt setup for my Docker Swarm.
Traefik is started this way in my stack's compose file:
image: traefik:v2.2
ports:
- 80:80
- 443:443
- 8080:8080
command:
- --api
- --log.level=DEBUG
- --providers.docker=true
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --providers.docker.swarmMode=true
- --providers.docker.exposedbydefault=false
- --providers.docker.network=traefik-public
- --entrypoints.http.address=:80
- --entrypoints.https.address=:443
- --certificatesResolvers.certbot=true
- --certificatesResolvers.certbot.acme.httpChallenge=true
- --certificatesResolvers.certbot.acme.httpChallenge.entrypoint=http
- --certificatesResolvers.certbot.acme.email=${EMAIL?Variable EMAIL not set}
- --certificatesResolvers.certbot.acme.storage=/certs/acme-v2.json
- --certificatesResolvers.certbot.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
...networks, volumes...
deploy:
mode: replicated
replicas: 1 # to avoid concurrency issues
...
labels:
- "traefik.docker.network=traefik-public"
- "traefik.enable=true"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
- "traefik.http.routers.traefik.rule=Host(`traefik.my-domain.com`)"
- "traefik.http.routers.traefik.entrypoints=http,https"
- "traefik.http.routers.traefik.tls.certresolver=certbot"
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:${HASHED_PASSWORD?Variable HASHED_PASSWORD not set}"
And I cannot get more than
level=debug msg="No ACME certificate generation required for domains [\"traefik.my-domain.com\"]." providerName=certbot.acme routerName=traefik#docker rule="Host(`traefik.my-domain.com`)"
I wonder why no ACME certificate is required while Firefox complains of getting the "TRAEFIK DEFAULT CERT" (Chromium also btw).
I also tried:
Without the staging server of let's encrypt
With a DNS challenge as I hope to make it work with wildcard *.my-domain.com for dev purpose (which works manually with certbot).
Setting a traefik.my-domain.com DNS zone (to remove the wildcard case from the problem)
Changed the mode "replicated" of the deploy with global as suggested here Traefik + Consul not generaitng SSL certificates in replicated mode, using TRAEFIK DEFAULT CERT
I'm presently looking for a way to handle certificates renewal with Certbot directly on my servers...
I've had same issue, and it helped me to change the volume where acme.json is stored. I think it's because Traefik sees that acme.json is not empty, he simply doesn't ask for new cert.
So if you're using something like:
command:
...
- --certificatesResolvers.certbot.acme.storage=/certs/acme-v2.json
volumes:
- "certs:/certs"
Try to use different volume:
command:
...
- --certificatesResolvers.certbot.acme.storage=/letsencrypt/acme-v2.json
volumes:
- "letsencrypt:/letsencrypt"
For me it was the set default (custom) Cert, that was valid for the full domain, so traefik didn't request a specific acme/letsencrypt one, because it thought it already has one.
After disabling the custom default cert it worked instantly.