miguelgrinberg / Flask-SocketIO

Socket.IO integration for Flask applications.
MIT License
5.37k stars 893 forks source link

Redis SSL socketio and .crt file #918

Closed valentin-ballester closed 5 years ago

valentin-ballester commented 5 years ago

Hello, I have migrated from heroku to ibm cloud and have been configuring the server. i created a redis database as a service but im stuck with the ssl. I have correctly set the ssl for a postgress service but im kinda confused with redis. I have only a .crt file decoded from a base64 that ibm gives you. I also have to configure celery but that is another problem.

could someone tell me if my current configuration is right?

config.py

for security reasons i wont pass the real redis_url

REDIS_URL = 'rediss://admin....databases.appdomain.cloud:30385/0'

init.py :


import eventlet
eventlet.monkey_patch()
app = Flask(__name__)
app.config.from_object(Config)
socketio = SocketIO(app, certfile='redis_cert.crt', message_queue=app.config['REDIS_URL'])

The postgress configuration was easy to understand because it was more direct, there was the database and the server and they must communicate securely. The thing that get me lost is the difference of a message_queue ssl and the socket ssl or if they are the same and also i would like to know if this configuration is right.

valentin-ballester commented 5 years ago

My traceback

ERR File "/home/vcap/deps/0/python/lib/python3.6/site-packages/redis/connection.py", line 498, in connect 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR raise ConnectionError(self._error_message(e)) 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR redis.exceptions.ConnectionError: Error 1 connecting to ...databases.appdomain.cloud:30385. [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777). 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR During handling of the above exception, another exception occurred: 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR Traceback (most recent call last): 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR File "/home/vcap/deps/0/python/lib/python3.6/site-packages/redis/connection.py", line 493, in connect 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR sock = self._connect() 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR File "/home/vcap/deps/0/python/lib/python3.6/site-packages/redis/connection.py", line 736, in _connect 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR ca_certs=self.ca_certs) 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR File "/home/vcap/deps/0/python/lib/python3.6/site-packages/eventlet/green/ssl.py", line 369, in wrap_socket 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR return GreenSSLSocket(sock, *a, *kw) 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR File "/home/vcap/deps/0/python/lib/python3.6/site-packages/eventlet/green/ssl.py", line 87, in init 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR self.do_handshake() 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR File "/home/vcap/deps/0/python/lib/python3.6/site-packages/eventlet/green/ssl.py", line 260, in do_handshake 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR super(GreenSSLSocket, self).do_handshake) 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR File "/home/vcap/deps/0/python/lib/python3.6/site-packages/eventlet/green/ssl.py", line 109, in _call_trampolining 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR return func(a, **kw) 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR File "/home/vcap/deps/0/python/lib/python3.6/ssl.py", line 1068, in do_handshake 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR self._sslobj.do_handshake() 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR File "/home/vcap/deps/0/python/lib/python3.6/ssl.py", line 689, in do_handshake 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR self._sslobj.do_handshake() 2019-03-08T14:56:46.46-0300 [APP/PROC/WEB/0] ERR ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)

miguelgrinberg commented 5 years ago

You are passing the redis SSL client certificate as the web server certificate. That is wrong.

While the redis client for Python supports SSL, the redis connection for Socket.IO is currently given as a URL, which means you cannot pass a certificate and private key.

valentin-ballester commented 5 years ago

Doesnt socketio uses kombu for queues? can be the solution passing the ssl to kombu ? how could i do that?

miguelgrinberg commented 5 years ago

As I said above, this is not currently possible. All you can pass is a connection URL. SSL works only for the case where the server offers a certificate that is validated by the client. What you apparently need is to pass a client certificate to be validated by the server, that is not supported by this package, even if the underlying Kombu and/or pyredis do support it (haven't checked if they do).

valentin-ballester commented 5 years ago

Ok, so i would just disable it. just for confirmation, i cant pass the ssl in the url right ? i didnt found how to do that.

miguelgrinberg commented 5 years ago

Sorry, don't understand. You disabled what?

valentin-ballester commented 5 years ago

i think there is a option to disable ssl in the redis database service on ibm cloud but im not sure, because otherwise i cant use sockets with queue and cant emit from celery

miguelgrinberg commented 5 years ago

I have zero knowledge of IBM cloud, so I can't really advise you to disable ssl and the security risks of doing so. You need to ask them about that.

valentin-ballester commented 5 years ago

ok, im so dissapointed with the fact i have been struggling for like 3 to 4 days deploying it but well it is the learning curve i guess, i dont know what im going to do.

valentin-ballester commented 5 years ago

What i dont understand is why no other deployment of a Flask socket io with a redis queue has encounter my problem. How do Flask socketio deployment differ in other platforms, im sure they also use ssl to connect to services like redis...

miguelgrinberg commented 5 years ago

Most people self-host redis, they don't get it from a platform.

valentin-ballester commented 5 years ago

Miguel sorry to keep bothering but im really stuck at deciding whether i change again of platform or i find a solution to this, maybe its local hosting redis or ... some ideas i have.

supposing i cant use 'rediss' url to connect with the redis database with ssl proxy, because i cant send in that url the path to the .crt neither directly to the driver i thought if leaving redis and going to other alternative as rabitmq could resolve the problem

valentin-ballester commented 5 years ago

I read a very complete post that explains how to work with ibm redis but it wasnt very helpful because the only way aparently i can connect is through a url given the current state of flask-socketio.

https://github.com/IBM-Bluemix-Docs/databases-for-redis/blob/master/connecting-external.md

valentin-ballester commented 5 years ago

im like hyper frustated to know that i cant use ibm solution and all these days learning how to use it and configuring it where in vane because i cant integrate socket io, isnt there a chance you would add ssl support for message queues in the near future ? I will continue working locally on functionallities and all other things i have dedicated a lot to deploying (which i couldnt get right) and i need to release my frustration.

miguelgrinberg commented 5 years ago

I don't know how to connect to the IBM redis service. You mentioned the need to use a certificate, which is something I never heard of. Were you able to connect using the Python client for redis? If you did, then show me the connection code, then I can decide how much effort it is to do the work.

valentin-ballester commented 5 years ago

Problem solved, i added the ssl credentials embeeded in the url and redis.py automatically accepted them and i read the source code to confirm the support. Im waiting to the new release of celery which aparently is comming out these weeks that will add support for rediss protocol, so until then just local testings.

ghost commented 4 years ago

Hi, your last message was: "i added the ssl credentials embeeded in the url and redis.py automatically accepted them" can you share how to do that ? add the ssl credentials in the url?

my current redis url is redis://:my_passoword@redis_server_ip:6379/0

However, this: import redis r = redis.Redis(host='redis_server_ip',port=6379, password='my_passoword') my_key_value = r.get('key123') Works fine.

so the problem is in the Flask-SocketIO, is the url accept password ? can i pass redis:// but the websocket itself is wss:// means secure (i cant see why not)

socketio = SocketIO(app, logger=True, engineio_logger=True, debug=True, cors_allowed_origins = None, message_queue='redis://:my_passoword@redis_server_ip:6379/0')

my_passoword, redis_server_ip its just placeholders, its the reall paswword and ip ... in the code :)

the websocket itself is also SSL client connected to wss://

Thanks

miguelgrinberg commented 4 years ago

@danielgrayson2012 if your password has characters that are not valid in URLs remember that you have to escape them.