Add OpenVPN bundle generation

This commit is contained in:
Lauri Võsandi 2017-01-25 11:34:08 +00:00
parent cca9d2ab2d
commit 1925207a6d
4 changed files with 56 additions and 6 deletions

View File

@ -12,6 +12,8 @@ KEYWORDS = (
(u"iPhone", u"iphone"),
(u"iPad", u"ipad"),
(u"Ubuntu", u"ubuntu"),
(u"Fedora", u"fedora"),
(u"Linux", u"linux"),
)
class BundleResource(object):
@ -29,8 +31,15 @@ class BundleResource(object):
hashlib.sha256(req.user_agent).hexdigest()[:8])
logger.info(u"Signing bundle %s for %s", common_name, req.context.get("user"))
resp.set_header("Content-Type", "application/x-pkcs12")
resp.set_header("Content-Disposition", "attachment; filename=%s.p12" % common_name.encode("ascii"))
resp.body, cert = authority.generate_pkcs12_bundle(common_name,
owner=req.context.get("user"))
if config.BUNDLE_FORMAT == "p12":
resp.set_header("Content-Type", "application/x-pkcs12")
resp.set_header("Content-Disposition", "attachment; filename=%s.p12" % common_name.encode("ascii"))
resp.body, cert = authority.generate_pkcs12_bundle(common_name,
owner=req.context.get("user"))
elif config.BUNDLE_FORMAT == "ovpn":
resp.set_header("Content-Type", "application/x-openvpn")
resp.set_header("Content-Disposition", "attachment; filename=%s.ovpn" % common_name.encode("ascii"))
resp.body, cert = authority.generate_ovpn_bundle(common_name,
owner=req.context.get("user"))
else:
raise ValueError("Unknown bundle format %s" % config.BUNDLE_FORMAT)

View File

@ -14,6 +14,7 @@ from cryptography.hazmat.primitives import hashes, serialization
from certidude import config, push, mailer, const
from certidude.wrappers import Certificate, Request
from certidude import errors
from jinja2 import Template
RE_HOSTNAME = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])(@(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]))?$"
@ -21,7 +22,6 @@ RE_HOSTNAME = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z
# https://jamielinux.com/docs/openssl-certificate-authority/
# http://pycopia.googlecode.com/svn/trunk/net/pycopia/ssl/certs.py
# Cache CA certificate
certificate = Certificate(open(config.AUTHORITY_CERTIFICATE_PATH))
@ -185,6 +185,39 @@ def delete_request(common_name):
requests.delete(config.PUSH_PUBLISH % request.fingerprint(),
headers={"User-Agent": "Certidude API"})
def generate_ovpn_bundle(common_name, owner=None):
# Construct private key
click.echo("Generating 4096-bit RSA key...")
key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096,
backend=default_backend()
)
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
x509.NameAttribute(k, v) for k, v in (
(NameOID.COMMON_NAME, common_name),
(NameOID.GIVEN_NAME, owner and owner.given_name),
(NameOID.SURNAME, owner and owner.surname),
) if v
]))
# Sign CSR
cert = sign(Request(
csr.sign(key, hashes.SHA512(), default_backend()).public_bytes(serialization.Encoding.PEM)), overwrite=True)
bundle = Template(open(config.OPENVPN_BUNDLE_TEMPLATE).read()).render(
ca = certificate.dump(),
key = key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
),
cert = cert.dump(),
crl=export_crl(),
)
return bundle, cert
def generate_pkcs12_bundle(common_name, key_size=4096, owner=None):
"""

View File

@ -40,6 +40,9 @@ SIGNED_DIR = cp.get("authority", "signed dir")
REVOKED_DIR = cp.get("authority", "revoked dir")
OUTBOX = cp.get("authority", "outbox")
BUNDLE_FORMAT = cp.get("authority", "bundle format")
OPENVPN_BUNDLE_TEMPLATE = cp.get("authority", "openvpn bundle template")
USER_CERTIFICATE_ENROLLMENT = {
"forbidden": False, "single allowed": True, "multiple allowed": True }[
cp.get("authority", "user certificate enrollment")]

View File

@ -95,3 +95,8 @@ revoked dir = {{ directory }}/revoked/
expired dir = {{ directory }}/expired/
outbox = {{ outbox }}
bundle format = p12
;bundle format = ovpn
openvpn bundle template = /etc/certidude/template.ovpn