diff --git a/README.rst b/README.rst index 2c2d290..cdccbf9 100644 --- a/README.rst +++ b/README.rst @@ -45,6 +45,12 @@ To install Certidude: apt-get install python3 python3-dev build-essential pip3 install certidude +Create a user for ``certidude``: + +.. code:: bash + + useradd certidude + Setting up CA -------------- @@ -87,11 +93,80 @@ Use web interface or following to sign a certificate on Certidude server: certidude sign client-hostname-or-common-name -Streaming push support ----------------------- +Production deployment +--------------------- + +Unstall uWSGI: + +.. code:: bash + + apt-get install uwsgi uwsgi-plugin-python3 + +Configure uUWSGI application in ``/etc/uwsgi/apps-available/certidude.ini``: + +.. code:: ini + + [uwsgi] + master = true + processes = 1 + vaccum = true + uid = certidude + gid = certidude + plugins = python34 + pidfile = /run/certidude/api/uwsgi.pid + socket = /run/certidude/api/uwsgi.sock + chdir = /tmp + module = certidude.wsgi + callable = app + chmod-socket = 660 + chown-socket = certidude:www-data + env = CERTIDUDE_EVENT_PUBLISH=http://localhost/event/publish/%s + env = CERTIDUDE_EVENT_SUBSCRIBE=http://localhost/event/subscribe/%s + +Also enable the application: + +.. code:: bash + + ln -s ../apps-available/certidude.ini /etc/uwsgi/apps-enabled/certidude.ini We support `nginx-push-stream-module `_, -configure it as follows to enable real-time responses to events: +configure the site in /etc/nginx/sites-available.d/certidude: + +.. code:: + + upstream certidude_api { + server unix:///run/uwsgi/app/certidude/socket; + } + + server { + server_name localhost; + listen 80 default_server; + listen [::]:80 default_server ipv6only=on; + + location ~ /event/publish/(.*) { + allow 127.0.0.1; # Allow publishing only from this IP address + push_stream_publisher admin; + push_stream_channels_path $1; + } + + location ~ /event/subscribe/(.*) { + push_stream_channels_path $1; + push_stream_subscriber long-polling; + } + + location / { + include uwsgi_params; + uwsgi_pass certidude_api; + } + } + +Enable the site: + +.. code:: bash + + ln -s ../sites-available.d/certidude.ini /etc/nginx/sites-enabled.d/certidude + +Also adjust ``/etc/nginx/nginx.conf``: .. code:: @@ -100,53 +175,29 @@ configure it as follows to enable real-time responses to events: pid /run/nginx.pid; events { - worker_connections 768; - # multi_accept on; + worker_connections 768; + # multi_accept on; } http { push_stream_shared_memory_size 32M; - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - types_hash_max_size 2048; - include /etc/nginx/mime.types; - default_type application/octet-stream; - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; - gzip on; - gzip_disable "msie6"; - - server { - listen 80 default_server; - listen [::]:80 default_server ipv6only=on; - server_name localhost; - - location ~ /event/publish/(.*) { - allow 127.0.0.1; # Allow publishing only from this IP address - push_stream_publisher admin; - push_stream_channels_path $1; - } - - location ~ /event/subscribe/(.*) { - push_stream_channels_path $1; - push_stream_subscriber long-polling; - } - - location /api/ { - proxy_pass http://127.0.0.1:9090/api/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - } - } + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + include /etc/nginx/mime.types; + default_type application/octet-stream; + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + gzip on; + gzip_disable "msie6"; + include /etc/nginx/sites-enabled.d/*; } - -For ``butterknife serve`` export environment variables: +Restart the services: .. code:: bash - export CERTIDUDE_EVENT_PUBLISH = "http://localhost/event/publish/%s" - export CERTIDUDE_EVENT_SUBSCRIBE = "http://localhost/event/subscribe/%s" - certidude server -p 9090 + service uwsgi restart + service nginx restart diff --git a/certidude/cli.py b/certidude/cli.py index 04bb4d7..47a0c88 100755 --- a/certidude/cli.py +++ b/certidude/cli.py @@ -755,6 +755,7 @@ def certidude_serve(user, port, listen, enable_signature): class ThreadingWSGIServer(ThreadingMixIn, WSGIServer): pass + click.echo("Listening on %s:%d" % (listen, port)) app = falcon.API() diff --git a/certidude/wsgi.py b/certidude/wsgi.py new file mode 100644 index 0000000..8a0fe59 --- /dev/null +++ b/certidude/wsgi.py @@ -0,0 +1,26 @@ + + +import falcon +from certidude.wrappers import CertificateAuthorityConfig +from certidude.api import CertificateAuthorityResource, \ + RequestDetailResource, RequestListResource, \ + SignedCertificateDetailResource, SignedCertificateListResource, \ + RevocationListResource, IndexResource, ApplicationConfigurationResource, \ + CertificateStatusResource + +# TODO: deduplicate routing code +# TODO: set up /run/certidude/api paths and permissions + +config = CertificateAuthorityConfig("/etc/ssl/openssl.cnf") + +app = falcon.API() +app.add_route("/api/{ca}/ocsp/", CertificateStatusResource(config)) +app.add_route("/api/{ca}/signed/{cn}/openvpn", ApplicationConfigurationResource(config)) +app.add_route("/api/{ca}/certificate/", CertificateAuthorityResource(config)) +app.add_route("/api/{ca}/revoked/", RevocationListResource(config)) +app.add_route("/api/{ca}/signed/{cn}/", SignedCertificateDetailResource(config)) +app.add_route("/api/{ca}/signed/", SignedCertificateListResource(config)) +app.add_route("/api/{ca}/request/{cn}/", RequestDetailResource(config)) +app.add_route("/api/{ca}/request/", RequestListResource(config)) +app.add_route("/api/{ca}/", IndexResource(config)) + diff --git a/setup.py b/setup.py index e4f0d88..24adf0c 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import setup setup( name = "certidude", - version = "0.1.2", + version = "0.1.3", author = u"Lauri Võsandi", author_email = "lauri.vosandi@gmail.com", description = "Certidude is a novel X.509 Certificate Authority management tool aiming to support PKCS#11 and in far future WebCrypto.", @@ -24,7 +24,8 @@ setup( "netifaces", "pyopenssl", "pycountry", - "humanize" + "humanize", + "pycrypto" ], scripts=[ "misc/certidude"