From 2b86a5c2c74432d34e642a7fcbf8624914be0414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauri=20V=C3=B5sandi?= Date: Tue, 29 May 2018 09:06:07 +0000 Subject: [PATCH] Grand unified snippets --- README.rst | 27 ++- certidude/api/ocsp.py | 3 + certidude/authority.py | 1 + certidude/builder/common.sh | 2 +- .../builder/overlay/usr/bin/certidude-enroll | 2 +- .../overlay/usr/bin/certidude-enroll-renew | 2 +- certidude/cli.py | 213 +++++++++++------- certidude/static/js/certidude.js | 10 +- certidude/templates/script/default.sh | 2 +- certidude/templates/server/backend.service | 17 ++ certidude/templates/server/ldap-kinit.service | 7 + certidude/templates/server/ldap-kinit.timer | 3 + certidude/templates/server/nginx.conf | 8 +- certidude/templates/server/server.conf | 2 +- .../snippets/ansible-site.yml | 0 .../snippets/certidude-client.sh | 0 .../snippets/gateway-updown.sh | 2 +- .../snippets/ios.mobileconfig | 0 .../snippets/networkmanager-openvpn.conf | 0 .../snippets/networkmanager-strongswan.conf | 0 .../{ => snippets}/nginx-https-site.conf | 16 +- .../snippets/nginx-ocsp-cache.service | 7 + .../templates/snippets/nginx-ocsp-cache.timer | 3 + .../templates/{ => snippets}/nginx-tls.conf | 5 +- .../templates/snippets/ocsp-cache@.service | 0 .../snippets/openvpn-client.conf | 0 .../snippets/openvpn-client.sh | 0 .../snippets/openwrt-openvpn.sh | 0 .../{static => templates}/snippets/renew.sh | 0 .../snippets/request-client.ps1 | 0 .../snippets/request-client.sh | 0 .../snippets/request-common.sh | 0 .../templates/snippets/request-server.sh | 7 + .../templates/snippets/setup-ocsp-caching.sh | 11 + .../snippets/store-authority.sh | 0 .../snippets/strongswan-client.sh | 0 .../snippets/strongswan-patching.sh | 0 .../snippets/strongswan-server.sh | 0 .../snippets/submit-request-wait.sh} | 6 - .../snippets/update-trust.ps1 | 0 .../snippets/update-trust.sh | 12 +- .../snippets/windows.ps1 | 0 .../views/attributes.html | 0 .../views/authority.html | 44 +++- .../views/configuration.html | 0 .../{static => templates}/views/enroll.html | 0 .../{static => templates}/views/error.html | 0 .../{static => templates}/views/insecure.html | 0 .../{static => templates}/views/lease.html | 2 +- .../{static => templates}/views/logentry.html | 0 .../{static => templates}/views/request.html | 0 .../{static => templates}/views/revoked.html | 0 .../{static => templates}/views/signed.html | 2 +- .../{static => templates}/views/tags.html | 0 .../{static => templates}/views/token.html | 0 tests/test_cli.py | 65 +++--- 56 files changed, 308 insertions(+), 173 deletions(-) create mode 100644 certidude/templates/server/backend.service create mode 100644 certidude/templates/server/ldap-kinit.service create mode 100644 certidude/templates/server/ldap-kinit.timer rename certidude/{static => templates}/snippets/ansible-site.yml (100%) rename certidude/{static => templates}/snippets/certidude-client.sh (100%) rename certidude/{static => templates}/snippets/gateway-updown.sh (67%) rename certidude/{static => templates}/snippets/ios.mobileconfig (100%) rename certidude/{static => templates}/snippets/networkmanager-openvpn.conf (100%) rename certidude/{static => templates}/snippets/networkmanager-strongswan.conf (100%) rename certidude/templates/{ => snippets}/nginx-https-site.conf (61%) create mode 100644 certidude/templates/snippets/nginx-ocsp-cache.service create mode 100644 certidude/templates/snippets/nginx-ocsp-cache.timer rename certidude/templates/{ => snippets}/nginx-tls.conf (87%) create mode 100644 certidude/templates/snippets/ocsp-cache@.service rename certidude/{static => templates}/snippets/openvpn-client.conf (100%) rename certidude/{static => templates}/snippets/openvpn-client.sh (100%) rename certidude/{static => templates}/snippets/openwrt-openvpn.sh (100%) rename certidude/{static => templates}/snippets/renew.sh (100%) rename certidude/{static => templates}/snippets/request-client.ps1 (100%) rename certidude/{static => templates}/snippets/request-client.sh (100%) rename certidude/{static => templates}/snippets/request-common.sh (100%) create mode 100644 certidude/templates/snippets/request-server.sh create mode 100644 certidude/templates/snippets/setup-ocsp-caching.sh rename certidude/{static => templates}/snippets/store-authority.sh (100%) rename certidude/{static => templates}/snippets/strongswan-client.sh (100%) rename certidude/{static => templates}/snippets/strongswan-patching.sh (100%) rename certidude/{static => templates}/snippets/strongswan-server.sh (100%) rename certidude/{static/snippets/request-server.sh => templates/snippets/submit-request-wait.sh} (59%) rename certidude/{static => templates}/snippets/update-trust.ps1 (100%) rename certidude/{static => templates}/snippets/update-trust.sh (50%) rename certidude/{static => templates}/snippets/windows.ps1 (100%) rename certidude/{static => templates}/views/attributes.html (100%) rename certidude/{static => templates}/views/authority.html (92%) rename certidude/{static => templates}/views/configuration.html (100%) rename certidude/{static => templates}/views/enroll.html (100%) rename certidude/{static => templates}/views/error.html (100%) rename certidude/{static => templates}/views/insecure.html (100%) rename certidude/{static => templates}/views/lease.html (85%) rename certidude/{static => templates}/views/logentry.html (100%) rename certidude/{static => templates}/views/request.html (100%) rename certidude/{static => templates}/views/revoked.html (100%) rename certidude/{static => templates}/views/signed.html (98%) rename certidude/{static => templates}/views/tags.html (100%) rename certidude/{static => templates}/views/token.html (100%) diff --git a/README.rst b/README.rst index 45703aa..bd03b4e 100644 --- a/README.rst +++ b/README.rst @@ -60,7 +60,7 @@ Features Common: * Standard request, sign, revoke workflow via web interface. -* RSA and Elliptic Curve Cryptography both supported, use ``certidude setup authority --elliptic-curve`` for the second +* RSA and Elliptic Curve Cryptography both supported, use ``certidude provision authority --elliptic-curve`` for the second * `OCSP `_ and `SCEP `_ support. * PAM and Active Directory compliant authentication backends: Kerberos single sign-on, LDAP simple bind. * POSIX groups and Active Directory (LDAP) group membership based authorization. @@ -74,14 +74,14 @@ Common: Virtual private networking: * Send VPN profile URL tokens via e-mail, for simplified VPN adoption on Android, iOS, Windows, Mac OS X and Ubuntu. -* OpenVPN gateway and roadwarrior integration, check out ``certidude setup openvpn server`` and ``certidude setup openvpn client``. -* StrongSwan gateway and roadwarrior integration, check out ``certidude setup strongswan server`` and ``certidude setup strongswan client``. -* NetworkManager integration for Ubuntu and Fedora, check out ``certidude setup openvpn networkmanager`` and ``certidude setup strongswan networkmanager``. +* OpenVPN gateway and roadwarrior integration, check out ``certidude provision openvpn server`` and ``certidude provision openvpn client``. +* StrongSwan gateway and roadwarrior integration, check out ``certidude provision strongswan server`` and ``certidude provision strongswan client``. +* NetworkManager integration for Ubuntu and Fedora, check out ``certidude provision openvpn networkmanager`` and ``certidude provision strongswan networkmanager``. HTTPS: * P12 bundle generation for web browsers, seems to work well with Android -* HTTPS server setup with client verification, check out ``certidude setup nginx`` +* HTTPS server setup with client verification, check out ``certidude provision nginx`` Install @@ -141,7 +141,7 @@ cronjobs in ``/etc/cron.hourly/certidude`` and much more: .. code:: bash - certidude setup authority + certidude provision authority Tweak the configuration in ``/etc/certidude/server.conf`` until you meet your requirements, to apply changes run: @@ -170,7 +170,7 @@ Python modules: pip3 install simplepam -The default configuration generated by ``certidude setup`` should make use of the +The default configuration generated by ``certidude provision`` should make use of the PAM. Setting up Active Directory authentication @@ -335,6 +335,17 @@ To uninstall: pip3 uninstall certidude +Docker +------ + +.. code:: bash + + git clone https://github.com/laurivosandi/certidude + cd certidude + docker build . + docker run --name ca --hostname ca.example.lan + + Offline install --------------- @@ -367,6 +378,6 @@ Proceed to bootstrap authority without installing packages or assembling assets: .. code:: bash - certidude setup authority --skip-packages --skip-assets [--elliptic-curve] [--organization "Mycorp LLC"] + certidude provision authority --skip-packages --skip-assets [--elliptic-curve] [--organization "Mycorp LLC"] Note it's highly recommended to enable nginx PPA in the target machine diff --git a/certidude/api/ocsp.py b/certidude/api/ocsp.py index bcbfaeb..d84296b 100644 --- a/certidude/api/ocsp.py +++ b/certidude/api/ocsp.py @@ -117,3 +117,6 @@ class OCSPResource(AuthorityHandler): } }).dump() + # Interestingly openssl's OCSP code doesn't care about content type + resp.append_header("Content-Type", "application/ocsp-response") + diff --git a/certidude/authority.py b/certidude/authority.py index d9dd22a..7495139 100644 --- a/certidude/authority.py +++ b/certidude/authority.py @@ -43,6 +43,7 @@ def self_enroll(skip_notify=False): from certidude import const, config common_name = const.FQDN + os.umask(0o0177) try: path, buf, cert, signed, expires = get_signed(common_name) diff --git a/certidude/builder/common.sh b/certidude/builder/common.sh index f07e43d..874e193 100644 --- a/certidude/builder/common.sh +++ b/certidude/builder/common.sh @@ -59,7 +59,7 @@ esac cat << EOF > $OVERLAY/etc/certidude/authority/$AUTHORITY/updown #!/bin/sh -CURL="curl -m 3 -f --key /etc/certidude/authority/$AUTHORITY/host_key.pem --cert /etc/certidude/authority/$AUTHORITY/host_cert.pem --cacert /etc/certidude/authority/$AUTHORITY/ca_cert.pem" +CURL="curl -m 3 -f --key /etc/certidude/authority/$AUTHORITY/host_key.pem --cert /etc/certidude/authority/$AUTHORITY/host_cert.pem --cacert /etc/certidude/authority/$AUTHORITY/ca_cert.pem --cert-status" URL="https://$AUTHORITY:8443/api/signed/\$(uci get system.@system[0].hostname)/script/" case \$PLUTO_VERB in diff --git a/certidude/builder/overlay/usr/bin/certidude-enroll b/certidude/builder/overlay/usr/bin/certidude-enroll index 68c8004..ddb9765 100755 --- a/certidude/builder/overlay/usr/bin/certidude-enroll +++ b/certidude/builder/overlay/usr/bin/certidude-enroll @@ -96,7 +96,7 @@ fi logger -t certidude -s "Request md5sum is $(md5sum -b $REQUEST_PATH)" -curl -f -L \ +curl --cert-status -f -L \ -H "Content-Type: application/pkcs10" \ --cacert $AUTHORITY_PATH \ --data-binary @$REQUEST_PATH \ diff --git a/certidude/builder/overlay/usr/bin/certidude-enroll-renew b/certidude/builder/overlay/usr/bin/certidude-enroll-renew index efff370..8e6eac0 100755 --- a/certidude/builder/overlay/usr/bin/certidude-enroll-renew +++ b/certidude/builder/overlay/usr/bin/certidude-enroll-renew @@ -10,7 +10,7 @@ KEY_PATH=$DIR/host_key.pem # TODO: fix Accepted 202 here -curl -f -L \ +curl --cert-status -f -L \ -H "Content-Type: application/pkcs10" \ --data-binary @$REQUEST_PATH \ --cacert $AUTHORITY_PATH \ diff --git a/certidude/cli.py b/certidude/cli.py index 68ebda6..13a4977 100755 --- a/certidude/cli.py +++ b/certidude/cli.py @@ -684,7 +684,7 @@ def certidude_enroll(fork, renew, no_wait, kerberos, skip_self): help="OpenVPN configuration file") @fqdn_required @setup_client(prefix="server_", dh=True) -def certidude_setup_openvpn_server(authority, common_name, config, subnet, route, local, proto, port, **paths): +def certidude_provision_openvpn_server(authority, common_name, config, subnet, route, local, proto, port, **paths): # Install dependencies apt("openvpn") rpm("openvpn") @@ -745,7 +745,7 @@ def certidude_setup_openvpn_server(authority, common_name, config, subnet, route @click.option("--verify-client", "-vc", default="optional", type=click.Choice(['optional', 'on', 'off'])) @fqdn_required @setup_client(prefix="server_", dh=True) -def certidude_setup_nginx(authority, common_name, site_config, tls_config, verify_client, **paths): +def certidude_provision_nginx(authority, common_name, site_config, tls_config, verify_client, **paths): apt("nginx") rpm("nginx") @@ -759,16 +759,15 @@ def certidude_setup_nginx(authority, common_name, site_config, tls_config, verif if os.path.exists(site_config.name): click.echo("Configuration file %s already exists, not overwriting" % site_config.name) else: - site_config.write(env.get_template("nginx-https-site.conf").render(context)) + site_config.write(env.get_template("snippets/nginx-https-site.conf").render(context)) click.echo("Generated %s" % site_config.name) if os.path.exists(tls_config.name): click.echo("Configuration file %s already exists, not overwriting" % tls_config.name) else: - tls_config.write(env.get_template("nginx-tls.conf").render(context)) + tls_config.write(env.get_template("snippets/nginx-tls.conf").render(context)) click.echo("Generated %s" % tls_config.name) - click.echo() click.echo("Inspect configuration files, enable it and start nginx service:") click.echo() @@ -789,7 +788,7 @@ def certidude_setup_nginx(authority, common_name, site_config, tls_config, verif type=click.File(mode="w", atomic=True, lazy=True), help="OpenVPN configuration file") @setup_client() -def certidude_setup_openvpn_client(authority, remote, common_name, config, proto, **paths): +def certidude_provision_openvpn_client(authority, remote, common_name, config, proto, **paths): # Install dependencies apt("openvpn") rpm("openvpn") @@ -843,7 +842,7 @@ def certidude_setup_openvpn_client(authority, remote, common_name, config, proto @click.option("--route", "-r", type=ip_network, multiple=True, help="Subnets to advertise via this connection, multiple allowed") @fqdn_required @setup_client(prefix="server_") -def certidude_setup_strongswan_server(authority, common_name, subnet, route, **paths): +def certidude_provision_strongswan_server(authority, common_name, subnet, route, **paths): # Install dependencies apt("strongswan") rpm("strongswan") @@ -892,7 +891,7 @@ def certidude_setup_strongswan_server(authority, common_name, subnet, route, **p @click.argument("remote") @click.option("--common-name", "-cn", default=const.HOSTNAME, help="Common name, %s by default" % const.HOSTNAME) @setup_client() -def certidude_setup_strongswan_client(authority, remote, common_name, **paths): +def certidude_provision_strongswan_client(authority, remote, common_name, **paths): # Install dependencies apt("strongswan") or rpm("strongswan") @@ -948,7 +947,7 @@ def certidude_setup_strongswan_client(authority, remote, common_name, **paths): @click.argument("remote") # StrongSwan gateway @click.option("--common-name", "-cn", default=const.HOSTNAME, help="Common name, %s by default" % const.HOSTNAME) @setup_client() -def certidude_setup_strongswan_networkmanager(authority, remote, common_name, **paths): +def certidude_provision_strongswan_networkmanager(authority, remote, common_name, **paths): # Install dependencies apt("network-manager strongswan-nm") rpm("NetworkManager NetworkManager-tui NetworkManager-strongswan-gnome") @@ -976,7 +975,7 @@ def certidude_setup_strongswan_networkmanager(authority, remote, common_name, ** @click.argument("remote") # OpenVPN gateway @click.option("--common-name", "-cn", default=const.HOSTNAME, help="Common name, %s by default" % const.HOSTNAME) @setup_client() -def certidude_setup_openvpn_networkmanager(authority, remote, common_name, **paths): +def certidude_provision_openvpn_networkmanager(authority, remote, common_name, **paths): apt("network-manager network-manager-openvpn-gnome") rpm("NetworkManager NetworkManager-tui NetworkManager-openvpn-gnome") @@ -997,7 +996,7 @@ def certidude_setup_openvpn_networkmanager(authority, remote, common_name, **pat click.echo("Section %s added to /etc/certidude/client.conf" % endpoint) -@click.command("authority", help="Set up Certificate Authority in a directory") +@click.command("authority", help="Set up Certificate Authority") @click.option("--username", default="certidude", help="Service user account, created if necessary, 'certidude' by default") @click.option("--kerberos-keytab", default="/etc/certidude/server.keytab", help="Kerberos keytab for using 'kerberos' authentication backend, /etc/certidude/server.keytab by default") @click.option("--nginx-config", "-n", @@ -1021,10 +1020,25 @@ def certidude_setup_openvpn_networkmanager(authority, remote, common_name, **pat @click.option("--packages-only", is_flag=True, help="Install only apt/pip/npm packages") @click.option("--elliptic-curve", "-e", is_flag=True, help="Generate EC instead of RSA keypair") @click.option("--subordinate", is_flag=True, help="Set up subordinate CA instead of root CA") -def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_config, organization, organizational_unit, common_name, directory, authority_lifetime, push_server, outbox, title, skip_assets, skip_packages, elliptic_curve, subordinate, packages_only): +def certidude_provision_authority(username, kerberos_keytab, nginx_config, tls_config, organization, organizational_unit, common_name, directory, authority_lifetime, push_server, outbox, title, skip_assets, skip_packages, elliptic_curve, subordinate, packages_only): assert subprocess.check_output(["/usr/bin/lsb_release", "-cs"]) in (b"trusty\n", b"xenial\n", b"bionic\n"), "Only Ubuntu 16.04 supported at the moment" assert os.getuid() == 0 and os.getgid() == 0, "Authority can be set up only by root" + def verbose_symlink(name, target): + if not os.path.islink(name): + click.echo("Symlinking %s to %s" % (name, target)) + os.symlink(target, name) + else: + click.echo("Symlink %s already exist, remove to relink" % name) + + def verbose_makedirs(path): + if not os.path.exists(path): + click.echo("Creating directory %s" % path) + os.makedirs(path) + else: + click.echo("Directory %s already exists" % path) + + import pwd from jinja2 import Environment, PackageLoader env = Environment(loader=PackageLoader("certidude", "templates"), trim_blocks=True) @@ -1070,8 +1084,7 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi if os.system(cmd): raise click.ClickException("Failed to install JavaScript packages") - if not os.path.exists("/usr/bin/node"): - os.symlink("/usr/bin/nodejs", "/usr/bin/node") + verbose_symlink("/usr/bin/node", "/usr/bin/nodejs") if packages_only: return @@ -1100,7 +1113,7 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi assets_dir = os.path.join(directory, "assets") ca_key = os.path.join(directory, "ca_key.pem") ca_req = os.path.join(directory, "ca_req.pem") - ca_cert = os.path.join(directory, "ca_cert.pem") + authority_path = os.path.join(directory, "ca_cert.pem") self_key = os.path.join(directory, "self_key.pem") sqlite_path = os.path.join(directory, "meta", "db.sqlite") distinguished_name = cn_to_dn(title, common_name, o=organization, ou=organizational_unit) @@ -1120,7 +1133,7 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi if os.path.exists(kerberos_keytab): click.echo("Service principal keytab found in '%s'" % kerberos_keytab) else: - click.echo("To use 'kerberos' authentication backend join the domain , create service principal and provision authority again:") + click.echo("To use 'kerberos' authentication backend join the domain, create service principal and provision authority again:") click.echo() click.echo(" kinit administrator@EXAMPLE.LAN") click.echo(" net ads join -k") @@ -1128,17 +1141,9 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi click.echo(" kdestroy") click.echo(" chown %s %s" % (username, kerberos_keytab)) click.echo(" mv /etc/certidude/server.conf /etc/certidude/server.backup") - click.echo(" certidude setup authority") + click.echo(" certidude provision authority") click.echo() - - for interval in ("hourly", "daily"): - if not os.path.exists("/etc/cron.%s/certidude" % interval): - with open("/etc/cron.%s/certidude" % interval, "w") as fh: - fh.write("#!/bin/bash\nLANG=C.UTF-8 certidude cron %s\n" % interval) - os.chmod("/etc/cron.%s/certidude" % interval, 0o755) - click.echo("Created /etc/cron.%s/certidude" % interval) - if os.path.exists("/etc/krb5.keytab") and os.path.exists("/etc/samba/smb.conf"): # Fetch Kerberos ticket for system account cp = ConfigParser() @@ -1148,6 +1153,7 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi name = cp.get("global", "netbios name") base = ",".join(["dc=" + j for j in domain.split(".")]) else: + realm = None click.echo("Warning: /etc/krb5.keytab or /etc/samba/smb.conf not found, Kerberos unconfigured") letsencrypt_fullchain = "/etc/letsencrypt/live/%s/fullchain.pem" % common_name @@ -1157,25 +1163,35 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi builder_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), "builder") script_dir = os.path.join(os.path.realpath(os.path.dirname(__file__)), "templates", "script") + templates_dir = os.path.join(os.path.realpath(os.path.dirname(__file__)), "templates") static_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), "static") certidude_path = sys.argv[0] click.echo("Generating: %s" % nginx_config.name) nginx_config.write(env.get_template("server/nginx.conf").render(vars())) nginx_config.close() - if not os.path.exists("/etc/nginx/sites-enabled/certidude.conf"): - os.symlink("../sites-available/certidude.conf", "/etc/nginx/sites-enabled/certidude.conf") - click.echo("Symlinked %s -> /etc/nginx/sites-enabled/" % nginx_config.name) + + def verbose_render_systemd_service(template, target, context): + target_path = "/etc/systemd/system/%s" % target + if os.path.exists(target_path): + click.echo("File %s already exists, remove to regenerate" % target_path) + else: + buf = env.get_template(template).render(context) + with open(target_path, "w") as fh: + fh.write(buf) + click.echo("File %s created" % target_path) + os.system("systemctl daemon-reload") + + verbose_symlink("/etc/nginx/sites-enabled/certidude.conf", "../sites-available/certidude.conf") + if os.path.exists("/etc/nginx/sites-enabled/default"): os.unlink("/etc/nginx/sites-enabled/default") if os.path.exists("/etc/systemd"): - if os.path.exists("/etc/systemd/system/certidude.service"): - click.echo("File /etc/systemd/system/certidude.service already exists, remove to regenerate") - else: - with open("/etc/systemd/system/certidude.service", "w") as fh: - fh.write(env.get_template("server/systemd.service").render(vars())) - click.echo("File /etc/systemd/system/certidude.service created") - os.system("systemctl daemon-reload") + verbose_render_systemd_service("server/backend.service", "certidude-backend.service", vars()) + verbose_render_systemd_service("server/ldap-kinit.service", "certidude-ldap-kinit.service", vars()) + verbose_render_systemd_service("server/ldap-kinit.timer", "certidude-ldap-kinit.timer", vars()) + verbose_render_systemd_service("snippets/nginx-ocsp-cache.service", "certidude-ocsp-cache.service", vars()) + verbose_render_systemd_service("snippets/nginx-ocsp-cache.timer", "certidude-ocsp-cache.timer", vars()) else: raise NotImplementedError("Not systemd based OS, don't know how to set up initscripts") @@ -1209,7 +1225,7 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi raise click.ClickException("Failed to copy fonts") # Compile nunjucks templates - cmd = 'nunjucks-precompile --include "\.html$" --include "\.ps1$" --include "\.sh$" --include "\.svg$" --include "\.yml$" --include "\.conf$" --include "\.mobileconfig$" %s > %s.part' % (static_path, bundle_js) + cmd = 'nunjucks-precompile --include snippets --include views %s > %s.part' % (templates_dir, bundle_js) click.echo("Compiling templates: %s" % cmd) if os.system(cmd): raise click.ClickException("Failed to compile nunjucks templates") @@ -1256,7 +1272,7 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi if os.path.exists(tls_config.name): click.echo("Configuration file %s already exists, not overwriting" % tls_config.name) else: - tls_config.write(env.get_template("nginx-tls.conf").render(locals())) + tls_config.write(env.get_template("snippets/nginx-tls.conf").render(locals())) click.echo("Generated %s" % tls_config.name) if os.path.exists(const.SERVER_CONFIG_PATH): @@ -1295,11 +1311,7 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi os.umask(0o007) for subdir in ("signed", "signed/by-serial", "requests", "revoked", "expired", "meta", "builder"): path = os.path.join(directory, subdir) - if not os.path.exists(path): - click.echo("Creating directory %s" % path) - os.mkdir(path) - else: - click.echo("Directory already exists %s" % path) + verbose_makedirs(path) assert os.stat(path).st_mode == 0o40770, path # Create SQLite database file with correct permissions @@ -1308,6 +1320,21 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi with open(sqlite_path, "wb") as fh: pass + # Create symlink for self certificate + verbose_symlink("/var/lib/certidude/self_cert.pem", "signed/" + common_name + ".pem") + + # Symlink client paths + verbose_makedirs("/etc/certidude/authority/%s" % common_name) + verbose_symlink( + "/etc/certidude/authority/%s/host_cert.pem" % common_name, + "/var/lib/certidude/self_cert.pem") + verbose_symlink( + "/etc/certidude/authority/%s/host_key.pem" % common_name, + "/var/lib/certidude/self_key.pem") + verbose_symlink( + "/etc/certidude/authority/%s/ca_cert.pem" % common_name, + "/var/lib/certidude/ca_cert.pem") + # Generate and sign CA key if not os.path.exists(ca_key) or subordinate and not os.path.exists(ca_req): if elliptic_curve: @@ -1329,22 +1356,22 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi f.write(pem_armor_csr(request)) os.rename(ca_req + ".part", ca_req) - if not os.path.exists(ca_cert): + if not os.path.exists(authority_path): if subordinate: click.echo("Request has been written to %s" % ca_req) click.echo() click.echo(open(ca_req).read()) click.echo() - click.echo("Get it signed and insert signed certificate into %s" % ca_cert) + click.echo("Get it signed and insert signed certificate into %s" % authority_path) click.echo() - click.echo(" cat > %s" % ca_cert) + click.echo(" cat > %s" % authority_path) click.echo() click.echo("Paste contents and press Ctrl-D, adjust permissions:") click.echo() - click.echo(" chown root:root %s" % ca_cert) - click.echo(" chmod 0644 %s" % ca_cert) + click.echo(" chown root:root %s" % authority_path) + click.echo(" chmod 0644 %s" % authority_path) click.echo() - click.echo("To finish setup procedure run 'certidude setup authority' again") + click.echo("To finish setup procedure run 'certidude provision authority' again") sys.exit(1) # stop this fork here with error # https://technet.microsoft.com/en-us/library/aa998840(v=exchg.141).aspx @@ -1360,9 +1387,9 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi # Set permission bits to 640 os.umask(0o137) - with open(ca_cert, 'wb') as f: + with open(authority_path, 'wb') as f: f.write(pem_armor_certificate(certificate)) - click.echo("Authority certificate written to: %s" % ca_cert) + click.echo("Authority certificate written to: %s" % authority_path) sys.exit(0) # stop this fork here else: @@ -1376,18 +1403,27 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi assert os.path.exists(os.path.join(directory, "signed", common_name) + ".pem") assert os.getuid() == 0 and os.getgid() == 0, "Enroll contaminated environment" assert os.stat(sqlite_path).st_mode == 0o100660 - assert os.stat(ca_cert).st_mode == 0o100640 + assert os.stat(authority_path).st_mode == 0o100640 assert os.stat(ca_key).st_mode == 0o100600 + assert os.stat(self_key).st_mode == 0o100600 assert os.stat("/etc/nginx/sites-available/certidude.conf").st_mode == 0o100600 assert os.stat("/etc/certidude/server.conf").st_mode == 0o100600 + # Disable legacy garbage + if os.path.exists("/etc/cron.hourly/certidude"): + os.unlink("/etc/cron.hourly/certidude") + if os.path.exists("/etc/cron.daily/certidude"): + os.unlink("/etc/cron.daily/certidude") + if os.path.exists("/etc/systemd/system/certidude.service"): + os.unlink("/etc/systemd/system/certidude.service") + click.echo("To enable e-mail notifications install Postfix as sattelite system and set mailer address in %s" % const.SERVER_CONFIG_PATH) click.echo() click.echo("Use following commands to inspect the newly created files:") click.echo() - click.echo(" openssl x509 -text -noout -in %s | less" % ca_cert) + click.echo(" openssl x509 -text -noout -in %s | less" % authority_path) click.echo(" openssl rsa -check -in %s" % ca_key) - click.echo(" openssl verify -CAfile %s %s" % (ca_cert, ca_cert)) + click.echo(" openssl verify -CAfile %s %s" % (authority_path, authority_path)) click.echo() click.echo("To inspect logs and issued tokens:") click.echo() @@ -1395,12 +1431,19 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, tls_confi click.echo(" echo 'select * from token;' | sqlite3 /var/lib/certidude/meta/db.sqlite") click.echo() click.echo("Enabling Certidude backend and nginx...") - os.system("systemctl enable certidude") + os.system("systemctl enable certidude-backend.service") os.system("systemctl enable nginx") + os.system("systemctl enable certidude-ocsp-cache.timer") + os.system("systemctl start certidude-ocsp-cache.timer") + if realm: + os.system("systemctl enable certidude-ldap-kinit.timer") + os.system("systemctl start certidude-ldap-kinit.timer") + os.system("systemctl start certidude-ldap-kinit.service") click.echo("To (re)start services:") click.echo() - click.echo(" systemctl restart certidude") + click.echo(" systemctl restart certidude-backend") click.echo(" systemctl restart nginx") + click.echo(" systemctl start certidude-ocsp-cache.service") click.echo() return 0 @@ -1517,8 +1560,8 @@ def certidude_revoke(common_name, reason): authority.revoke(common_name, reason) -@click.command("hourly", help="Hourly housekeeping tasks") -def certidude_cron_hourly(): +@click.command("kinit", help="Initialize Kerberos credential cache for LDAP") +def certidude_housekeeping_kinit(): from certidude import config # Update LDAP service ticket if Certidude is joined to domain @@ -1535,8 +1578,8 @@ def certidude_cron_hourly(): os.rename("/run/certidude/krb5cc.part", "/run/certidude/krb5cc") -@click.command("daily", help="Daily housekeeping tasks") -def certidude_cron_daily(): +@click.command("daily", help="Send notifications about expired certificates") +def certidude_housekeeping_expiration(): from certidude import authority, config, mailer threshold_move = datetime.utcnow() - const.CLOCK_SKEW_TOLERANCE threshold_notify = datetime.utcnow() + timedelta(hours=48) @@ -1633,11 +1676,6 @@ def certidude_serve(port, listen, fork): Drop privileges """ - - # Initialize LDAP service ticket - if os.path.exists("/etc/cron.hourly/certidude"): - os.system("/etc/cron.hourly/certidude") - from certidude.push import EventSourceLogHandler log_handlers.append(EventSourceLogHandler()) @@ -1671,7 +1709,7 @@ def certidude_serve(port, listen, fork): @click.option("-p", "--pin", default="123456", help="Slot pincode, 123456 by default") @click.option("-s", "--slot", default="9a", help="Yubikey slot to use, 9a by default") @click.option("-u", "--username", default=os.getenv("USER"), help="Username to use, %s by default" % os.getenv("USER")) -def certidude_setup_yubikey(authority, slot, username, pin): +def certidude_provision_yubikey(authority, slot, username, pin): import requests cmd = "ykinfo", "-q", "-s" click.echo("Executing: %s" % " ".join(cmd)) @@ -1750,47 +1788,48 @@ def certidude_token_issue(subject, subject_mail): @click.group("strongswan", help="strongSwan helpers") -def certidude_setup_strongswan(): pass +def certidude_provision_strongswan(): pass @click.group("openvpn", help="OpenVPN helpers") -def certidude_setup_openvpn(): pass +def certidude_provision_openvpn(): pass -@click.group("setup", help="Getting started section") -def certidude_setup(): pass +@click.group("provision", help="Getting started section") +def certidude_provision(): pass + +@click.group("housekeeping", help="Housekeeping tasks") +def certidude_housekeeping(): pass @click.group("token", help="Token management") def certidude_token(): pass -@click.group("cron", help="Housekeeping tasks") -def certidude_cron(): pass - @click.group() def entry_point(): pass -certidude_setup_strongswan.add_command(certidude_setup_strongswan_server) -certidude_setup_strongswan.add_command(certidude_setup_strongswan_client) -certidude_setup_strongswan.add_command(certidude_setup_strongswan_networkmanager) -certidude_setup_openvpn.add_command(certidude_setup_openvpn_server) -certidude_setup_openvpn.add_command(certidude_setup_openvpn_client) -certidude_setup_openvpn.add_command(certidude_setup_openvpn_networkmanager) -certidude_setup.add_command(certidude_setup_authority) -certidude_setup.add_command(certidude_setup_openvpn) -certidude_setup.add_command(certidude_setup_strongswan) -certidude_setup.add_command(certidude_setup_nginx) -certidude_setup.add_command(certidude_setup_yubikey) + +certidude_provision_strongswan.add_command(certidude_provision_strongswan_server) +certidude_provision_strongswan.add_command(certidude_provision_strongswan_client) +certidude_provision_strongswan.add_command(certidude_provision_strongswan_networkmanager) +certidude_provision_openvpn.add_command(certidude_provision_openvpn_server) +certidude_provision_openvpn.add_command(certidude_provision_openvpn_client) +certidude_provision_openvpn.add_command(certidude_provision_openvpn_networkmanager) +certidude_provision.add_command(certidude_provision_authority) +certidude_provision.add_command(certidude_provision_openvpn) +certidude_provision.add_command(certidude_provision_strongswan) +certidude_provision.add_command(certidude_provision_nginx) +certidude_provision.add_command(certidude_provision_yubikey) certidude_token.add_command(certidude_token_list) certidude_token.add_command(certidude_token_purge) certidude_token.add_command(certidude_token_issue) -certidude_cron.add_command(certidude_cron_hourly) -certidude_cron.add_command(certidude_cron_daily) +certidude_housekeeping.add_command(certidude_housekeeping_kinit) +certidude_housekeeping.add_command(certidude_housekeeping_expiration) entry_point.add_command(certidude_token) -entry_point.add_command(certidude_setup) +entry_point.add_command(certidude_provision) entry_point.add_command(certidude_serve) entry_point.add_command(certidude_enroll) entry_point.add_command(certidude_sign) entry_point.add_command(certidude_revoke) entry_point.add_command(certidude_list) -entry_point.add_command(certidude_cron) +entry_point.add_command(certidude_housekeeping) entry_point.add_command(certidude_users) entry_point.add_command(certidude_test) diff --git a/certidude/static/js/certidude.js b/certidude/static/js/certidude.js index 573794a..860019e 100644 --- a/certidude/static/js/certidude.js +++ b/certidude/static/js/certidude.js @@ -546,7 +546,15 @@ function loadAuthority(query) { **/ $("#view-dashboard").html(env.render('views/authority.html', { session: session, - window: window + window: window, + + // Parameters for unified snippets + dhparam_path: "/etc/ssl/dhparam.pem", + key_path: "/etc/certidude/authority/" + session.authority.hostname + "/host_key.pem", + certificate_path: "/etc/certidude/authority/" + session.authority.hostname + "/host_cert.pem", + authority_path: "/etc/certidude/authority/" + session.authority.hostname + "/ca_cert.pem", + revocations_path: "/etc/certidude/authority/" + session.authority.hostname + "/crl.pem", + common_name: "$NAME" })); $("time").timeago(); diff --git a/certidude/templates/script/default.sh b/certidude/templates/script/default.sh index 9e1305a..bc0a246 100644 --- a/certidude/templates/script/default.sh +++ b/certidude/templates/script/default.sh @@ -32,7 +32,7 @@ else fi # Submit some stats to CA -curl https://{{ authority_name }}:8443/api/signed/{{ common_name }}/attr \ +curl --cert-status https://{{ authority_name }}:8443/api/signed/{{ common_name }}/attr \ --cacert /etc/certidude/authority/{{ authority_name }}/ca_cert.pem \ --key /etc/certidude/authority/{{ authority_name }}/host_key.pem \ --cert /etc/certidude/authority/{{ authority_name }}/host_cert.pem \ diff --git a/certidude/templates/server/backend.service b/certidude/templates/server/backend.service new file mode 100644 index 0000000..ef0d364 --- /dev/null +++ b/certidude/templates/server/backend.service @@ -0,0 +1,17 @@ +[Unit] +Description=Certidude server +After=network.target + +[Service] +Type=forking +EnvironmentFile=/etc/environment +Environment=LANG=C.UTF-8 +Environment=PYTHON_EGG_CACHE=/tmp/.cache +PIDFile=/run/certidude/server.pid +KillSignal=SIGINT +ExecStart={{ certidude_path }} serve --fork +TimeoutSec=15 + +[Install] +WantedBy=multi-user.target + diff --git a/certidude/templates/server/ldap-kinit.service b/certidude/templates/server/ldap-kinit.service new file mode 100644 index 0000000..220a82b --- /dev/null +++ b/certidude/templates/server/ldap-kinit.service @@ -0,0 +1,7 @@ +[Unit] +Description=Initialize Kerberos credential cache for LDAP connections of Certidude + +[Service] +Type=oneshot +ExecStart={{ certidude_path }} housekeeping kinit +Before=certidude-backend.service diff --git a/certidude/templates/server/ldap-kinit.timer b/certidude/templates/server/ldap-kinit.timer new file mode 100644 index 0000000..ca42dca --- /dev/null +++ b/certidude/templates/server/ldap-kinit.timer @@ -0,0 +1,3 @@ +[Timer] +OnCalendar=00/8:30 +Persistent=true diff --git a/certidude/templates/server/nginx.conf b/certidude/templates/server/nginx.conf index b5e4613..dcf3a68 100644 --- a/certidude/templates/server/nginx.conf +++ b/certidude/templates/server/nginx.conf @@ -137,10 +137,16 @@ server { server_name {{ common_name }}; listen 8443 ssl http2; + # Enforce OCSP stapling for the server certificate + # Note that even nginx 1.14.0 doesn't immideately populate the OCSP cache + # You need to run separate cronjob to populate the OCSP response cache + ssl_stapling on; + ssl_stapling_verify on; + # Allow client authentication with certificate, # backend must still check if certificate was used for TLS handshake ssl_verify_client optional; - ssl_client_certificate {{ directory }}/ca_cert.pem; + ssl_client_certificate {{ authority_path }}; # Proxy pass to backend location /api/ { diff --git a/certidude/templates/server/server.conf b/certidude/templates/server/server.conf index 543ced9..7b5c642 100644 --- a/certidude/templates/server/server.conf +++ b/certidude/templates/server/server.conf @@ -218,7 +218,7 @@ user enrollment = multiple allowed # Certificate authority keypair private key path = {{ ca_key }} -certificate path = {{ ca_cert }} +certificate path = {{ authority_path }} # Private key used by nginx frontend self key path = {{ self_key }} diff --git a/certidude/static/snippets/ansible-site.yml b/certidude/templates/snippets/ansible-site.yml similarity index 100% rename from certidude/static/snippets/ansible-site.yml rename to certidude/templates/snippets/ansible-site.yml diff --git a/certidude/static/snippets/certidude-client.sh b/certidude/templates/snippets/certidude-client.sh similarity index 100% rename from certidude/static/snippets/certidude-client.sh rename to certidude/templates/snippets/certidude-client.sh diff --git a/certidude/static/snippets/gateway-updown.sh b/certidude/templates/snippets/gateway-updown.sh similarity index 67% rename from certidude/static/snippets/gateway-updown.sh rename to certidude/templates/snippets/gateway-updown.sh index a89d3fb..b487a72 100644 --- a/certidude/static/snippets/gateway-updown.sh +++ b/certidude/templates/snippets/gateway-updown.sh @@ -2,7 +2,7 @@ cat <<\EOF > /etc/certidude/authority/{{ session.authority.hostname }}/updown #!/bin/sh -CURL="curl -m 3 -f --key /etc/certidude/authority/{{ session.authority.hostname }}/host_key.pem --cert /etc/certidude/authority/{{ session.authority.hostname }}/host_cert.pem --cacert /etc/certidude/authority/{{ session.authority.hostname }}/ca_cert.pem https://{{ session.authority.hostname }}:8443/api/lease/" +CURL="curl --cert-status -m 3 -f --key /etc/certidude/authority/{{ session.authority.hostname }}/host_key.pem --cert /etc/certidude/authority/{{ session.authority.hostname }}/host_cert.pem --cacert /etc/certidude/authority/{{ session.authority.hostname }}/ca_cert.pem https://{{ session.authority.hostname }}:8443/api/lease/" case $PLUTO_VERB in up-client) $CURL --data-urlencode "outer_address=$PLUTO_PEER" --data-urlencode "inner_address=$PLUTO_PEER_SOURCEIP" --data-urlencode "client=$PLUTO_PEER_ID" ;; diff --git a/certidude/static/snippets/ios.mobileconfig b/certidude/templates/snippets/ios.mobileconfig similarity index 100% rename from certidude/static/snippets/ios.mobileconfig rename to certidude/templates/snippets/ios.mobileconfig diff --git a/certidude/static/snippets/networkmanager-openvpn.conf b/certidude/templates/snippets/networkmanager-openvpn.conf similarity index 100% rename from certidude/static/snippets/networkmanager-openvpn.conf rename to certidude/templates/snippets/networkmanager-openvpn.conf diff --git a/certidude/static/snippets/networkmanager-strongswan.conf b/certidude/templates/snippets/networkmanager-strongswan.conf similarity index 100% rename from certidude/static/snippets/networkmanager-strongswan.conf rename to certidude/templates/snippets/networkmanager-strongswan.conf diff --git a/certidude/templates/nginx-https-site.conf b/certidude/templates/snippets/nginx-https-site.conf similarity index 61% rename from certidude/templates/nginx-https-site.conf rename to certidude/templates/snippets/nginx-https-site.conf index e700b2b..6bb298a 100644 --- a/certidude/templates/nginx-https-site.conf +++ b/certidude/templates/snippets/nginx-https-site.conf @@ -1,8 +1,8 @@ server { listen 80; - server_name {{common_name}}; - rewrite ^ https://{{common_name}}$request_uri?; + server_name {{ common_name }}; + rewrite ^ https://{{ common_name }}\$request_uri?; } server { @@ -10,19 +10,21 @@ server { add_header X-Frame-Options "DENY"; add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; listen 443 ssl; - server_name {{common_name}}; + server_name $NAME; client_max_body_size 10G; ssl_certificate {{certificate_path}}; ssl_certificate_key {{key_path}}; ssl_client_certificate {{authority_path}}; - ssl_crl {{revocations_path}}; - ssl_verify_client {{verify_client}}; - location ~ \.php$ { + # Uncomment following to enable mutual authentication with certificates + #ssl_crl {{revocations_path}}; + #ssl_verify_client on; + + location ~ \.php\$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/run/php5-fpm.sock; fastcgi_index index.php; - fastcgi_param REMOTE_USER $ssl_client_s_dn_cn; + fastcgi_param REMOTE_USER \$ssl_client_s_dn_cn; include fastcgi_params; } } diff --git a/certidude/templates/snippets/nginx-ocsp-cache.service b/certidude/templates/snippets/nginx-ocsp-cache.service new file mode 100644 index 0000000..d58c07f --- /dev/null +++ b/certidude/templates/snippets/nginx-ocsp-cache.service @@ -0,0 +1,7 @@ +[Unit] +Description=Cache OCSP responses for nginx OCSP stapling + +[Service] +Type=oneshot +Requires=nginx.service +ExecStart=-/usr/bin/curl --cert-status https://{{ common_name }}:8443/ --cacert /etc/certidude/authority/{{ session.authority.hostname }}/ca_cert.pem diff --git a/certidude/templates/snippets/nginx-ocsp-cache.timer b/certidude/templates/snippets/nginx-ocsp-cache.timer new file mode 100644 index 0000000..82a60c0 --- /dev/null +++ b/certidude/templates/snippets/nginx-ocsp-cache.timer @@ -0,0 +1,3 @@ +[Timer] +OnCalendar=*:0/15 +Persistent=true diff --git a/certidude/templates/nginx-tls.conf b/certidude/templates/snippets/nginx-tls.conf similarity index 87% rename from certidude/templates/nginx-tls.conf rename to certidude/templates/snippets/nginx-tls.conf index 30fa0fb..8884875 100644 --- a/certidude/templates/nginx-tls.conf +++ b/certidude/templates/snippets/nginx-tls.conf @@ -8,9 +8,6 @@ ssl_ecdh_curve secp384r1; ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; -ssl_trusted_certificate {{ ca_cert }}; # OCSP responder trust chain -ssl_stapling on; -ssl_stapling_verify on; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; @@ -23,6 +20,6 @@ add_header X-Robots-Tag none; # Add SSLUserName SSL_CLIENT_S_DN_CN style parameter support map $ssl_client_s_dn $ssl_client_s_dn_cn { default ""; - ~/CN=(?[^/]+) $CN; + ~/CN=([^/]+) $1; } diff --git a/certidude/templates/snippets/ocsp-cache@.service b/certidude/templates/snippets/ocsp-cache@.service new file mode 100644 index 0000000..e69de29 diff --git a/certidude/static/snippets/openvpn-client.conf b/certidude/templates/snippets/openvpn-client.conf similarity index 100% rename from certidude/static/snippets/openvpn-client.conf rename to certidude/templates/snippets/openvpn-client.conf diff --git a/certidude/static/snippets/openvpn-client.sh b/certidude/templates/snippets/openvpn-client.sh similarity index 100% rename from certidude/static/snippets/openvpn-client.sh rename to certidude/templates/snippets/openvpn-client.sh diff --git a/certidude/static/snippets/openwrt-openvpn.sh b/certidude/templates/snippets/openwrt-openvpn.sh similarity index 100% rename from certidude/static/snippets/openwrt-openvpn.sh rename to certidude/templates/snippets/openwrt-openvpn.sh diff --git a/certidude/static/snippets/renew.sh b/certidude/templates/snippets/renew.sh similarity index 100% rename from certidude/static/snippets/renew.sh rename to certidude/templates/snippets/renew.sh diff --git a/certidude/static/snippets/request-client.ps1 b/certidude/templates/snippets/request-client.ps1 similarity index 100% rename from certidude/static/snippets/request-client.ps1 rename to certidude/templates/snippets/request-client.ps1 diff --git a/certidude/static/snippets/request-client.sh b/certidude/templates/snippets/request-client.sh similarity index 100% rename from certidude/static/snippets/request-client.sh rename to certidude/templates/snippets/request-client.sh diff --git a/certidude/static/snippets/request-common.sh b/certidude/templates/snippets/request-common.sh similarity index 100% rename from certidude/static/snippets/request-common.sh rename to certidude/templates/snippets/request-common.sh diff --git a/certidude/templates/snippets/request-server.sh b/certidude/templates/snippets/request-server.sh new file mode 100644 index 0000000..2c62a92 --- /dev/null +++ b/certidude/templates/snippets/request-server.sh @@ -0,0 +1,7 @@ +# Use fully qualified name +test -e /sbin/uci && NAME=$(nslookup $(uci get network.wan.ipaddr) | grep "name =" | head -n1 | cut -d "=" -f 2 | xargs) +test -e /bin/hostname && NAME=$(hostname -f) +test -n "$NAME" || NAME=$(cat /proc/sys/kernel/hostname) + +{% include "snippets/request-common.sh" %} +{% include "snippets/submit-request-wait.sh" %} diff --git a/certidude/templates/snippets/setup-ocsp-caching.sh b/certidude/templates/snippets/setup-ocsp-caching.sh new file mode 100644 index 0000000..514f036 --- /dev/null +++ b/certidude/templates/snippets/setup-ocsp-caching.sh @@ -0,0 +1,11 @@ +# See more on http://unmitigatedrisk.com/?p=241 why we're doing this +cat << EOF > /etc/systemd/system/nginx-ocsp-cache.service +{% include "snippets/nginx-ocsp-cache.service" %}EOF + +cat << EOF > /etc/systemd/system/nginx-ocsp-cache.timer +{% include "snippets/nginx-ocsp-cache.timer" %}EOF + +systemctl enable nginx-ocsp-cache.service +systemctl enable nginx-ocsp-cache.timer +systemctl start nginx-ocsp-cache.service +systemctl start nginx-ocsp-cache.timer diff --git a/certidude/static/snippets/store-authority.sh b/certidude/templates/snippets/store-authority.sh similarity index 100% rename from certidude/static/snippets/store-authority.sh rename to certidude/templates/snippets/store-authority.sh diff --git a/certidude/static/snippets/strongswan-client.sh b/certidude/templates/snippets/strongswan-client.sh similarity index 100% rename from certidude/static/snippets/strongswan-client.sh rename to certidude/templates/snippets/strongswan-client.sh diff --git a/certidude/static/snippets/strongswan-patching.sh b/certidude/templates/snippets/strongswan-patching.sh similarity index 100% rename from certidude/static/snippets/strongswan-patching.sh rename to certidude/templates/snippets/strongswan-patching.sh diff --git a/certidude/static/snippets/strongswan-server.sh b/certidude/templates/snippets/strongswan-server.sh similarity index 100% rename from certidude/static/snippets/strongswan-server.sh rename to certidude/templates/snippets/strongswan-server.sh diff --git a/certidude/static/snippets/request-server.sh b/certidude/templates/snippets/submit-request-wait.sh similarity index 59% rename from certidude/static/snippets/request-server.sh rename to certidude/templates/snippets/submit-request-wait.sh index d7e6a80..9ad2710 100644 --- a/certidude/static/snippets/request-server.sh +++ b/certidude/templates/snippets/submit-request-wait.sh @@ -1,9 +1,3 @@ -# Use fully qualified name -test -e /sbin/uci && NAME=$(nslookup $(uci get network.wan.ipaddr) | grep "name =" | head -n1 | cut -d "=" -f 2 | xargs) -test -e /bin/hostname && NAME=$(hostname -f) -test -n "$NAME" || NAME=$(cat /proc/sys/kernel/hostname) - -{% include "snippets/request-common.sh" %} # Submit CSR and save signed certificate curl --cert-status -f -L -H "Content-type: application/pkcs10" \ --cacert /etc/certidude/authority/{{ session.authority.hostname }}/ca_cert.pem \ diff --git a/certidude/static/snippets/update-trust.ps1 b/certidude/templates/snippets/update-trust.ps1 similarity index 100% rename from certidude/static/snippets/update-trust.ps1 rename to certidude/templates/snippets/update-trust.ps1 diff --git a/certidude/static/snippets/update-trust.sh b/certidude/templates/snippets/update-trust.sh similarity index 50% rename from certidude/static/snippets/update-trust.sh rename to certidude/templates/snippets/update-trust.sh index 5328b27..f33a65f 100644 --- a/certidude/static/snippets/update-trust.sh +++ b/certidude/templates/snippets/update-trust.sh @@ -5,12 +5,14 @@ test -e /etc/pki/ca-trust/source/anchors \ # Insert into Ubuntu trust store, only applies to curl test -e /usr/local/share/ca-certificates/ \ - && ln -s /etc/certidude/authority/{{ session.authority.hostname }}/ca_cert.pem /usr/local/share/ca-certificates/{{ session.authority.hostname }}.crt \ + && ln -f -s /etc/certidude/authority/{{ session.authority.hostname }}/ca_cert.pem /usr/local/share/ca-certificates/{{ session.authority.hostname }}.crt \ && update-ca-certificates # Patch Firefox trust store on Ubuntu -if [ ! -h /usr/lib/firefox/libnssckbi.so ]; then - apt install p11-kit p11-kit-modules - mv /usr/lib/firefox/libnssckbi.so /usr/lib/firefox/libnssckbi.so.bak - ln -s /usr/lib/x86_64-linux-gnu/pkcs11/p11-kit-trust.so /usr/lib/firefox/libnssckbi.so +if [ -d /usr/lib/firefox ]; then + if [ ! -h /usr/lib/firefox/libnssckbi.so ]; then + apt install -y p11-kit p11-kit-modules + mv /usr/lib/firefox/libnssckbi.so /usr/lib/firefox/libnssckbi.so.bak + ln -s /usr/lib/x86_64-linux-gnu/pkcs11/p11-kit-trust.so /usr/lib/firefox/libnssckbi.so + fi fi diff --git a/certidude/static/snippets/windows.ps1 b/certidude/templates/snippets/windows.ps1 similarity index 100% rename from certidude/static/snippets/windows.ps1 rename to certidude/templates/snippets/windows.ps1 diff --git a/certidude/static/views/attributes.html b/certidude/templates/views/attributes.html similarity index 100% rename from certidude/static/views/attributes.html rename to certidude/templates/views/attributes.html diff --git a/certidude/static/views/authority.html b/certidude/templates/views/authority.html similarity index 92% rename from certidude/static/views/authority.html rename to certidude/templates/views/authority.html index 018c7cb..98cd160 100644 --- a/certidude/static/views/authority.html +++ b/certidude/templates/views/authority.html @@ -19,6 +19,10 @@ UNIX + + {% if "openvpn" in session.service.protocols %}