mirror of
https://github.com/laurivosandi/certidude
synced 2024-12-23 00:25:18 +00:00
Add OpenVPN bundle generation
This commit is contained in:
parent
cca9d2ab2d
commit
1925207a6d
@ -12,6 +12,8 @@ KEYWORDS = (
|
|||||||
(u"iPhone", u"iphone"),
|
(u"iPhone", u"iphone"),
|
||||||
(u"iPad", u"ipad"),
|
(u"iPad", u"ipad"),
|
||||||
(u"Ubuntu", u"ubuntu"),
|
(u"Ubuntu", u"ubuntu"),
|
||||||
|
(u"Fedora", u"fedora"),
|
||||||
|
(u"Linux", u"linux"),
|
||||||
)
|
)
|
||||||
|
|
||||||
class BundleResource(object):
|
class BundleResource(object):
|
||||||
@ -29,8 +31,15 @@ class BundleResource(object):
|
|||||||
hashlib.sha256(req.user_agent).hexdigest()[:8])
|
hashlib.sha256(req.user_agent).hexdigest()[:8])
|
||||||
|
|
||||||
logger.info(u"Signing bundle %s for %s", common_name, req.context.get("user"))
|
logger.info(u"Signing bundle %s for %s", common_name, req.context.get("user"))
|
||||||
resp.set_header("Content-Type", "application/x-pkcs12")
|
if config.BUNDLE_FORMAT == "p12":
|
||||||
resp.set_header("Content-Disposition", "attachment; filename=%s.p12" % common_name.encode("ascii"))
|
resp.set_header("Content-Type", "application/x-pkcs12")
|
||||||
resp.body, cert = authority.generate_pkcs12_bundle(common_name,
|
resp.set_header("Content-Disposition", "attachment; filename=%s.p12" % common_name.encode("ascii"))
|
||||||
owner=req.context.get("user"))
|
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)
|
||||||
|
@ -14,6 +14,7 @@ from cryptography.hazmat.primitives import hashes, serialization
|
|||||||
from certidude import config, push, mailer, const
|
from certidude import config, push, mailer, const
|
||||||
from certidude.wrappers import Certificate, Request
|
from certidude.wrappers import Certificate, Request
|
||||||
from certidude import errors
|
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]))?$"
|
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/
|
# https://jamielinux.com/docs/openssl-certificate-authority/
|
||||||
# http://pycopia.googlecode.com/svn/trunk/net/pycopia/ssl/certs.py
|
# http://pycopia.googlecode.com/svn/trunk/net/pycopia/ssl/certs.py
|
||||||
|
|
||||||
|
|
||||||
# Cache CA certificate
|
# Cache CA certificate
|
||||||
certificate = Certificate(open(config.AUTHORITY_CERTIFICATE_PATH))
|
certificate = Certificate(open(config.AUTHORITY_CERTIFICATE_PATH))
|
||||||
|
|
||||||
@ -185,6 +185,39 @@ def delete_request(common_name):
|
|||||||
requests.delete(config.PUSH_PUBLISH % request.fingerprint(),
|
requests.delete(config.PUSH_PUBLISH % request.fingerprint(),
|
||||||
headers={"User-Agent": "Certidude API"})
|
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):
|
def generate_pkcs12_bundle(common_name, key_size=4096, owner=None):
|
||||||
"""
|
"""
|
||||||
|
@ -40,6 +40,9 @@ SIGNED_DIR = cp.get("authority", "signed dir")
|
|||||||
REVOKED_DIR = cp.get("authority", "revoked dir")
|
REVOKED_DIR = cp.get("authority", "revoked dir")
|
||||||
OUTBOX = cp.get("authority", "outbox")
|
OUTBOX = cp.get("authority", "outbox")
|
||||||
|
|
||||||
|
BUNDLE_FORMAT = cp.get("authority", "bundle format")
|
||||||
|
OPENVPN_BUNDLE_TEMPLATE = cp.get("authority", "openvpn bundle template")
|
||||||
|
|
||||||
USER_CERTIFICATE_ENROLLMENT = {
|
USER_CERTIFICATE_ENROLLMENT = {
|
||||||
"forbidden": False, "single allowed": True, "multiple allowed": True }[
|
"forbidden": False, "single allowed": True, "multiple allowed": True }[
|
||||||
cp.get("authority", "user certificate enrollment")]
|
cp.get("authority", "user certificate enrollment")]
|
||||||
|
@ -95,3 +95,8 @@ revoked dir = {{ directory }}/revoked/
|
|||||||
expired dir = {{ directory }}/expired/
|
expired dir = {{ directory }}/expired/
|
||||||
outbox = {{ outbox }}
|
outbox = {{ outbox }}
|
||||||
|
|
||||||
|
bundle format = p12
|
||||||
|
;bundle format = ovpn
|
||||||
|
|
||||||
|
openvpn bundle template = /etc/certidude/template.ovpn
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user