Skip to content

Commit

Permalink
TLS migration for demos/web (cmusatyalab#260)
Browse files Browse the repository at this point in the history
What does this PR do?

Minimally invasive migration to TLS for the http (8000) and websocket (9000) endpoints for the real time web demo.

Where should the reviewer start?

Install the demo like a normal install. During the install-deps.sh script it will prompt for questions to generate a local self-signed cert. Anything can be entered into the cert. Start the demo as normal but connect on https://domain:http_port instead of http.

How should this PR be tested?

The first step is the cert generation (added to install-deps.sh for convenience). The second step is ensuring the two endpoints are brought up. The next step is loading the web page and accepting the self-signed cert. Reloading the web app everything should now be secure, e.g. no errors or warnings and the video works as normal.

Any background context you want to provide?

I tried to be as minimal as possible so the changes tends to follow the existing structure rather than a refactor of anything major. With that said, SimpleHTTPServer doesn't work with TLS via the -m flag so that is now a short script. I updated all the html/js files to point to https/wss. I also updated the js for Firefox's change from navigator.mozGetUserMedia to navigator.mediaDevices.getUserMedia.

What are the relevant issues?

cmusatyalab#75

Questions:

Do the docs need to be updated?
Yes. I updated the script's docs in demos/web but didn't make any changes outside of demos/web

Does this PR add new (Python) dependencies?
I don't think so.
  • Loading branch information
montag authored and Brandon Amos committed Apr 28, 2017
1 parent 07fb4c7 commit 37ba2ac
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 28 deletions.
10 changes: 10 additions & 0 deletions demos/web/create-cert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# generate self-signed certs with no password for the web and socket servers
mkdir tls
openssl genrsa -des3 -out tls/server.key 1024
openssl req -new -key tls/server.key -out tls/server.csr
cp tls/server.key tls/server.key.org
openssl rsa -in tls/server.key.org -out tls/server.key
openssl x509 -req -days 365 -in tls/server.csr -signkey tls/server.key -out tls/server.crt
echo 'converting to pem'
cat tls/server.crt tls/server.key > tls/server.pem
echo 'cert complete'
4 changes: 2 additions & 2 deletions demos/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ <h2>Training
$("#viewTSNEBtn").click(viewTSNECallback);

redrawPeople();
// createSocket("ws://facerec.cmusatyalab.org:9000", "CMU");
createSocket("ws:" + window.location.hostname + ":9000", "Local");
// createSocket("wss://facerec.cmusatyalab.org:9000", "CMU");
createSocket("wss://" + window.location.hostname + ":9000", "Local");
</script>
</html>
2 changes: 2 additions & 0 deletions demos/web/install-deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ sudo apt-get install -y libprotobuf-dev libleveldb-dev libsnappy-dev \
python-pip python-numpy python-imaging python-opencv \
git wget cmake gfortran

source ~/openface/demos/web/create-cert.sh

mkdir -p ~/src
cd ~/src
git clone https://github.com/bvlc/caffe.git
Expand Down
13 changes: 8 additions & 5 deletions demos/web/js/openface-demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ limitations under the License.

navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) ?
function(c, os, oe) {
navigator.mediaDevices.getUserMedia(c).then(os,oe);
} : null ||
navigator.msGetUserMedia;

window.URL = window.URL ||
Expand Down Expand Up @@ -329,22 +332,22 @@ function changeServerCallback() {
case "Local":
socket.close();
redrawPeople();
createSocket("ws:" + window.location.hostname + ":9000", "Local");
createSocket("wss:" + window.location.hostname + ":9000", "Local");
break;
case "CMU":
socket.close();
redrawPeople();
createSocket("ws://facerec.cmusatyalab.org:9000", "CMU");
createSocket("wss://facerec.cmusatyalab.org:9000", "CMU");
break;
case "AWS East":
socket.close();
redrawPeople();
createSocket("ws://54.159.128.49:9000", "AWS-East");
createSocket("wss://54.159.128.49:9000", "AWS-East");
break;
case "AWS West":
socket.close();
redrawPeople();
createSocket("ws://54.188.234.61:9000", "AWS-West");
createSocket("wss://54.188.234.61:9000", "AWS-West");
break;
default:
alert("Unrecognized server: " + $(this.html()));
Expand Down
18 changes: 18 additions & 0 deletions demos/web/simpleSSLServer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from __future__ import print_function
import BaseHTTPServer
import SimpleHTTPServer
import ssl
import sys


'''Adopted from https://www.piware.de/2011/01/creating-an-https-server-in-python/'''


def main(port):
httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', port), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile='tls/server.pem', server_side=True)
print('now serving tls http on port:', port)
httpd.serve_forever()

if __name__ == '__main__':
main(int(sys.argv[1]))
21 changes: 8 additions & 13 deletions demos/web/start-servers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,25 @@ trap 'kill $(jobs -p)' EXIT

cat <<EOF
Starting the HTTP server on port $HTTP_PORT
and the WebSocket server on port $WEBSOCKET_PORT.
Starting the HTTP TLS server on port $HTTP_PORT
and the Secure WebSocket server on port $WEBSOCKET_PORT.
Access the demo through the HTTP server in your browser.
If you're running on the same computer outside of Docker, use http://localhost:$HTTP_PORT
If you're running on the same computer outside of Docker, use https://localhost:$HTTP_PORT
If you're running on the same computer with Docker, find the IP
address of the Docker container and use http://<docker-ip>:$HTTP_PORT.
address of the Docker container and use https://<docker-ip>:$HTTP_PORT.
If you're running on a remote computer, find the IP address
and use http://<remote-ip>:$HTTP_PORT.
WARNING: Chromium refuses to connect to the insecure WebSocket server
if you are running a remote or Docker deployment.
We have posted a workaround to forward traffic through localhost
using ncat at http://cmusatyalab.github.io/openface/demo-1-web/.
Track our progress on fixing this at:
https://github.com/cmusatyalab/openface/issues/75.
and use https://<remote-ip>:$HTTP_PORT.
WARNING: Chromium will warn on self-signed certificates. Please accept the certificate
and reload the app.
EOF

WEBSOCKET_LOG='/tmp/openface.websocket.log'
printf "WebSocket Server: Logging to '%s'\n\n" $WEBSOCKET_LOG

python2 -m SimpleHTTPServer $HTTP_PORT &> /dev/null &
python2 simpleSSLServer.py $HTTP_PORT &> /dev/null &

cd ../../ # Root OpenFace directory.
./demos/web/websocket-server.py --port $WEBSOCKET_PORT 2>&1 | tee $WEBSOCKET_LOG &
Expand Down
23 changes: 15 additions & 8 deletions demos/web/websocket-server.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@

from autobahn.twisted.websocket import WebSocketServerProtocol, \
WebSocketServerFactory
from twisted.internet import task, defer
from twisted.internet.ssl import DefaultOpenSSLContextFactory

from twisted.python import log
from twisted.internet import reactor

import argparse
import cv2
Expand Down Expand Up @@ -53,6 +55,9 @@
modelDir = os.path.join(fileDir, '..', '..', 'models')
dlibModelDir = os.path.join(modelDir, 'dlib')
openfaceModelDir = os.path.join(modelDir, 'openface')
# For TLS connections
tls_crt = os.path.join(fileDir, 'tls', 'server.crt')
tls_key = os.path.join(fileDir, 'tls', 'server.key')

parser = argparse.ArgumentParser()
parser.add_argument('--dlibFacePredictor', type=str, help="Path to dlib's face predictor.",
Expand Down Expand Up @@ -88,8 +93,8 @@ def __repr__(self):


class OpenFaceServerProtocol(WebSocketServerProtocol):

def __init__(self):
super(OpenFaceServerProtocol, self).__init__()
self.images = {}
self.training = True
self.people = []
Expand Down Expand Up @@ -353,12 +358,14 @@ def processFrame(self, dataURL, identity):
plt.close()
self.sendMessage(json.dumps(msg))

if __name__ == '__main__':
log.startLogging(sys.stdout)

factory = WebSocketServerFactory("ws://localhost:{}".format(args.port),
debug=False)
def main(reactor):
log.startLogging(sys.stdout)
factory = WebSocketServerFactory()
factory.protocol = OpenFaceServerProtocol
ctx_factory = DefaultOpenSSLContextFactory(tls_key, tls_crt)
reactor.listenSSL(args.port, factory, ctx_factory)
return defer.Deferred()

reactor.listenTCP(args.port, factory)
reactor.run()
if __name__ == '__main__':
task.react(main)

0 comments on commit 37ba2ac

Please sign in to comment.