I have very limited knowledge about TLS certification. I wanted to enable https for docker daemon. I followed this tutorial but at the end failed to start docker daemon.
I am using docker in a Ubuntu 16.04 VM and my client and server is the same machine. So I use the $hostname as the 'Common Name' during all the process.
After following the whole process in docker documentation when I run
sudo dockerd --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H=0.0.0.0:2376
I get the INFO log that "API listen on [::]:2376"
When I use the below command:
docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=$HOST:2376 version
I get proper response.
But when I reload the daemon and try to start docker it says failed to start docker and give the following message-
Job for docker.service failed because the control process exited with error code.
See "systemctl status docker.service" and "journalctl -xe" for details.
Output of 'journalctl -xe' is:
I copied the necessary certificate to ~/.docker/ and the 'ExecStart' in my /lib/systemd/system/docker.service file is:
ExecStart=/usr/bin/dockerd -H fd:// -H 0.0.0.0:2376 \
--tlsverify --tlscacert=/home/sakib/.docker/ca.pem \
--tlskey=/home/sakib/.docker/key.pem \
--tlscert=/home/sakib/.docker/cert.pem
When I try to communicate with the API I get the following response:
$ curl -X GET https://0.0.0.0:2376/images/json
curl: (35) gnutls_handshake() failed: Certificate is bad
$ docker version
Client:
Version: 1.12.1
API version: 1.24
Go version: go1.6.3
Git commit: 23cf638
Built: Thu Aug 18 05:33:38 2016
OS/Arch: linux/amd64
An error occurred trying to connect: Get https://EL802:2376/v1.24/version: x509: certificate is valid for $HOST, not EL802
NOTE: EL802 is my hostname which I set as the 'HOST' environment variable.
I think the problem is with the 'CN' name that I chose while creating client certificate. I create the server and client certificate as below-
Server:
openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
Client:
openssl req -subj '/CN=$HOST' -new -key key.pem -out client.csr
As my client and server is my host machine(EL802) which I set as the $HOST variable.
Your picture does not show the full error line, but if the error message is:
pid file found, ensure docker is not running or delete /var/run/docker.pid
Try and delete the pid, and restart.
Also double-check your docker installation on Ubuntu, and its systemd configuration.
x509: certificate is valid for $HOST, not EL802
That means the certificate has been created with the string $HOST instead of its actual value.
openssl req -subj '/CN=$HOST'
The strong quoting of the single quotes would prevent the shell to replace $HOST with its value. Use double quotes.
Related
I have an issue when using certificate when using curl. I'm running centOS7. We managed to get the curl going in other places, but not our dev machine:
What we are trying to do:
sudo curl -X 'GET' 'https://webpage/document' --cert '/localization.crt.pem' --key '/localization.key.pem' -H 'accept: */*' -k
Im getting this error:
curl: (58) SSL peer cannot verify your certificate.
What I tried to do?(from centOS documentation)
https://access.redhat.com/documentation/en-us/red_hat_certificate_system/9/html/administration_guide_common_criteria_edition/importing_certificate_into_nssdb
# PKICertImport -d . -n "client name" -t ",," -a -i certificate.crt.pem -u C
after echo $? we get a 0, so i think it is installed properly?
Any idea on whats wrong would be great.
I have run into this recently on our linux environments. I've found that this tends to happen if you have an SSL Certificate issued that also includes a chain certificate. If that chain is not also configured on your server OpenSSL considers the certificate invalid.
I would test this using this command:
openssl s_client -showcerts -verify 5 -connect website.com:443
If you see a block like this that means you are missing the certificate chain in your server configuration:
---
SSL handshake has read 2162 bytes and written 401 bytes
Verification error: unable to verify the first certificate
---
Windows fills in the gaps and doesn't mind this type of configuration, but openssl is very particular.
I managed to solve the issue. Recompiled curl with openSSL with following tutorial:
Install curl with openssl
Works like a charm :)
So i have a simple GO server running on port 8080 using a self-signed certificate that i created with the following command:
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out local.crt -keyout local.key
When creating it i set the fields to these values:
As you can see i skipped everything but the fully qualified host name which i set to go-auth
I started my go server using the local.key and local.crt files successfully.
I tried cURLing it like:
➜ certs git:(master) ✗ curl --proxy-cacert local.crt https://go-auth/
curl: (6) Could not resolve host: go-auth
➜ certs git:(master) ✗ curl --proxy-cacert local.crt https://localhost:8080/
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
After that i tried to get the certs from the running server and saving it to the cacert.pem file and tried again:
➜ certs git:(master) ✗ echo quit | openssl s_client -showcerts -servername go-auth -connect localhost:8080 > cacert.pem
depth=0 CN = go-auth
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = go-auth
verify return:1
DONE
➜ certs git:(master) ✗ curl --cacert cacert.pem https://go-auth/
curl: (6) Could not resolve host: go-auth
➜ certs git:(master) ✗ curl --proxy-cacert cacert.pem https://go-auth/
curl: (6) Could not resolve host: go-auth
At this point i don't know, i was trying to follow the answer to this question: Use self signed certificate with cURL? but did not get the desired result.
You can use the -k parameter in order to skip the certificate validation.
Your command have to be similar to the following one:
curl -vk https://localhost:8080/
-v enable some debug information
-k disable the certificate validation
If you want to enable the certificate validation, you have two way:
Add and trust the certificate to your current CA list
By this way, you are going to "accept" your self signed certificate as a valid one, and you will be able to call the service (from your machine, obviously) using any type of HTTP client (Java, Go, cURL etc etc).
Use the --cacert parameter of the cURL command in order to specify the path related to the certificate to use in order to authenticate to the service.
I have a Kubernetes that runs 3 node cassandra cluster. when I try to connect to cqlsh from the local machine it works fine. but after enabling SSL on the cluster, I am seeing the below error. I tried setting up the cqlshrc on my local machine and also kubernetes pods but still the same error. can someone help me?
$ kubectl run -i --tty --restart=Never --rm --image cassandra cqlsh -- cqlsh cassandra-0.cassandra.default.svc.cluster.local -u cassandra -p password --ssl
Validation is enabled; SSL transport factory requires a valid certfile to be specified. Please provide path to the certfile in [ssl] section as 'certfile' option in /root/.cassandra/cqlshrc (or use [certfiles] section) or set SSL_CERTFILE environment variable.
pod "cqlsh" deleted
pod default/cqlsh terminated (Error)
Follow the below steps to troublshoot
Check the subject,validity,issuer of remote node certificate (host-remote) from host-local
echo | openssl s_client -showcerts -connect host-remote:cassandra-ssl-port 2>/dev/null | openssl x509 -noout -subject -dates -issuer
Check cqlsh.cer.pem it may only one entry and has subject with CN=host-local, this can be a possible reason that you are able to connect to local but not remote host.
openssl x509 -text -noout -in path to trustore in cqlhrc file/cqlsh.cer.pem
Your truststore shoud have root certificate/CA certificate as well to connect to remote host by successfully validating the certificate chain which is coming from remote node .
You may need to embed the root certificate in trutstore
Refer this to apply ssl in in cassandra.
I have set up a docker registry using harbor.
I have copied the appropriate certificates in /usr/share/local/ca-certificates and run sudo update-ca-certificates with success. (indicated the number of newly certs added).
When trying to login to the specific registry:
ubuntu#master1:/home/vagrant$ docker login my.registry.url
Username: pkaramol
Password:
Error response from daemon: Get https://my.registry.url/v2/: x509: certificate signed by unknown authority
However the following test succeeds:
openssl s_client -connect my.registry.url:443 -CApath /etc/ssl/certs/
...coming back with a lot of verbose output, the certificate itself and ending in :
Verify return code: 0 (ok)
curl also succeeds to the above https link (it fails when the site is not trusted).
Any suggestions?
If you read the documentation
Use self-signed certificates
Warning: Using this along with basic authentication requires to also trust the certificate into the OS cert store for some versions of docker (see below)
This is more secure than the insecure registry solution.
Generate your own certificate:
$ mkdir -p certs
$ openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
-x509 -days 365 -out certs/domain.crt
Be sure to use the name myregistrydomain.com as a CN.
Use the result to start your registry with TLS enabled.
Instruct every Docker daemon to trust that certificate. The way to do this depends on your OS.
Linux: Copy the domain.crt file to /etc/docker/certs.d/myregistrydomain.com:5000/ca.crt on every Docker host. You do not need to restart Docker.
See below link for more details
https://docs.docker.com/registry/insecure/#use-self-signed-certificates
I have a flask application running using a self signed certificate. I'm able to send in a curl request using:
curl -v -k -H "Content-Type: application/json" -d '{"data":"value1","key":"value2"}' https://<server_ip>:<port>
The verbose logs show that everything went alright.
I wanted to avoid using the -k (--insecure) option and instead specify a .pem file that curl could use. Looking at the curl man page I found that you could do this using the --cert option.
So I created a .pem file using this:
openssl rsa -in server.key -text > private.pem
CURL throws me this error when using the private.pem file:
curl: (58) unable to use client certificate (no key found or wrong pass phrase?)
Any suggestions? - or is this only possible with a properly signed certificate?
Tnx
This is just another version of this question: Using openssl to get the certificate from a server
Or put more bluntly:
Using curl --cert is wrong, it is for client certificates.
First, get the the certs your server is using:
$ echo quit | openssl s_client -showcerts -servername server -connect server:443 > cacert.pem
(-servername is necessary for SNI so that you get the right virtual server's certificate back)
Then make your curl command line use that set to verify the server in subsequent operations:
$ curl --cacert cacert.pem https://server/ [and the rest]
special teaser
Starting with curl 7.88.0 (to be shipped in February 2023), curl can save the certificates itself with the new %{certs} variable for the -w option. Blogged about here.
To make request from https server through curl. I make use of below steps
Step1: Generate self signed certificate with below code at root of the project you want to make use of it.openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes
Step2: Fill the prompt with required details but when you get to Common name input localhost e.g Common Name (eg, fully qualified host name) []:localhost
step3: When your openssl cert.pem & key.pem has being generated startup your server then in another terminal or command line run curl --cacert cert.pem https://localhost:443
Note: I use port 443 which is the default https port, you can make use of another port then make sure cert.pem file path is well referenced.