1
0
mirror of https://github.com/laurivosandi/certidude synced 2024-12-23 00:25:18 +00:00
This commit is contained in:
Lauri Võsandi 2015-07-27 18:49:50 +03:00
parent 10a329c0fe
commit f24ef4024c
9 changed files with 49 additions and 32 deletions

View File

@ -13,8 +13,8 @@ Features
-------- --------
* Standard request, sign, revoke workflow via web interface. * Standard request, sign, revoke workflow via web interface.
* Colored command-line interface, check out ``butterknife list`` * Colored command-line interface, check out ``certidude list``
* OpenVPN integration, check out ``butterknife setup openvpn server`` and ``butterknife setup openvpn client`` * OpenVPN integration, check out ``certidude setup openvpn server`` and ``certidude setup openvpn client``
* Privilege isolation, separate signer process is spawned per private key isolating * Privilege isolation, separate signer process is spawned per private key isolating
private key use from the the web interface. private key use from the the web interface.
* Certificate numbering obfuscation, certificate serial numbers are intentionally * Certificate numbering obfuscation, certificate serial numbers are intentionally
@ -42,7 +42,7 @@ To install Certidude:
.. code:: bash .. code:: bash
apt-get install python3 python3-dev build-essential apt-get install python3 python3-pip python3-dev cython3 build-essential libffi-dev libssl-dev
pip3 install certidude pip3 install certidude
Create a user for ``certidude``: Create a user for ``certidude``:
@ -96,7 +96,7 @@ Use web interface or following to sign a certificate on Certidude server:
Production deployment Production deployment
--------------------- ---------------------
Unstall uWSGI: Install uWSGI:
.. code:: bash .. code:: bash
@ -120,8 +120,8 @@ Configure uUWSGI application in ``/etc/uwsgi/apps-available/certidude.ini``:
callable = app callable = app
chmod-socket = 660 chmod-socket = 660
chown-socket = certidude:www-data chown-socket = certidude:www-data
env = CERTIDUDE_EVENT_PUBLISH=http://localhost/event/publish/%s env = CERTIDUDE_EVENT_PUBLISH=http://localhost/event/publish/%(channel)s
env = CERTIDUDE_EVENT_SUBSCRIBE=http://localhost/event/subscribe/%s env = CERTIDUDE_EVENT_SUBSCRIBE=http://localhost/event/subscribe/%(channel)s
Also enable the application: Also enable the application:
@ -135,7 +135,7 @@ configure the site in /etc/nginx/sites-available.d/certidude:
.. code:: .. code::
upstream certidude_api { upstream certidude_api {
server unix:///run/uwsgi/app/certidude/socket; server unix:///run/certidude/api/uwsgi.sock;
} }
server { server {
@ -192,7 +192,7 @@ Also adjust ``/etc/nginx/nginx.conf``:
error_log /var/log/nginx/error.log; error_log /var/log/nginx/error.log;
gzip on; gzip on;
gzip_disable "msie6"; gzip_disable "msie6";
include /etc/nginx/sites-enabled.d/*; include /etc/nginx/sites-enabled/*;
} }
Restart the services: Restart the services:

View File

@ -235,7 +235,7 @@ class RequestListResource(CertificateAuthorityBase):
url_template = os.getenv("CERTIDUDE_EVENT_SUBSCRIBE") url_template = os.getenv("CERTIDUDE_EVENT_SUBSCRIBE")
if url_template: if url_template:
# Redirect to nginx pub/sub # Redirect to nginx pub/sub
url = url_template % request.fingerprint() url = url_template % dict(channel=request.fingerprint())
click.echo("Redirecting to: %s" % url) click.echo("Redirecting to: %s" % url)
resp.status = falcon.HTTP_FOUND resp.status = falcon.HTTP_FOUND
resp.append_header("Location", url) resp.append_header("Location", url)

View File

@ -15,6 +15,7 @@ import logging
import signal import signal
import netifaces import netifaces
import urllib.request import urllib.request
import subprocess
from humanize import naturaltime from humanize import naturaltime
from ipaddress import ip_network from ipaddress import ip_network
from time import sleep from time import sleep
@ -320,11 +321,12 @@ def certidude_setup_client(quiet, **kwargs):
type=click.File(mode="w", atomic=True, lazy=True), type=click.File(mode="w", atomic=True, lazy=True),
help="OpenVPN configuration file") help="OpenVPN configuration file")
@click.option("--directory", "-d", default="/etc/openvpn/keys", help="Directory for keys, /etc/openvpn/keys by default") @click.option("--directory", "-d", default="/etc/openvpn/keys", help="Directory for keys, /etc/openvpn/keys by default")
@click.option("--key-path", "-k", default=HOSTNAME + ".key", help="Key path, %s.key relative to --directory by default" % HOSTNAME) @click.option("--key-path", "-key", default=HOSTNAME + ".key", help="Key path, %s.key relative to --directory by default" % HOSTNAME)
@click.option("--request-path", "-r", default=HOSTNAME + ".csr", help="Request path, %s.csr relative to --directory by default" % HOSTNAME) @click.option("--request-path", "-csr", default=HOSTNAME + ".csr", help="Request path, %s.csr relative to --directory by default" % HOSTNAME)
@click.option("--certificate-path", "-c", default=HOSTNAME + ".crt", help="Certificate path, %s.crt relative to --directory by default" % HOSTNAME) @click.option("--certificate-path", "-crt", default=HOSTNAME + ".crt", help="Certificate path, %s.crt relative to --directory by default" % HOSTNAME)
@click.option("--authority-path", "-a", default="ca.crt", help="Certificate authority certificate path, ca.crt relative to --dir by default") @click.option("--dhparam-path", "-dh", default="dhparam2048.pem", help="Diffie/Hellman parameters path, dhparam2048.pem relative to --directory by default")
def certidude_setup_openvpn_server(url, config, subnet, email_address, common_name, org_unit, directory, key_path, request_path, certificate_path, authority_path, local, proto, port): @click.option("--authority-path", "-ca", default="ca.crt", help="Certificate authority certificate path, ca.crt relative to --dir by default")
def certidude_setup_openvpn_server(url, config, subnet, email_address, common_name, org_unit, directory, key_path, request_path, certificate_path, authority_path, dhparam_path, local, proto, port):
# TODO: Intelligent way of getting last IP address in the subnet # TODO: Intelligent way of getting last IP address in the subnet
subnet_first = None subnet_first = None
subnet_last = None subnet_last = None
@ -345,6 +347,7 @@ def certidude_setup_openvpn_server(url, config, subnet, email_address, common_na
certificate_path = os.path.join(directory, certificate_path) certificate_path = os.path.join(directory, certificate_path)
request_path = os.path.join(directory, request_path) request_path = os.path.join(directory, request_path)
authority_path = os.path.join(directory, authority_path) authority_path = os.path.join(directory, authority_path)
dhparam_path = os.path.join(directory, dhparam_path)
if not os.path.exists(certificate_path): if not os.path.exists(certificate_path):
click.echo("As OpenVPN server certificate needs specific key usage extensions please") click.echo("As OpenVPN server certificate needs specific key usage extensions please")
@ -365,6 +368,10 @@ def certidude_setup_openvpn_server(url, config, subnet, email_address, common_na
extended_key_usage="serverAuth", extended_key_usage="serverAuth",
wait=True) wait=True)
if not os.path.exists(dhparam_path):
cmd = "openssl", "dhparam", "-out", dhparam_path, "2048"
subprocess.check_call(cmd)
if retval: if retval:
return retval return retval

View File

@ -35,9 +35,12 @@ def raw_sign(private_key, ca_cert, request, basic_constraints, lifetime, key_usa
cert = crypto.X509() cert = crypto.X509()
# Set public key
cert.set_pubkey(request.get_pubkey()) cert.set_pubkey(request.get_pubkey())
# Set issuer
cert.set_issuer(ca_cert.get_subject())
# TODO: Assert openssl.cnf policy for subject attributes # TODO: Assert openssl.cnf policy for subject attributes
# if request.get_subject().O != ca_cert.get_subject().O: # if request.get_subject().O != ca_cert.get_subject().O:
# raise ValueError("Orgnization name mismatch!") # raise ValueError("Orgnization name mismatch!")

View File

@ -1,5 +1,6 @@
client client
remote {{remote}} remote {{remote}}
remote-cert-tls server
proto {{proto}} proto {{proto}}
dev tap0 dev tap0
nobind nobind

View File

@ -7,6 +7,7 @@ local {{local}}
key {{key_path}} key {{key_path}}
cert {{certificate_path}} cert {{certificate_path}}
ca {{authority_path}} ca {{authority_path}}
dh {{dhparam_path}}
comp-lzo comp-lzo
user nobody user nobody
group nogroup group nogroup

View File

@ -28,7 +28,7 @@ def notify(func):
assert isinstance(cert, Certificate), "notify wrapped function %s returned %s" % (func, type(cert)) assert isinstance(cert, Certificate), "notify wrapped function %s returned %s" % (func, type(cert))
url_template = os.getenv("CERTIDUDE_EVENT_PUBLISH") url_template = os.getenv("CERTIDUDE_EVENT_PUBLISH")
if url_template: if url_template:
url = url_template % csr.fingerprint() url = url_template % dict(channel=csr.fingerprint())
notification = urllib.request.Request(url, cert.dump().encode("ascii")) notification = urllib.request.Request(url, cert.dump().encode("ascii"))
notification.add_header("User-Agent", "Certidude API") notification.add_header("User-Agent", "Certidude API")
notification.add_header("Content-Type", "application/x-x509-user-cert") notification.add_header("Content-Type", "application/x-x509-user-cert")

View File

@ -1,5 +1,5 @@
import os
import falcon import falcon
from certidude.wrappers import CertificateAuthorityConfig from certidude.wrappers import CertificateAuthorityConfig
from certidude.api import CertificateAuthorityResource, \ from certidude.api import CertificateAuthorityResource, \
@ -13,6 +13,9 @@ from certidude.api import CertificateAuthorityResource, \
config = CertificateAuthorityConfig("/etc/ssl/openssl.cnf") config = CertificateAuthorityConfig("/etc/ssl/openssl.cnf")
assert os.getenv("CERTIDUDE_EVENT_SUBSCRIBE"), "Please set CERTIDUDE_EVENT_SUBSCRIBE to your web server's subscribe URL"
assert os.getenv("CERTIDUDE_EVENT_PUBLISH"), "Please set CERTIDUDE_EVENT_SUBSCRIBE to your web server's subscribe URL"
app = falcon.API() app = falcon.API()
app.add_route("/api/{ca}/ocsp/", CertificateStatusResource(config)) app.add_route("/api/{ca}/ocsp/", CertificateStatusResource(config))
app.add_route("/api/{ca}/signed/{cn}/openvpn", ApplicationConfigurationResource(config)) app.add_route("/api/{ca}/signed/{cn}/openvpn", ApplicationConfigurationResource(config))

View File

@ -5,7 +5,7 @@ from setuptools import setup
setup( setup(
name = "certidude", name = "certidude",
version = "0.1.3", version = "0.1.7",
author = u"Lauri Võsandi", author = u"Lauri Võsandi",
author_email = "lauri.vosandi@gmail.com", 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.", description = "Certidude is a novel X.509 Certificate Authority management tool aiming to support PKCS#11 and in far future WebCrypto.",
@ -25,7 +25,9 @@ setup(
"pyopenssl", "pyopenssl",
"pycountry", "pycountry",
"humanize", "humanize",
"pycrypto" "pycrypto",
"cryptography",
"markupsafe"
], ],
scripts=[ scripts=[
"misc/certidude" "misc/certidude"