diff --git a/certidude/authority.py b/certidude/authority.py index f04ac0f..2740a77 100644 --- a/certidude/authority.py +++ b/certidude/authority.py @@ -312,7 +312,7 @@ def delete_request(common_name): config.LONG_POLL_PUBLISH % hashlib.sha256(buf).hexdigest(), headers={"User-Agent": "Certidude API"}) -def sign(common_name, skip_notify=False, skip_push=False, overwrite=False, profile=None, signer=None): +def sign(common_name, skip_notify=False, skip_push=False, overwrite=False, profile="default", signer=None): """ Sign certificate signing request by it's common name """ @@ -330,7 +330,7 @@ def sign(common_name, skip_notify=False, skip_push=False, overwrite=False, profi os.unlink(req_path) return cert, buf -def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, profile=None, signer=None): +def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, profile="default", signer=None): # TODO: CRLDistributionPoints, OCSP URL, Certificate URL if profile not in config.PROFILES: raise ValueError("Invalid profile supplied '%s'" % profile) diff --git a/certidude/cli.py b/certidude/cli.py index 18c6ce8..1949f18 100755 --- a/certidude/cli.py +++ b/certidude/cli.py @@ -195,6 +195,9 @@ def certidude_enroll(fork, renew, no_wait, kerberos, skip_self): finally: if os.path.exists(authority_path): click.echo("Found authority certificate in: %s" % authority_path) + with open(authority_path, "rb") as fh: + header, _, certificate_der_bytes = pem.unarmor(fh.read()) + authority_certificate = x509.Certificate.load(certificate_der_bytes) else: if not os.path.exists(os.path.dirname(authority_path)): os.makedirs(os.path.dirname(authority_path)) @@ -203,7 +206,7 @@ def certidude_enroll(fork, renew, no_wait, kerberos, skip_self): r = requests.get(authority_url, headers={"Accept": "application/x-x509-ca-cert,application/x-pem-file"}) header, _, certificate_der_bytes = pem.unarmor(r.content) - cert = x509.Certificate.load(certificate_der_bytes) + authority_certificate = x509.Certificate.load(certificate_der_bytes) except: # TODO: catch correct exceptions raise # raise ValueError("Failed to parse PEM: %s" % r.text) @@ -214,6 +217,10 @@ def certidude_enroll(fork, renew, no_wait, kerberos, skip_self): selinux_fixup(authority_partial) os.rename(authority_partial, authority_path) + authority_public_key = asymmetric.load_public_key( + authority_certificate["tbs_certificate"]["subject_public_key_info"]) + + # Attempt to install CA certificates system wide try: @@ -288,17 +295,14 @@ def certidude_enroll(fork, renew, no_wait, kerberos, skip_self): key_partial = key_path + ".part" request_partial = request_path + ".part" - certificate = x509.Certificate.load(certificate_der_bytes) - public_key = asymmetric.load_public_key(certificate["tbs_certificate"]["subject_public_key_info"]) - - if public_key.algorithm == "ec": - self_public_key, private_key = asymmetric.generate_pair("ec", curve=public_key.curve) - elif public_key.algorithm == "rsa": - self_public_key, private_key = asymmetric.generate_pair("rsa", bit_size=public_key.bit_size) + if authority_public_key.algorithm == "ec": + self_public_key, private_key = asymmetric.generate_pair("ec", curve=authority_public_key.curve) + elif authority_public_key.algorithm == "rsa": + self_public_key, private_key = asymmetric.generate_pair("rsa", bit_size=authority_public_key.bit_size) else: NotImplemented - builder = CSRBuilder({"common_name": common_name}, public_key) + builder = CSRBuilder({"common_name": common_name}, self_public_key) request = builder.build(private_key) with open(key_partial, 'wb') as f: f.write(asymmetric.dump_private_key(private_key, None)) @@ -343,7 +347,7 @@ def certidude_enroll(fork, renew, no_wait, kerberos, skip_self): asymmetric.rsa_pss_sign( asymmetric.load_private_key(kh.read()), cert_buf + rh.read(), - "sha512")) + "sha384")) except EnvironmentError: # Certificate missing, can't renew pass else: @@ -1326,7 +1330,7 @@ def certidude_list(verbose, show_key_type, show_extensions, show_path, show_sign @click.command("sign", help="Sign certificate") @click.argument("common_name") -@click.option("--profile", "-p", default=None, help="Profile") +@click.option("--profile", "-p", default="default", help="Profile") @click.option("--overwrite", "-o", default=False, is_flag=True, help="Revoke valid certificate with same CN") def certidude_sign(common_name, overwrite, profile): from certidude import authority diff --git a/certidude/static/views/authority.html b/certidude/static/views/authority.html index 057241c..7b7ca17 100644 --- a/certidude/static/views/authority.html +++ b/certidude/static/views/authority.html @@ -90,9 +90,12 @@ curl -f -L -H "Content-type: application/pkcs10" --data-binary @client_req.pem \

First enroll certificates:

-

-FQDN=$(cat /etc/hostname)
-curl -f http://{{ window.location.hostname }}/api/certificate/ -o /etc/ipsec.d/cacerts/ca.pem; \
+              
opkg update
+opkg install curl strongswan-full strongswan-mod-kernel-libipsec kmod-crypto-echainiv kmod-crypto-gcm
+FQDN=$(uci get system.@system[0].hostname)
+cat << EOF > /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem
+{{ session.authority.certificate.blob }}
+EOF
 test -e /etc/ipsec.d/private/client.pem \
  || openssl ecparam -name secp384r1 -genkey -noout -out /etc/ipsec.d/private/client.pem; \
 test -e /etc/ipsec.d/reqs/client.pem \
@@ -107,8 +110,7 @@ curl -f -L -H "Content-type: application/pkcs10" \
 
             

Then configure StrongSwan

-

-cat > /etc/ipsec.conf << EOF
+              
cat > /etc/ipsec.conf << EOF
 conn c2s
     auto=start
     right=router.k-space.ee
@@ -176,7 +178,10 @@ chmod +x /etc/certidude/authority/{{ window.location.hostname }}/updownThen either set up OpenVPN service:

-
# Generate Diffie-Hellman parameters file for OpenVPN
+              
opkg update
+opkg install curl openssl-util openvpn-openssl
+
+# Generate Diffie-Hellman parameters file for OpenVPN
 test -e /etc/certidude/dh.pem \
  || openssl dhparam 2048 -out /etc/certidude/dh.pem
 
@@ -265,7 +270,10 @@ done
 
             

Alternatively or additionally set up StrongSwan:

-
# Generate StrongSwan config
+              
opkg update
+opkg install curl openssl-util strongswan-full kmod-crypto-echainiv kmod-crypto-gcm
+
+# Generate StrongSwan config
 cat > /etc/ipsec.conf << EOF
 config setup
     strictcrlpolicy=yes
diff --git a/tests/test_cli.py b/tests/test_cli.py
index a6568f4..c6598f0 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -716,7 +716,7 @@ def test_cli_setup_authority():
 
     child_pid = os.fork()
     if not child_pid:
-        result = runner.invoke(cli, ["sign", "www.example.lan"])
+        result = runner.invoke(cli, ["sign", "www.example.lan", "--profile", "srv"])
         assert not result.exception, result.output
         assert "Publishing request-signed event 'www.example.lan' on http://localhost/ev/pub/" in result.output, result.output
         return
@@ -773,7 +773,7 @@ def test_cli_setup_authority():
     child_pid = os.fork()
     if not child_pid:
         assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/vpn.example.lan.pem")
-        result = runner.invoke(cli, ["sign", "vpn.example.lan"])
+        result = runner.invoke(cli, ["sign", "vpn.example.lan", "--profile", "srv"])
         assert not result.exception, result.output
         assert "overwrit" not in result.output, result.output
         assert "Publishing request-signed event 'vpn.example.lan' on http://localhost/ev/pub/" in result.output, result.output
@@ -996,7 +996,7 @@ def test_cli_setup_authority():
     child_pid = os.fork()
     if not child_pid:
         assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/ipsec.example.lan.pem")
-        result = runner.invoke(cli, ["sign", "ipsec.example.lan"])
+        result = runner.invoke(cli, ["sign", "ipsec.example.lan", "--profile", "srv"])
         assert not result.exception, result.output
         assert "overwrit" not in result.output, result.output
         assert "Publishing request-signed event 'ipsec.example.lan' on http://localhost/ev/pub/" in result.output, result.output