Flask application using TLS - python

I am trying to execute my Flask application over TLS, this is my example:
from flask import Flask
import ssl
app = Flask(__name__)
#app.route('/ping')
def ping():
return 'pong'
if __name__ == '__main__':
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations('./ca-crt.pem')
context.load_cert_chain('./server.crt', './server.key')
app.run('0.0.0.0', 8080, ssl_context=context)
and these is how I am generating the certificates:
# create server private key and server CSR
openssl req -nodes -new -keyout server.key -out server.csr
# generate certicate based on server's CSR using CA root certificate and CA private key
openssl x509 -req -days 365 -in server.csr -CA ca-crt.pem -CAkey ca.key -CAcreateserial -out server.crt
# verify the certificate (optionally)
openssl verify -CAfile ca-crt.pem server.crt
while for client certificate:
# create client private key and client CSR
openssl req -nodes -new -keyout client.key -out client.csr
# generate certicate based on client's CSR using CA root certificate and CA private key
openssl x509 -req -days 365 -in client.csr -CA ca-crt.pem -CAkey ca.key -CAcreateserial -out client.crt
# verify the certificate (optionally)
openssl verify -CAfile ca-crt.pem client.crt
But when I try to execute my curl request:
curl --insecure --cacert ca-crt.pem --key client.key --cert client.crt https://localhost:8080/ping -v
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
* found 1 certificates in ca-crt.pem
* found 597 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* gnutls_handshake() failed: CA is unknown
* Closing connection 0
curl: (35) gnutls_handshake() failed: CA is unknown
What is the problem?
In case I remove the part to identify the client, it works:
if __name__ == '__main__':
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.load_cert_chain('server.crt', 'server.key')
app.run('0.0.0.0', 8080, ssl_context=context)
curl --insecure https://localhost:8080/ping
pong
Moreover, in case of certificates with password, how to specify PEM password during load of certificates?

Related

Mutual TLS with self signed certificates, with requests in python

I created both client and server certificates:
# client
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out ssl/client.crt -keyout ssl/client.key
# server
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out ssl/server.crt -keyout ssl/server
Then with python I have the following:
import requests
response = requests.get(
"https://localhost:8080/",
verify="ssl/server.crt",
cert=("ssl/client.crt", "ssl/client.key")
)
I also have a gunicorn server running with the server self signed certificate.
The code snippet is throwing me the following error:
requests.exceptions.SSLError: HTTPSConnectionPool(host='localhost', port=8080): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:2633)')))
It is a self signed certificate so I am not sure what CA is it expecting.
tlsv1 alert unknown ca
The server is sending a TLS alert back since it cannot validate your client certificate - the certificate authority (ca) which signed the certificate is unknown to the server. You either need to disable client certificate validation in your server or (better) make the server trust your client certificate.
It is a self signed certificate so I am not sure what CA is it expecting.
A self-signed certificate is signed by itself, i.e. the CA is the certificate itself.
It looks like the server isn't able to validate your client certificate. If you're just using a pair of self-signed certificates for the client and server, then the server needs to also use the client's certificate as its CA, since it will attempt to validate it was signed by the CA - which in this case is the client.
I recently wrote a blog on deploying mTLS with self-signed certificates which might help you as it contains more details, specifically with how to configure the client and server. Check it out here: https://otterize.com/blog/so-you-want-to-deploy-mtls

Python requests with https - certificate verify failed

I am attempting to estabilish a https connection between 2 applications: 1 is a api in nodejs and the other is a python client application.
After reading about https and certificates i have created a self-signed certificate.
To do so i used the following command:
openssl req -newkey rsa:2048 -nodes -keyout pvtkey.pem -x509 -days 365 -out domain.crt
And this to have the public key explicitely:
openssl rsa -in pvtkey.pem -pubout > pubkey.pem
Then on my python code i have the following line to make the request:
response = requests.post(endpoint, cert=("home/pi/se24-title.crt", "/home/pi/pvtkey.pem"), headers=self.headers, json=req_payload)
When i run to test my code i get the following error:
Max retries exceeded with url: /api/title
(Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')])")))
Previously i had also tried to install the crt to the trusted certificates and make the requests like this:
response = requests.post(endpoint, verify=True, headers=self.headers, json=req_payload)
but still have the same result.
What am i doing wrong?
Could it be the certificate i have generated?
So i managed to figure out how to do it.
Somehow i must have missed some step along the way but this is how i ended up being able to install the self-signed-certificate:
STEPS:
1. Create a self-signed certificate
> openssl req -newkey rsa:2048 -nodes -keyout pvtkey.pem -x509 -days 365 -out domain.crt
2. Create the public key from the private key
> openssl rsa -in pvtkey.pem -pubout > pubkey.pem
3. To install the certificate on raspbian:
sudo mkdir /usr/local/share/ca-certificates/extra
sudo cp domain.crt /usr/local/share/ca-certificates/extra/domain.crt
sudo update-ca-certificates
Hope this helps other people with the same issue.

how to run flask app in localhost with SSL

I tried to run my Flask Application on localhost and as well as on my local network's IP address and it ran very well (without SSL).
However, when I tried to run the application with SSL then the web browsers didn't load the page and gives the error:
Your connection is not private : NET::ERR_CERT_INVALID
Methods I have tried but failed:
1. Using Self-signed .pem certificate (Subject Type=CA)
With generated certificate .pem, cert key, and configuring my flask app use it.
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
app.run(
host='192.168.1.127', port="8282", debug=True,
ssl_context=('cert.pem', 'key.pem'),
)
2. Using Self-signed .crt certificate
With generated certificate .crt, cert key, and configuring my flask app use it.
$ openssl genrsa -des3 -out server.key 1024
$ openssl req -new -key server.key -out server.csr
$ cp server.key server.key.org
$ openssl rsa -in server.key.org -out server.key
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
app.run(
host='192.168.1.127', port="8282", debug=True,
ssl_context=('server.crt', 'server.key')
)
3. Run Flask with ssl_context='adhoc'
```
app.run(
host='192.168.1.127', port="8282", debug=True,
ssl_context='adhoc'
)
```
I am trying to build a system where multiple raspberry pi are located at different rooms of the house but they are connected to the same home network.
There is the main computer on the same network which acts as a Controller and to implement the system successfully I need to make requests from the controller system to all the Raspberry PI over HTTPS.
Its working.
The message connection not private is misleading, what is actually happening is that the connection is encrypted with a certificate that is not in your chain of trust. Even if it was, I doubt the browser would accept a certificate for an IP address.
In any case, your connection is indeed encrypted.
You don't shoe the additional details. But you can try to add the generated certificate to your system's chain of trust.

Custom web server & self-signed certificate

First of all let me to say my knowledge of ssl and criptography protocols is very limited. Please be patient if I say something blatantly wrong :-) . Feel free to correct me!
I'm building a custom web server to be deployed inside an isolated local network; this is how I run my service (Python code):
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_context.load_cert_chain(certfile='mykey.crt', keyfile='mykey.key')
... client connects to https port 443 ...
ssl_sock = ssl_context.wrap_socket(sock, server_side=True)
This is how I generated mykey.crt and mykey.key files:
$ openssl genrsa -des3 -out mykey.orig.key 2048
$ openssl rsa -in mykey.orig.key -out mykey.key
$ openssl req -new -key mykey.key -out mykey.csr
$ openssl x509 -req -days 3650 -in mykey.csr -signkey mykey.key -out mykey.crt
So far so good, my webserver works very well. But I have go past the "not secure" warning that Firefox rightfully shove in my face.
I'd like to install my self-signed certificate in the few clients that are going access my web server in order to permanently avoid the warning.
I followed every single certificate installation guide I was able to find but I absolutely cannot get Firefox (and Chrome) accept my certificate. And I get no error message whatsoever from the browsers.
I think I'm missing something in the certificate generation commands.
Somebody could help me?
Thanks a lot!
self-signed certificate can uses only for tests. You have to get the certificate from an 'Accredited certification authority'
2) check please : self-signed certificate need to has next data:
URL, address,
name,
email
3) you should use a certificate signed by a CA

How to add a SSL certificate after running Web2py 'one step production deployment'

I have set up a web2py environment on a linux server using the 'one step production deployment' descriped in the web2py document.
Now I can go to my website by typing my domain name into a web browser, except now it is untrusted by the browser.
Then I got a ssl certificate that I want to add to my server.
So my question is how to add ssl certificate after using the one step deployment?
I searched online, but most tutorial is to setup every thing from scratch.
If you look into the one-step-production-deployment script, you can see that it generated a self-signed cert:
echo "creating a self signed certificate"
echo "=================================="
openssl genrsa 1024 > /etc/apache2/ssl/self_signed.key
chmod 400 /etc/apache2/ssl/self_signed.key
openssl req -new -x509 -nodes -sha1 -days 365 -key /etc/apache2/ssl/self_signed.key > /etc/apache2/ssl/self_signed.cert
openssl x509 -noout -fingerprint -text < /etc/apache2/ssl/self_signed.cert > /etc/apache2/ssl/self_signed.info
And let Apache use it:
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/self_signed.cert
SSLCertificateKeyFile /etc/apache2/ssl/self_signed.key
# ...
So I think what you need to do is changing the path above to your new cert.

Categories

Resources