mirror of
				https://github.com/laurivosandi/certidude
				synced 2025-10-31 01:19:11 +00:00 
			
		
		
		
	Bugfixes, OU support and image builder fixes
This commit is contained in:
		| @@ -44,6 +44,7 @@ class SessionResource(object): | |||||||
|                 except IOError: |                 except IOError: | ||||||
|                     submission_hostname = None |                     submission_hostname = None | ||||||
|                 yield dict( |                 yield dict( | ||||||
|  |                     server = authority.server_flags(common_name), | ||||||
|                     submitted = submitted, |                     submitted = submitted, | ||||||
|                     common_name = common_name, |                     common_name = common_name, | ||||||
|                     address = submission_address, |                     address = submission_address, | ||||||
| @@ -103,6 +104,7 @@ class SessionResource(object): | |||||||
|  |  | ||||||
|                 yield dict( |                 yield dict( | ||||||
|                     serial = "%x" % cert.serial_number, |                     serial = "%x" % cert.serial_number, | ||||||
|  |                     organizational_unit = cert.subject.native.get("organizational_unit_name"), | ||||||
|                     common_name = common_name, |                     common_name = common_name, | ||||||
|                     # TODO: key type, key length, key exponent, key modulo |                     # TODO: key type, key length, key exponent, key modulo | ||||||
|                     signed = signed, |                     signed = signed, | ||||||
| @@ -158,10 +160,8 @@ class SessionResource(object): | |||||||
|                 request_subnets = config.REQUEST_SUBNETS or None, |                 request_subnets = config.REQUEST_SUBNETS or None, | ||||||
|                 admin_subnets=config.ADMIN_SUBNETS or None, |                 admin_subnets=config.ADMIN_SUBNETS or None, | ||||||
|                 signature = dict( |                 signature = dict( | ||||||
|                     server_certificate_lifetime=config.SERVER_CERTIFICATE_LIFETIME, |  | ||||||
|                     client_certificate_lifetime=config.CLIENT_CERTIFICATE_LIFETIME, |  | ||||||
|                     revocation_list_lifetime=config.REVOCATION_LIST_LIFETIME, |                     revocation_list_lifetime=config.REVOCATION_LIST_LIFETIME, | ||||||
|                     profiles = [dict(organizational_unit=ou, flags=f, lifetime=lt) for f, lt, ou in config.PROFILES.values()] |                     profiles = [dict(name=k, server=v[0]=="server", lifetime=v[1], organizational_unit=v[2], title=v[3]) for k,v in config.PROFILES.items()] | ||||||
|                 ) |                 ) | ||||||
|             ) if req.context.get("user").is_admin() else None, |             ) if req.context.get("user").is_admin() else None, | ||||||
|             features=dict( |             features=dict( | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ class ImageBuilderResource(object): | |||||||
|         suffix = config.cp2.get(profile, "filename") |         suffix = config.cp2.get(profile, "filename") | ||||||
|  |  | ||||||
|         build = "/var/lib/certidude/builder/" + profile |         build = "/var/lib/certidude/builder/" + profile | ||||||
|  |         log_path = build + "/build.log" | ||||||
|         if not os.path.exists(build + "/overlay/etc/uci-defaults"): |         if not os.path.exists(build + "/overlay/etc/uci-defaults"): | ||||||
|             os.makedirs(build + "/overlay/etc/uci-defaults") |             os.makedirs(build + "/overlay/etc/uci-defaults") | ||||||
|         os.system("rsync -av " + overlay_path + "/ " + build + "/overlay/") |         os.system("rsync -av " + overlay_path + "/ " + build + "/overlay/") | ||||||
| @@ -31,12 +32,16 @@ class ImageBuilderResource(object): | |||||||
|                 fh.write(template.render(authority_name=const.FQDN)) |                 fh.write(template.render(authority_name=const.FQDN)) | ||||||
|  |  | ||||||
|         proc = subprocess.Popen(("/bin/bash", build_script_path), |         proc = subprocess.Popen(("/bin/bash", build_script_path), | ||||||
|             stdout=open(build + "/build.log", "w"), stderr=subprocess.STDOUT, |             stdout=open(log_path, "w"), stderr=subprocess.STDOUT, | ||||||
|             close_fds=True, shell=False, |             close_fds=True, shell=False, | ||||||
|             cwd=build, |             cwd=os.path.dirname(os.path.realpath(build_script_path)), | ||||||
|             env={"PROFILE":model, "PATH":"/usr/sbin:/usr/bin:/sbin:/bin"}, |             env={"PROFILE":model, "PATH":"/usr/sbin:/usr/bin:/sbin:/bin", | ||||||
|  |                 "BUILD":build, "OVERLAY":build + "/overlay/"}, | ||||||
|             startupinfo=None, creationflags=0) |             startupinfo=None, creationflags=0) | ||||||
|         proc.communicate() |         proc.communicate() | ||||||
|  |         if proc.returncode: | ||||||
|  |             logger.info("Build script finished with non-zero exitcode, see %s for more information" % log_path) | ||||||
|  |             raise falcon.HTTPInternalServerError("Build script finished with non-zero exitcode") | ||||||
|  |  | ||||||
|         for dname in os.listdir(build): |         for dname in os.listdir(build): | ||||||
|             if dname.startswith("lede-imagebuilder-"): |             if dname.startswith("lede-imagebuilder-"): | ||||||
|   | |||||||
| @@ -33,6 +33,11 @@ class LeaseResource(object): | |||||||
|     @authorize_server |     @authorize_server | ||||||
|     def on_post(self, req, resp): |     def on_post(self, req, resp): | ||||||
|         client_common_name = req.get_param("client", required=True) |         client_common_name = req.get_param("client", required=True) | ||||||
|  |         if "=" in client_common_name: # It's actually DN, resolve it to CN | ||||||
|  |             _, client_common_name = client_common_name.split(" CN=", 1) | ||||||
|  |             if "," in client_common_name: | ||||||
|  |                 client_common_name, _ = client_common_name.split(",", 1) | ||||||
|  |  | ||||||
|         path, buf, cert, signed, expires = authority.get_signed(client_common_name) # TODO: catch exceptions |         path, buf, cert, signed, expires = authority.get_signed(client_common_name) # TODO: catch exceptions | ||||||
|         if req.get_param("serial") and cert.serial_number != req.get_param_as_int("serial"): # OCSP-ish solution for OpenVPN, not exposed for StrongSwan |         if req.get_param("serial") and cert.serial_number != req.get_param_as_int("serial"): # OCSP-ish solution for OpenVPN, not exposed for StrongSwan | ||||||
|             raise falcon.HTTPForbidden("Forbidden", "Invalid serial number supplied") |             raise falcon.HTTPForbidden("Forbidden", "Invalid serial number supplied") | ||||||
|   | |||||||
| @@ -225,7 +225,10 @@ class RequestDetailResource(object): | |||||||
|         Sign a certificate signing request |         Sign a certificate signing request | ||||||
|         """ |         """ | ||||||
|         try: |         try: | ||||||
|             cert, buf = authority.sign(cn, ou=req.get_param("ou"), overwrite=True, signer=req.context.get("user").name) |             cert, buf = authority.sign(cn, | ||||||
|  |                 profile=req.get_param("profile", default="default"), | ||||||
|  |                 overwrite=True, | ||||||
|  |                 signer=req.context.get("user").name) | ||||||
|             # Mailing and long poll publishing implemented in the function above |             # Mailing and long poll publishing implemented in the function above | ||||||
|         except EnvironmentError: # no such CSR |         except EnvironmentError: # no such CSR | ||||||
|             raise falcon.HTTPNotFound() |             raise falcon.HTTPNotFound() | ||||||
|   | |||||||
| @@ -38,6 +38,7 @@ class SignedCertificateDetailResource(object): | |||||||
|                 common_name = cn, |                 common_name = cn, | ||||||
|                 signer = signer_username, |                 signer = signer_username, | ||||||
|                 serial_number = "%x" % cert.serial_number, |                 serial_number = "%x" % cert.serial_number, | ||||||
|  |                 organizational_unit = cert.subject.native.get("organizational_unit_name"), | ||||||
|                 signed = cert["tbs_certificate"]["validity"]["not_before"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z", |                 signed = cert["tbs_certificate"]["validity"]["not_before"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z", | ||||||
|                 expires = cert["tbs_certificate"]["validity"]["not_after"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z", |                 expires = cert["tbs_certificate"]["validity"]["not_after"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z", | ||||||
|                 sha256sum = hashlib.sha256(buf).hexdigest())) |                 sha256sum = hashlib.sha256(buf).hexdigest())) | ||||||
|   | |||||||
| @@ -55,7 +55,7 @@ def self_enroll(): | |||||||
|             fh.write(asymmetric.dump_private_key(private_key, None)) |             fh.write(asymmetric.dump_private_key(private_key, None)) | ||||||
|     else: |     else: | ||||||
|         now = datetime.utcnow() |         now = datetime.utcnow() | ||||||
|         if now - timedelta(days=1) < expires: |         if now + timedelta(days=1) < expires: | ||||||
|             click.echo("Certificate %s still valid, delete to self-enroll again" % path) |             click.echo("Certificate %s still valid, delete to self-enroll again" % path) | ||||||
|             return |             return | ||||||
|  |  | ||||||
| @@ -307,7 +307,7 @@ def delete_request(common_name): | |||||||
|         config.LONG_POLL_PUBLISH % hashlib.sha256(buf).hexdigest(), |         config.LONG_POLL_PUBLISH % hashlib.sha256(buf).hexdigest(), | ||||||
|         headers={"User-Agent": "Certidude API"}) |         headers={"User-Agent": "Certidude API"}) | ||||||
|  |  | ||||||
| def sign(common_name, skip_notify=False, skip_push=False, overwrite=False, ou=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 |     Sign certificate signing request by it's common name | ||||||
|     """ |     """ | ||||||
| @@ -320,13 +320,15 @@ def sign(common_name, skip_notify=False, skip_push=False, overwrite=False, ou=No | |||||||
|  |  | ||||||
|  |  | ||||||
|     # Sign with function below |     # Sign with function below | ||||||
|     cert, buf = _sign(csr, csr_buf, skip_notify, skip_push, overwrite, ou, signer) |     cert, buf = _sign(csr, csr_buf, skip_notify, skip_push, overwrite, profile, signer) | ||||||
|  |  | ||||||
|     os.unlink(req_path) |     os.unlink(req_path) | ||||||
|     return cert, buf |     return cert, buf | ||||||
|  |  | ||||||
| def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, ou=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 |     # TODO: CRLDistributionPoints, OCSP URL, Certificate URL | ||||||
|  |     if profile not in config.PROFILES: | ||||||
|  |         raise ValueError("Invalid profile supplied '%s'" % profile) | ||||||
|  |  | ||||||
|     assert buf.startswith(b"-----BEGIN CERTIFICATE REQUEST-----") |     assert buf.startswith(b"-----BEGIN CERTIFICATE REQUEST-----") | ||||||
|     assert isinstance(csr, CertificationRequest) |     assert isinstance(csr, CertificationRequest) | ||||||
| @@ -367,8 +369,9 @@ def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, ou=None | |||||||
|  |  | ||||||
|     # Sign via signer process |     # Sign via signer process | ||||||
|     dn = {u'common_name': common_name } |     dn = {u'common_name': common_name } | ||||||
|     if ou: |     profile_server_flags, lifetime, dn["organizational_unit_name"], _ = config.PROFILES[profile] | ||||||
|         dn["organizational_unit"] = ou |     lifetime = int(lifetime) | ||||||
|  |  | ||||||
|     builder = CertificateBuilder(dn, csr_pubkey) |     builder = CertificateBuilder(dn, csr_pubkey) | ||||||
|     builder.serial_number = random.randint( |     builder.serial_number = random.randint( | ||||||
|         0x1000000000000000000000000000000000000000, |         0x1000000000000000000000000000000000000000, | ||||||
| @@ -376,16 +379,14 @@ def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, ou=None | |||||||
|  |  | ||||||
|     now = datetime.utcnow() |     now = datetime.utcnow() | ||||||
|     builder.begin_date = now - timedelta(minutes=5) |     builder.begin_date = now - timedelta(minutes=5) | ||||||
|     builder.end_date = now + timedelta(days=config.SERVER_CERTIFICATE_LIFETIME |     builder.end_date = now + timedelta(days=lifetime) | ||||||
|         if server_flags(common_name) |  | ||||||
|         else config.CLIENT_CERTIFICATE_LIFETIME) |  | ||||||
|     builder.issuer = certificate |     builder.issuer = certificate | ||||||
|     builder.ca = False |     builder.ca = False | ||||||
|     builder.key_usage = set(["digital_signature", "key_encipherment"]) |     builder.key_usage = set(["digital_signature", "key_encipherment"]) | ||||||
|  |  | ||||||
|     # OpenVPN uses CN while StrongSwan uses SAN |     # If we have FQDN and profile suggests server flags, enable them | ||||||
|     if server_flags(common_name): |     if server_flags(common_name) and profile_server_flags: | ||||||
|         builder.subject_alt_domains = [common_name] |         builder.subject_alt_domains = [common_name] # OpenVPN uses CN while StrongSwan uses SAN to match hostname of the server | ||||||
|         builder.extended_key_usage = set(["server_auth", "1.3.6.1.5.5.8.2.2", "client_auth"]) |         builder.extended_key_usage = set(["server_auth", "1.3.6.1.5.5.8.2.2", "client_auth"]) | ||||||
|     else: |     else: | ||||||
|         builder.extended_key_usage = set(["client_auth"]) |         builder.extended_key_usage = set(["client_auth"]) | ||||||
|   | |||||||
| @@ -1312,7 +1312,7 @@ def certidude_list(verbose, show_key_type, show_extensions, show_path, show_sign | |||||||
| def certidude_sign(common_name, overwrite): | def certidude_sign(common_name, overwrite): | ||||||
|     from certidude import authority |     from certidude import authority | ||||||
|     drop_privileges() |     drop_privileges() | ||||||
|     cert = authority.sign(common_name, overwrite) |     cert = authority.sign(common_name, overwrite=overwrite) | ||||||
|  |  | ||||||
|  |  | ||||||
| @click.command("revoke", help="Revoke certificate") | @click.command("revoke", help="Revoke certificate") | ||||||
|   | |||||||
| @@ -60,8 +60,6 @@ USER_MULTIPLE_CERTIFICATES = { | |||||||
|     cp.get("authority", "user enrollment")] |     cp.get("authority", "user enrollment")] | ||||||
|  |  | ||||||
| REQUEST_SUBMISSION_ALLOWED = cp.getboolean("authority", "request submission allowed") | REQUEST_SUBMISSION_ALLOWED = cp.getboolean("authority", "request submission allowed") | ||||||
| CLIENT_CERTIFICATE_LIFETIME = cp.getint("signature", "client certificate lifetime") |  | ||||||
| SERVER_CERTIFICATE_LIFETIME = cp.getint("signature", "server certificate lifetime") |  | ||||||
| AUTHORITY_CERTIFICATE_URL = cp.get("signature", "authority certificate url") | AUTHORITY_CERTIFICATE_URL = cp.get("signature", "authority certificate url") | ||||||
| AUTHORITY_CRL_URL = cp.get("signature", "revoked url") | AUTHORITY_CRL_URL = cp.get("signature", "revoked url") | ||||||
| AUTHORITY_OCSP_URL = cp.get("signature", "responder url") | AUTHORITY_OCSP_URL = cp.get("signature", "responder url") | ||||||
|   | |||||||
| @@ -118,7 +118,7 @@ function onRequestSubmitted(e) { | |||||||
|             console.info("Going to prepend:", request); |             console.info("Going to prepend:", request); | ||||||
|             onRequestDeleted(e); // Delete any existing ones just in case |             onRequestDeleted(e); // Delete any existing ones just in case | ||||||
|             $("#pending_requests").prepend( |             $("#pending_requests").prepend( | ||||||
|                 env.render('views/request.html', { request: request })); |                 env.render('views/request.html', { request: request, session: session })); | ||||||
|             $("#pending_requests time").timeago(); |             $("#pending_requests time").timeago(); | ||||||
|         }, |         }, | ||||||
|         error: function(response) { |         error: function(response) { | ||||||
|   | |||||||
| @@ -28,23 +28,105 @@ curl -f -L -H "Content-type: application/pkcs10" --data-binary @client_req.pem \ | |||||||
|   http://{{ window.location.hostname }}/api/request/?wait=yes > client_cert.pem</code></pre> |   http://{{ window.location.hostname }}/api/request/?wait=yes > client_cert.pem</code></pre> | ||||||
|             </div> |             </div> | ||||||
|  |  | ||||||
|             <h5>Vanilla OpenWrt/LEDE</h5> |             <h5>OpenVPN gateway on OpenWrt/LEDE router</h5> | ||||||
|  |  | ||||||
|             <p>On OpenWrt/LEDE router to convert it into VPN gateway:</p> |             <p>First enroll certificates:</p> | ||||||
|             <div class="highlight"> |             <div class="highlight"> | ||||||
|               <pre class="code"><code>mkdir -p /var/lib/certidude/{{ window.location.hostname }}; \ |               <pre class="code"><code># Derive FQDN from WAN interface's reverse DNS record | ||||||
| grep -c certidude /etc/sysupgrade.conf || echo /var/lib/certidude >> /etc/sysupgrade.conf; \ | FQDN=$(nslookup $(uci get network.wan.ipaddr) |  grep "name =" | head -n1 | cut -d "=" -f 2 | xargs) | ||||||
| curl -f http://{{ window.location.hostname }}/api/certificate/ -o /var/lib/certidude/{{ window.location.hostname }}/ca_cert.pem; \ |  | ||||||
| test -e /var/lib/certidude/{{ window.location.hostname }}/client_key.pem || openssl genrsa -out /var/lib/certidude/{{ window.location.hostname }}/client_key.pem 2048; \ | mkdir -p /etc/certidude/authority/{{ window.location.hostname }}; \ | ||||||
| test -e /var/lib/certidude/{{ window.location.hostname }}/client_req.pem || read -p "Enter FQDN: " NAME; openssl req -new -sha256 \ | grep -c certidude /etc/sysupgrade.conf || echo /etc/certidude >> /etc/sysupgrade.conf; \ | ||||||
|   -key /var/lib/certidude/{{ window.location.hostname }}/client_key.pem \ | curl -f http://{{ window.location.hostname }}/api/certificate/ -o /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem; \ | ||||||
|   -out /var/lib/certidude/{{ window.location.hostname }}/client_req.pem -subj "/CN=$NAME"; \ | test -e /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem \ | ||||||
|  |  || openssl genrsa -out /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem 2048; \ | ||||||
|  | test -e /etc/certidude/authority/{{ window.location.hostname }}/server_req.pem \ | ||||||
|  |  || openssl req -new -sha256 \ | ||||||
|  |       -key /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem \ | ||||||
|  |       -out /etc/certidude/authority/{{ window.location.hostname }}/server_req.pem -subj "/CN=$FQDN"; \ | ||||||
| curl -f -L -H "Content-type: application/pkcs10" \ | curl -f -L -H "Content-type: application/pkcs10" \ | ||||||
|   --data-binary @/var/lib/certidude/{{ window.location.hostname }}/client_req.pem \ |   --data-binary @/etc/certidude/authority/{{ window.location.hostname }}/server_req.pem \ | ||||||
|   -o /var/lib/certidude/{{ window.location.hostname }}/client_cert.pem \ |   -o /etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem \ | ||||||
|   http://{{ window.location.hostname }}/api/request/?wait=yes</code></pre> |   http://{{ window.location.hostname }}/api/request/?wait=yes</code></pre> | ||||||
|             </div> |             </div> | ||||||
|  |  | ||||||
|  |             <p>Then set up service:</p> | ||||||
|  |             <div class="highlight"> | ||||||
|  |               <pre class="code"><code># Create VPN gateway up/down script for reporting client IP addresses to CA | ||||||
|  | cat <<\EOF > /etc/certidude/updown | ||||||
|  | #!/bin/sh | ||||||
|  | CURL="curl -f --key /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem --cert /etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem --cacert /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem https://{{ window.location.hostname }}:8443/api/lease/" | ||||||
|  |  | ||||||
|  | case $PLUTO_VERB in | ||||||
|  |   up-client|down-client) $CURL --data "outer_address=$PLUTO_PEER&inner_address=$PLUTO_PEER_SOURCEIP&client=$PLUTO_PEER_ID" ;; | ||||||
|  |   *) $CURL --data "client=$X509_0_CN&outer_address=$untrusted_ip&inner_address=$ifconfig_pool_remote_ip&serial=$tls_serial_0" ;; | ||||||
|  | esac | ||||||
|  | EOF | ||||||
|  |  | ||||||
|  | chmod +x /etc/certidude/updown | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Generate Diffie-Hellman parameters file for OpenVPN | ||||||
|  | test -e /etc/certidude/dh.pem \ | ||||||
|  |  || openssl dhparam 2048 -out /etc/certidude/dh.pem | ||||||
|  |  | ||||||
|  | # Create interface definition for tunnel | ||||||
|  | uci set network.vpn=interface | ||||||
|  | uci set network.vpn.name='vpn' | ||||||
|  | uci set network.vpn.ifname=tun_s2c | ||||||
|  | uci set network.vpn.proto='none' | ||||||
|  |  | ||||||
|  | # Create zone definition for VPN interface | ||||||
|  | uci set firewall.vpn=zone | ||||||
|  | uci set firewall.vpn.name='vpn' | ||||||
|  | uci set firewall.vpn.input='ACCEPT' | ||||||
|  | uci set firewall.vpn.forward='ACCEPT' | ||||||
|  | uci set firewall.vpn.output='ACCEPT' | ||||||
|  | uci set firewall.vpn.network='vpn' | ||||||
|  |  | ||||||
|  | # Allow UDP 1194 on WAN interface | ||||||
|  | uci set firewall.openvpn=rule | ||||||
|  | uci set firewall.openvpn.name='Allow OpenVPN' | ||||||
|  | uci set firewall.openvpn.src='wan' | ||||||
|  | uci set firewall.openvpn.dest_port=1194 | ||||||
|  | uci set firewall.openvpn.proto='udp' | ||||||
|  | uci set firewall.openvpn.target='ACCEPT' | ||||||
|  |  | ||||||
|  | # Forward traffic from VPN to LAN | ||||||
|  | uci set firewall.c2s=forwarding | ||||||
|  | uci set firewall.c2s.src='vpn' | ||||||
|  | uci set firewall.c2s.dest='lan' | ||||||
|  |  | ||||||
|  | # Permit DNS queries from VPN | ||||||
|  | uci set dhcp.@dnsmasq[0].localservice='0' | ||||||
|  |  | ||||||
|  | touch /etc/config/openvpn | ||||||
|  | uci set openvpn.s2c=openvpn | ||||||
|  | uci set openvpn.s2c.local=$(uci get network.wan.ipaddr) | ||||||
|  | uci set openvpn.s2c.script_security=2 | ||||||
|  | uci set openvpn.s2c.client_connect='/etc/certidude/updown' | ||||||
|  | uci set openvpn.s2c.tls_version_min='1.2' | ||||||
|  | uci set openvpn.s2c.tls_cipher='TLS-DHE-RSA-WITH-AES-256-GCM-SHA384' | ||||||
|  | uci set openvpn.s2c.cipher='AES-256-CBC' | ||||||
|  | uci set openvpn.s2c.auth='SHA384' | ||||||
|  | uci set openvpn.s2c.dev=tun_s2c | ||||||
|  | uci set openvpn.s2c.server='10.179.43.0 255.255.255.0' | ||||||
|  | uci set openvpn.s2c.key='/etc/certidude/authority/{{ window.location.hostname }}/server_key.pem' | ||||||
|  | uci set openvpn.s2c.cert='/etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem' | ||||||
|  | uci set openvpn.s2c.ca='/etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem' | ||||||
|  | uci set openvpn.s2c.dh='/etc/certidude/dh.pem' | ||||||
|  | uci set openvpn.s2c.enabled=1 | ||||||
|  | uci set openvpn.s2c.comp_lzo=yes | ||||||
|  | uci add_list openvpn.s2c.push="route-metric 1000" | ||||||
|  | uci add_list openvpn.s2c.push="route $(uci get network.lan.ipaddr) $(uci get network.lan.netmask)" | ||||||
|  | uci add_list openvpn.s2c.push="dhcp-option DNS $(uci get network.lan.ipaddr)" | ||||||
|  | uci add_list openvpn.s2c.push="dhcp-option DOMAIN $(uci get dhcp.@dnsmasq[0].domain)" | ||||||
|  |  | ||||||
|  | /etc/init.d/openvpn restart | ||||||
|  | /etc/init.d/firewall restart</code></pre> | ||||||
|  |             </div> | ||||||
|  |  | ||||||
|  |  | ||||||
|             {% if session.authority.builder %} |             {% if session.authority.builder %} | ||||||
|             <h5>OpenWrt/LEDE image builder</h5> |             <h5>OpenWrt/LEDE image builder</h5> | ||||||
|             <p>Hit a link to generate machine specific image. Note that this might take couple minutes to finish.</p> |             <p>Hit a link to generate machine specific image. Note that this might take couple minutes to finish.</p> | ||||||
|   | |||||||
| @@ -30,10 +30,11 @@ | |||||||
|       </button> |       </button> | ||||||
|       <div class="dropdown-menu"> |       <div class="dropdown-menu"> | ||||||
|         {% for p in session.authority.signature.profiles %} |         {% for p in session.authority.signature.profiles %} | ||||||
|           <a class="dropdown-item" href="/api/request/?organizational_unit={{ p.organizational_unit }}&lifetime={{ p.lifetime }}&flags={{ p.flags }}"> |           <a class="dropdown-item{% if p.server and not request.server %} disabled{% endif %}" | ||||||
|             {% if p.organizational_unit %} |             {% if p.server and not request.server %}title="Resubmit with FQDN as common name"{% endif %} | ||||||
|             {{ p.organizational_unit }} ({{ p.flags }}){% else %} |             href="#" onclick="javascript:$.ajax({url:'/api/request/{{request.common_name}}/?sha256sum={{ request.sha256sum }}&profile={{ p.name }}',type:'post'});"> | ||||||
|             {{ p.flags | capitalize }}{% endif %}, expires in {{ p.lifetime }} days</a> |             {% if p.title %}{{ p.title }} ({% if p.server %}server{% else %}client{% endif %}){% else %} | ||||||
|  |             {% if p.server %}Server{% else %}Client{% endif %}{% endif %}, expires in {{ p.lifetime }} days</a> | ||||||
|         {% endfor %} |         {% endfor %} | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   | |||||||
| @@ -1,6 +1,10 @@ | |||||||
| <p> | <p> | ||||||
| <div id="certificate-{{ certificate.common_name | replace('@', '--') | replace('.', '-') }}" class="card"> | <div id="certificate-{{ certificate.common_name | replace('@', '--') | replace('.', '-') }}" class="card"> | ||||||
|   <div class="card-header"> |   <div class="card-header"> | ||||||
|  |     {% if certificate.organizational_unit %} | ||||||
|  |       <i class="fa fa-folder" aria-hidden="true"></i> | ||||||
|  |     {{ certificate.organizational_unit }} / | ||||||
|  |     {% endif %} | ||||||
|     {% if certificate.server %} |     {% if certificate.server %} | ||||||
|       <i class="fa fa-server"></i> |       <i class="fa fa-server"></i> | ||||||
|     {% else %} |     {% else %} | ||||||
| @@ -17,12 +21,9 @@ | |||||||
|       </span> |       </span> | ||||||
|  |  | ||||||
|       Signed |       Signed | ||||||
|       <time class="timeago" datetime="{{ certificate.signed }}">Certificate was signed {{ certificate.signed }}</time>, |       <time class="timeago" datetime="{{ certificate.signed }}">Certificate was signed {{ certificate.signed }}</time>{% if certificate.signer %} by {{ certificate.signer }}{% endif %}, | ||||||
|       expires |       expires | ||||||
|       <time class="timeago" datetime="{{ certificate.expires }}">Certificate expires {{ certificate.expires }}</time>. |       <time class="timeago" datetime="{{ certificate.expires }}">Certificate expires {{ certificate.expires }}</time>. | ||||||
|       {% if certificate.organizational_unit %} |  | ||||||
|         Part of {{ certificate.organizational_unit }} organizational unit. |  | ||||||
|       {% endif %} |  | ||||||
|     </p> |     </p> | ||||||
|     <p> |     <p> | ||||||
|     {% if session.authority.tagging %} |     {% if session.authority.tagging %} | ||||||
| @@ -91,10 +92,10 @@ curl --cert client_cert.pem https://{{ window.location.hostname }}:8443/api/sign | |||||||
|       <div style="overflow: auto; max-width: 100%;"> |       <div style="overflow: auto; max-width: 100%;"> | ||||||
|         <table class="table" id="signed_certificates"> |         <table class="table" id="signed_certificates"> | ||||||
|           <tbody> |           <tbody> | ||||||
|             <tr><th>Common name</th><td>{{ certificate.common_name }}</td></tr> |             <tr><th>Common name</th><td>{{ certificate.common_name }}</td></tr> | ||||||
|             <tr><th>Organizational unit</th><td>{% if certificate.organizational_unit %}{{ certificate.organizational_unit }}{% else %}-{% endif %}</td></tr> |             <tr><th>Organizational unit</th><td>{% if certificate.organizational_unit %}{{ certificate.organizational_unit }}{% else %}-{% endif %}</td></tr> | ||||||
|             <tr><th>Serial number</th><td style="word-wrap:break-word;">{{ certificate.serial | serial }}</td></tr> |             <tr><th>Serial number</th><td style="word-wrap:break-word;">{{ certificate.serial | serial }}</td></tr> | ||||||
|             <tr><th>Signed</th><td>{{ certificate.signed | datetime  }}{% if certificate.signer %}, by {{ certificate.signer }}{% endif %}</td></tr> |             <tr><th>Signed</th><td>{{ certificate.signed | datetime  }}{% if certificate.signer %} by {{ certificate.signer }}{% endif %}</td></tr> | ||||||
|             <tr><th>Expires</th><td>{{ certificate.expires | datetime  }}</td></tr> |             <tr><th>Expires</th><td>{{ certificate.expires | datetime  }}</td></tr> | ||||||
|             {% if certificate.lease %} |             {% if certificate.lease %} | ||||||
|             <tr><th>Lease</th><td><a href="http://{{ certificate.lease.inner_address }}">{{ certificate.lease.inner_address }}</a> at {{ certificate.lease.last_seen | datetime  }} |             <tr><th>Lease</th><td><a href="http://{{ certificate.lease.inner_address }}">{{ certificate.lease.inner_address }}</a> at {{ certificate.lease.last_seen | datetime  }} | ||||||
|   | |||||||
| @@ -191,13 +191,13 @@ lifetime = 30 | |||||||
| # Secret for generating and validating tokens, regenerate occasionally | # Secret for generating and validating tokens, regenerate occasionally | ||||||
| secret = {{ token_secret }} | secret = {{ token_secret }} | ||||||
|  |  | ||||||
|  |  | ||||||
| [profile] | [profile] | ||||||
| # title, flags, lifetime, organizational unit | # name, flags, lifetime, organizational unit, title | ||||||
| default = client, 120, | default = client, 120, Roadwarrior, Roadwarrior | ||||||
| srv = server, 365, Server | gw = server, 30, Gateway, Gateway | ||||||
| gw = server, 3, Gateway | srv = server, 365, Server, | ||||||
| ap = client, 1825, Access Point | ap = client, 1825, Access Point, Access Point | ||||||
|  | mfp = client, 30, MFP, Printers | ||||||
|  |  | ||||||
| [script] | [script] | ||||||
| # Path to the folder with scripts that can be served to the clients, set none to disable scripting | # Path to the folder with scripts that can be served to the clients, set none to disable scripting | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user