I'm trying to use Insomnia with Client Certificates. I followed this document from the Insomnia documentation. I added my certificate pem files and password.
The problem is that I'm still getting this error:
Error: Couldn't connect to server.
Do you have any idea why? Thanks.
Insomnia seems rather strict in the rules to apply the client certificate.
For example, if you connect to localhost:5050 you should put localhost:5050 as the host. Localhost as such does not work in this case.
Key + Certificate is also the safest way to get working results. I've noticed a number of cases where the encapsulated certificates (PFX) didn't work but the key + certificate file did. I assume that this is related to the way the pfx-certificates are created because it also applies for the browsers I test with.
I was able to consume an extremely and rare service using insomnia version 2021.4.1. I could not consume it with Soapui nor Postman.
I followed these easy steps. It worked at first attempt :D, just the p12 file was enough on my case.
Importing Certificates with Insomnia
I will put here the official documentation, in case the link disappears:
Insomnia supports PFX (Mac), and PEM (Windows and Linux) certificates. To import a new certificate, open the Document/Collection Settings dialog – accessible from the top-left menu – and click on the Client Certificates tab. From here, you can add new certificates and view existing ones.
Now lets walk through how to import one.
If you’re familiar with client certificates, the only field needing explanation should be the Host field.
Host: certificate will be sent when the host (and port if specified) matches
PFX: certificate in PFX or PKCS12 format (Only supported on Mac)
CRT File + Key File: certificate and key pair (only supported on Windows and Linux)
Passphrase: An optional passphrase for the certificate if required
After importing a certificate, it will show up in the main certificates list. From here, it can be enabled/disabled or deleted.
Insomnia is very strict about self-signed certificates.
I had a similar issue on a Windows environment with Insomnia version 2022.2.1.
My solution was to add the intermediate and root certificates as well to the client certificate (.crt) file with the following order:
-----BEGIN CERTIFICATE-----
client cert
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
intermediate cert
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
root cert
-----END CERTIFICATE-----
Then I imported the client certificate .crt file and .key file for the host and it worked.
Related
I am trying to make REST calls to server from a client.
Server Side
I am using Flask as web server. I have generated the certificate(cert.pem) and public key(key.pem) using the following command.
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
Following is the server side code.
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}
#app.route('/someroute/<arg1>,<arg2>', methods=['GET'])
def fn1(arg1,arg2):
res = fn2(arg1, arg2)
return str(res)
def fn2(un,pwd):
#Do something and return a number
return num
if __name__ == '__main__':
context = ('cert.pem', 'key.pem')
app.run(host="ip", port=port1, debug=True, ssl_context=context)
Client Side
I have a flask application from which I need to make REST calls to the above server. Following is the code I am using to do so.
import requests
# Below is the part of a function which gets called upon hitting a route in Flask.
ret = requests.get("https://<ip>:<port1>/<someroute>/arg1,arg2", verify=True)
print ret.text
This is throwing the following error.
requests.exceptions.SSLError: [Errno 1] _ssl.c:510: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
This error is expected as the certificate is not known to the client. Everything is working perfectly fine if I skip the certificate verification (verify=False).
How do I make the client trust this unknown server SSL certificate? I have seen solutions where I need to use Nginx on the client side. Can we not do some changes on flask(client side) itself to make it trust my server? If yes, what is that exact change I should be making in Flask? Also, suggest if urllib is better than requests.
UPDATE 1
I have another query here. From above, I understood that requests.get verifies the certificate every time we make a REST call (Please correct me if I am wrong). But, this looks like an extra load. Can we not have an encrypted connected established in the beginning and exchange the data by encrypting it with a private key? So, how to implement the beginning part - Send private key by encrypting it with the public key to the server and then start exchanging data by encrypting the data with the private key.
OC (original comment):
Server Side
I am using Flask as web server. I have generated the certificate(cert.pem) and public key(key.pem) using the following command.
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 36
If you read man req it says,
-out filename
This specifies the output filename to write to or standard output by default.
-keyout filename
This gives the filename to write the newly created private key to. If this option is not specified then the filename present in the configuration file is used.
Here, cert.pem could be referred to as the public certificate and key.pem really is your private key (Keep it safe and well, private). FTFY.
OC (original comment):
This error is expected as the certificate is not known to the client. Everything is working perfectly fine if I skip the certificate verification (verify=False).
How do I make the client trust this unknown server SSL certificate? I have seen solutions where I need to use Nginx on the client side. Can we not do some changes on flask(client side) itself to make it trust my server? If yes, what is that exact change I should be making in Flask? Also, suggest if urllib is better than requests.
I'll answer this backwards, but first a little background. I found these links really useful to understand - on a high level - how the SSL/TLS handshake happens and how authentication is carried out
IBM: An overview of the SSL or TLS handshake
IBM: How SSL and TLS provide authentication
Now, coming back to your question,
requests > urllib (Personal opinion, but requests does have a good support and is mature - not implying that urllib isn't)
It looks like you want to do server authentication only, for that your client needs the server's public certificate. From How SSL and TLS provide authentication:
The certificates required are as follows, where CA X issues the certificate to the SSL or TLS client, and CA Y issues the certificate to the SSL or TLS server:
For server authentication only, the SSL or TLS server needs:
The personal certificate issued to the server by CA Y
The server's private key
and the SSL or TLS client needs:
The CA certificate for CA Y
Use it in requests.get referring this from requests, which says,
You can pass verify the path to a CA_BUNDLE file or directory with certificates of trusted CAs:
requests.get('https://github.com', verify='/path/to/certfile')
Once you do that and have good certificates, it should work.
NOTE: The openssl command in the OC does not show any subject for the key/cert pair, this would still fail cert verification, refer documentation that shows how to generate self-signed certs. There's a requirement to provide SANs (SubjectAltNames) so providing just a CommonName (CN) in the subject won't future proof your process.
EDIT:
The CA talk in the IBM document can be confusing, but since this is a self-signed cert, you don't have to worry about this, just think of it as your Flask server being the SSL/TLS server, and any client of that server can do server verification using server's public key.
OC (original comment):
From above, I understood that requests.get verifies the certificate every time we make a REST call (Please correct me if I am wrong). But, this looks like an extra load.
That's true. It would perform verification each time. To avoid that you can use requests.Session() as mentioned in requests SSL Cert Verification
OC (original comment):
Can we not have an encrypted connected established in the beginning and exchange the data by encrypting it with a private key? So, how to implement the beginning part - Send private key by encrypting it with the public key to the server and then start exchanging data by encrypting the data with the private key.
This is explained really well in the IBM docs listed
I was working on a sample TLS client/server program to perform certificate validation.
For a self signed certificate validation, these are the steps i followed.
#server side:
Generated a server key file serverkey.key
Generated a CSR certificate servercert.csr from the key file.
Digitally signed(using openssl x509 utility) the servercert.csr using a
generated rootCA.key and rootCA.cert. server certificate file servercert.cert
is generated.
Loaded the certificate file(servercert.cert) and key file(serverkey.key) using
SSL_CTX_use_certificate_file and SSL_CTX_use_PrivateKey openssl apis.
#client side:
Loaded the server ca-file --> rootCA.cert (which was manually copied to the
client) using the SSL_CTX_load_verify_locations api.
Using the SSL_get_verify_result() api validated the certificate that server
sends in the Certificate message.
The question that i have is that if i use a trusted CA(like godaddy) to sign a server CSR certificate, will the CA be providing its public key file (something similar to rootCA.cert) as well which was used for signing ?
By which i can load the same to the trusted list at client side using SSL_CTX_load_verify_locations api.
My intention is to keep the code unchanged regardless of being a self signed certificate or a valid CA provided certificate.
When (any) x509 certificate is generated, these things happen:
Private key is generated
Public key (associated with the private key mentioned above) is embedded in the new certificate (becomes an integral part of it)
The new certificate is signed using private key of the issuer (read: CA)
In order to verify the certificate integrity (to check if nobody tampered with it) - you need to verify the signature (created using issuer's private key - see 3)). To be able to do it you need to obtain (somehow) the issuer's public key. This key is embedded in the issuer's certificate (see 2)). Usually the trusted CAs' certificates are stored in so called trusted certificate store. In case of OpenSSL you specify this "store" by using SSL_CTX_load_verify_locations function (and a few other simmilar functions - consult OpenSSL documentation).
To summarize:
In your case the location pointed by SSL_CTX_load_verify_locations should contain your CA's certificate(s) - all of them - the whole certificate chain up to the self-signed root certificate. You can obtain all of the certificates in the chain from your CA (in your case GoDaddy).
I hope that helps.
If I can clarify anything more please ask.
Mojolicious lets me specify an ssl certificate and key when starting the app:
> ./myapp.pl prefork --listen 'https://*:8485&cert=my.crt&key=my.key'
I am trying todo this with a rapidssl certificate.
Connecting to this service results in wget being rather unhappy:
$ wget https://example.com:8485/
--2016-06-22 09:50:49-- https://example.com:8485/
Resolving example.com (example.com)... 1.3.2.4
Connecting to example.com (example.com)|1.3.2.4|:8485... connected.
ERROR: cannot verify example.com's certificate, issued by `/C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3':
Unable to locally verify the issuer's authority.
To connect to example.com insecurely, use `--no-check-certificate'.
No big surprise, since when using rapidssl certs in other applications I have
to specify an intermediate certificate as well. So I tried to add this here too by concatenating the intermediate cert to the site certificate, but this has no influence on the outcome.
I also tried to put the intermediate certificate along with the root cert into a separate file and start with:
> ./myapp.pl prefork --listen 'https://*:8485&cert=my.crt&key=my.key&ca=myca.crt'
but the result was equally uninspiring:
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
please advise.
If you want the server to send not only the leaf (servers) certificate but also any other (intermediate) certificates to the client then you simply add these to the cert file in the correct order. This means your my.crt should look like this
----BEGIN CERTIFICATE-----
MII... the leaf certificate
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MII... the first intermediate certificate, i.e. the one which signed the leaf cert
-----END CERTIFICATE-----
...
We are using JBoss 5.1. We have deployed a web service and wish to add certificate functionality. We have created a CA and a certificate signed by that CA (we used openssl and the java keytool to create the .keystore file). We imported both the CA and the certificate in the .keystore file and pointed the connector (in server.xml) on that .keystore:
The common name used for the CA is aname.com while the common name for the certificate is hostname. The validity period of the certificate is almost one year while for the CA is a little more.
Trying to access the web service url (https://hostname:8443/path_to_webservice) with Internet Explorer we get the error that our certificate is not issued by a trusted certificate authority.
When we select to view the certificate in the browser, we get a certificate that is issued for hostname, issued by hostname and its validity period is only 3 months. Obviously, the certificate we get from Internet Explorer is very different than the one we created.
How can I solve this issue? Is it a certificate issue or do I need to make some changes in JBoss?
Is it a certificate issue or do I need to make some changes in JBoss?
While I'm not able to provide you a precise answer, I'll provide you some guiding questions that may help you solve the problem :-) Are you able to import this certificate (the pem file, which you used to create the keystore file) in a browser? What about the fingerprint, does it looks the same as the one stored in the JBoss? Does this bogus certificate reminds you of any previous attempt?
I'd say that this is most certainly a problem with the certificate itself, as I don't believe JBoss is able to fake your certificate :-)
I followed the instructions at:
How To Build An Apple Push Notification Provider Server
When I run the php script on my MacOSX or on Windows using Parallel desktop, the script works. But as soon as I run it on my hosting I get the message:
Warning: stream_socket_client() [function.stream-socket-client]: unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Connection timed out) in provider.php on line 23
Failed to connect 110 Connection timed out
Does this have to do with the certificates? If so how can I make a certificate that could work on the computer where my hosting is located.
Your hosting provider probably does not allow outbound connections to ports 2195 and 2196. Most shared hosting providers do not have those ports open. You might need to get a VPS or you can also try UrbanAirship which provides Apple Notification Service integration and is free for a certain limit per month.
Yes you need a certificate. THis is explained in the Apple docs. One catch, you will probably need to convert the cert to .pem format. The .pem cert needs to include both the certificate and the RSA private key.
Here is a good site to read: http://www.macoscoders.com/2009/05/17/iphone-apple-push-notification-service-apns/
My pem looks like:
Bag Attributes
friendlyName: Apple Development Push Services: <my data>
localKeyID: <my local key in hexascii>
subject=/UID=com.my.push.sandbox1/CN=Apple Development Push Services: <my data>/C=US
issuer=/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority
-----BEGIN CERTIFICATE-----
<my certificate data omitted>
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
<my key data omitted>
-----END RSA PRIVATE KEY-----
I found the simplest and cheapest solution was to request a dedicated IP from your hosting company. At Blue Host it was $2.50 a month. With this dedicated IP, they were willing to open ports 2195 and 2196.