mirror of
https://github.com/laurivosandi/certidude
synced 2024-12-22 16:25:17 +00:00
Fixes
This commit is contained in:
parent
10a329c0fe
commit
f24ef4024c
42
README.rst
42
README.rst
@ -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 {
|
||||||
@ -175,24 +175,24 @@ Also adjust ``/etc/nginx/nginx.conf``:
|
|||||||
pid /run/nginx.pid;
|
pid /run/nginx.pid;
|
||||||
|
|
||||||
events {
|
events {
|
||||||
worker_connections 768;
|
worker_connections 768;
|
||||||
# multi_accept on;
|
# multi_accept on;
|
||||||
}
|
}
|
||||||
|
|
||||||
http {
|
http {
|
||||||
push_stream_shared_memory_size 32M;
|
push_stream_shared_memory_size 32M;
|
||||||
sendfile on;
|
sendfile on;
|
||||||
tcp_nopush on;
|
tcp_nopush on;
|
||||||
tcp_nodelay on;
|
tcp_nodelay on;
|
||||||
keepalive_timeout 65;
|
keepalive_timeout 65;
|
||||||
types_hash_max_size 2048;
|
types_hash_max_size 2048;
|
||||||
include /etc/nginx/mime.types;
|
include /etc/nginx/mime.types;
|
||||||
default_type application/octet-stream;
|
default_type application/octet-stream;
|
||||||
access_log /var/log/nginx/access.log;
|
access_log /var/log/nginx/access.log;
|
||||||
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:
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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!")
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
client
|
client
|
||||||
remote {{remote}}
|
remote {{remote}}
|
||||||
|
remote-cert-tls server
|
||||||
proto {{proto}}
|
proto {{proto}}
|
||||||
dev tap0
|
dev tap0
|
||||||
nobind
|
nobind
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
@ -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))
|
||||||
|
6
setup.py
6
setup.py
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user