mirror of
https://github.com/laurivosandi/certidude
synced 2024-12-22 16:25:17 +00:00
commit
70f89f996a
@ -60,7 +60,7 @@ To install Certidude:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
apt-get install -y python3 python3-pip python3-dev cython3 build-essential libffi-dev libssl-dev
|
||||
apt-get install -y python3 python3-pip python3-dev cython3 build-essential libffi-dev libssl-dev libkrb5-dev
|
||||
pip3 install certidude
|
||||
|
||||
Make sure you're running PyOpenSSL 0.15+ and netifaces 0.10.4+ from PyPI,
|
||||
|
@ -9,18 +9,15 @@ import mimetypes
|
||||
import netifaces
|
||||
import os
|
||||
import pwd
|
||||
import random
|
||||
import re
|
||||
import signal
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from certidude.helpers import expand_paths, \
|
||||
certidude_request_certificate
|
||||
from certidude.signer import SignServer
|
||||
from certidude.wrappers import CertificateAuthorityConfig, \
|
||||
CertificateAuthority, Certificate, subject2dn, Request
|
||||
from certidude.wrappers import CertificateAuthorityConfig, subject2dn
|
||||
from datetime import datetime
|
||||
from humanize import naturaltime
|
||||
from ipaddress import ip_network
|
||||
@ -46,7 +43,7 @@ assert hasattr(crypto.X509Req(), "get_extensions"), "You're running too old vers
|
||||
# keyUsage, extendedKeyUsage - https://www.openssl.org/docs/apps/x509v3_config.html
|
||||
# strongSwan key paths - https://wiki.strongswan.org/projects/1/wiki/SimpleCA
|
||||
|
||||
config = CertificateAuthorityConfig("/etc/ssl/openssl.cnf")
|
||||
config = CertificateAuthorityConfig()
|
||||
|
||||
# Parse command-line argument defaults from environment
|
||||
HOSTNAME = socket.gethostname()
|
||||
@ -77,6 +74,11 @@ def certidude_spawn(kill, no_interaction):
|
||||
"""
|
||||
Spawn processes for signers
|
||||
"""
|
||||
# Check whether we have privileges
|
||||
os.umask(0o027)
|
||||
uid = os.getuid()
|
||||
if uid != 0:
|
||||
raise click.ClickException("Not running as root")
|
||||
|
||||
# Process directories
|
||||
run_dir = "/run/certidude"
|
||||
@ -88,10 +90,6 @@ def certidude_spawn(kill, no_interaction):
|
||||
click.echo("Creating: %s" % signer_dir)
|
||||
os.makedirs(signer_dir)
|
||||
|
||||
os.umask(0o027)
|
||||
uid = os.getuid()
|
||||
assert uid == 0, "Not running as root"
|
||||
|
||||
# Preload charmap encoding for byte_string() function of pyOpenSSL
|
||||
# in order to enable chrooting
|
||||
"".encode("charmap")
|
||||
@ -103,6 +101,7 @@ def certidude_spawn(kill, no_interaction):
|
||||
# TODO: use os.mknod instead
|
||||
os.system("mknod -m 444 %s c 1 9" % os.path.join(chroot_dir, "dev", "urandom"))
|
||||
|
||||
ca_loaded = False
|
||||
for ca in config.all_authorities():
|
||||
socket_path = os.path.join(signer_dir, ca.slug + ".sock")
|
||||
pidfile_path = os.path.join(signer_dir, ca.slug + ".pid")
|
||||
@ -125,7 +124,9 @@ def certidude_spawn(kill, no_interaction):
|
||||
sleep(1)
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
ca_loaded = True
|
||||
else:
|
||||
ca_loaded = True
|
||||
continue
|
||||
|
||||
child_pid = os.fork()
|
||||
@ -144,6 +145,10 @@ def certidude_spawn(kill, no_interaction):
|
||||
asyncore.loop()
|
||||
else:
|
||||
click.echo("Spawned certidude signer process with PID %d at %s" % (child_pid, socket_path))
|
||||
ca_loaded = True
|
||||
|
||||
if not ca_loaded:
|
||||
raise click.ClickException("No CA sections defined in configuration: {}".format(config.path))
|
||||
|
||||
|
||||
@click.command("client", help="Setup X.509 certificates for application")
|
||||
@ -469,6 +474,12 @@ def certidude_setup_authority(parent, country, state, locality, organization, or
|
||||
_, _, uid, gid, gecos, root, shell = pwd.getpwnam(group)
|
||||
os.setgid(gid)
|
||||
|
||||
slug = os.path.basename(directory[:-1] if directory.endswith('/') else directory)
|
||||
if not slug:
|
||||
raise ValueError("Please supply proper target path")
|
||||
|
||||
click.echo("CA configuration files are saved to: {}".format(os.path.abspath(slug)))
|
||||
|
||||
click.echo("Generating 4096-bit RSA key...")
|
||||
|
||||
if pkcs11:
|
||||
@ -477,8 +488,6 @@ def certidude_setup_authority(parent, country, state, locality, organization, or
|
||||
key = crypto.PKey()
|
||||
key.generate_key(crypto.TYPE_RSA, 4096)
|
||||
|
||||
slug = os.path.basename(directory)
|
||||
|
||||
if not crl_distribution_url:
|
||||
crl_distribution_url = "http://%s/api/%s/revoked/" % (common_name, slug)
|
||||
|
||||
@ -575,9 +584,13 @@ def certidude_setup_authority(parent, country, state, locality, organization, or
|
||||
with open(ca_key, "wb") as fh:
|
||||
fh.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key))
|
||||
|
||||
click.echo("Insert following to /etc/ssl/openssl.cnf:")
|
||||
with open(os.path.join(directory, "openssl.cnf.example"), "w") as fh:
|
||||
fh.write(env.get_template("openssl.cnf").render(locals()))
|
||||
|
||||
click.echo("You need to copy the contents of the 'openssl.cnf.example'")
|
||||
click.echo("to system-wide OpenSSL configuration file, usually located")
|
||||
click.echo("at /etc/ssl/openssl.cnf")
|
||||
click.echo()
|
||||
click.secho(env.get_template("openssl.cnf").render(locals()), fg="blue")
|
||||
|
||||
click.echo()
|
||||
click.echo("Use following commands to inspect the newly created files:")
|
||||
|
@ -1,3 +1,6 @@
|
||||
# You have to copy the settings to the system-wide
|
||||
# OpenSSL configuration (usually /etc/ssl/openssl.cnf
|
||||
|
||||
[CA_{{slug}}]
|
||||
default_crl_days = {{revocation_list_lifetime}}
|
||||
default_days = {{certificate_lifetime}}
|
||||
@ -38,3 +41,4 @@ emailAddress = optional
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation,digitalSignature,keyEncipherment
|
||||
extendedKeyUsage = clientAuth
|
||||
|
||||
|
@ -61,13 +61,19 @@ def subject2dn(subject):
|
||||
|
||||
class CertificateAuthorityConfig(object):
|
||||
"""
|
||||
Attempt to parse CA-s from openssl.cnf
|
||||
Certificate Authority configuration
|
||||
|
||||
:param path: Absolute path to configuration file.
|
||||
Defaults to /etc/ssl/openssl.cnf
|
||||
"""
|
||||
|
||||
def __init__(self, *args):
|
||||
def __init__(self, path='/etc/ssl/openssl.cnf', *args):
|
||||
|
||||
#: Path to file where current configuration is loaded from.
|
||||
self.path = path
|
||||
|
||||
self._config = RawConfigParser()
|
||||
for arg in args:
|
||||
self._config.readfp(itertools.chain(["[global]"], open(os.path.expanduser(arg))))
|
||||
self._config.readfp(itertools.chain(["[global]"], open(self.path)))
|
||||
|
||||
def get(self, section, key, default=""):
|
||||
if self._config.has_option(section, key):
|
||||
|
@ -11,7 +11,7 @@ from certidude.api import CertificateAuthorityResource, \
|
||||
# TODO: deduplicate routing code
|
||||
# TODO: set up /run/certidude/api paths and permissions
|
||||
|
||||
config = CertificateAuthorityConfig("/etc/ssl/openssl.cnf")
|
||||
config = CertificateAuthorityConfig()
|
||||
|
||||
assert os.getenv("PUSH_SUBSCRIBE"), "Please set PUSH_SUBSCRIBE to your web server's subscription URL"
|
||||
assert os.getenv("PUSH_PUBLISH"), "Please set PUSH_PUBLISH to your web server's publishing URL"
|
||||
|
19
requirements.txt
Normal file
19
requirements.txt
Normal file
@ -0,0 +1,19 @@
|
||||
cffi==1.2.1
|
||||
click==5.1
|
||||
cryptography==1.0
|
||||
falcon==0.3.0
|
||||
humanize==0.5.1
|
||||
idna==2.0
|
||||
Jinja2==2.8
|
||||
ldap3==0.9.8.8
|
||||
MarkupSafe==0.23
|
||||
netifaces==0.10.4
|
||||
pyasn1==0.1.8
|
||||
pycountry==1.14
|
||||
pycparser==2.14
|
||||
pycrypto==2.6.1
|
||||
pykerberos==1.1.8
|
||||
pyOpenSSL==0.15.1
|
||||
python-mimeparse==0.1.4
|
||||
setproctitle==1.1.9
|
||||
six==1.9.0
|
Loading…
Reference in New Issue
Block a user