1
0
mirror of https://github.com/laurivosandi/certidude synced 2025-10-29 00:19:27 +00:00
Files
certidude/certidude/static/views/authority.html

410 lines
15 KiB
HTML

<div class="modal fade" id="request_submission_modal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Request submission</h4>
</div>
<form action="/api/request/" method="post">
<div class="modal-body">
<h5>Certidude client</h5>
<p>Submit a certificate signing request from Mac OS X, Ubuntu or Fedora:</p>
<div class="highlight">
<pre><code>easy_install pip;
pip3 install certidude;
certidude bootstrap {{session.authority.common_name}}
</code></pre>
</div>
<h5>Windows 10</h5>
<p>On Windows execute following PowerShell script</p>
<div class="highlight">
<pre class="code"><code>$hostname = $env:computername.ToLower()
$templ = @"
[Version]
Signature="$Windows NT$
[NewRequest]
Subject = "CN=$hostname"
Exportable = FALSE
KeyLength = 2048
KeySpec = 1
KeyUsage = 0xA0
MachineKeySet = True
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
"@
$templ | Out-File req.inf
# Fetch CA certificate and install it
Invoke-WebRequest -Uri http://{{ window.location.hostname }}/api/certificate -OutFile ca_cert.pem
Import-Certificate -FilePath ca_cert.pem -CertStoreLocation Cert:\LocalMachine\Root
# Generate keypair and submit CSR
C:\Windows\system32\certreq.exe -new -f -q req.inf client_csr.pem
Invoke-WebRequest -TimeoutSec 900 -Uri http://{{ window.location.hostname }}/api/request/?wait=1 -InFile client_csr.pem -ContentType application/pkcs10 -Method POST -MaximumRedirection 3 -OutFile client_cert.pem
# Import certificate
Import-Certificate -FilePath client_cert.pem -CertStoreLocation Cert:\LocalMachine\My
# Set up IPSec VPN tunnel
Remove-VpnConnection -AllUserConnection -Force k-space
Add-VpnConnection -Name k-space -ServerAddress guests.k-space.ee -SplitTunneling -PassThru -TunnelType ikev2 -AllUserConnection -AuthenticationMethod MachineCertificate
Set-VpnConnectionIPsecConfiguration -ConnectionName k-space -AuthenticationTransformConstants SHA256128 -CipherTransformConstants AES256 -EncryptionMethod AES256 -IntegrityCheckMethod SHA384 -PfsGroup PFS24 -DHGroup Group24 -PassThru -AllUserConnection -Force</code></pre>
</div>
<h5>UNIX & UNIX-like</h5>
<p>On other UNIX-like machines generate key pair and submit the signing request using OpenSSL and cURL:</p>
<div class="highlight">
<pre class="code"><code>NAME=$(hostname);
openssl genrsa -out client_key.pem 2048;
openssl req -new -sha256 -key client_key.pem -out client_req.pem -subj "/CN=$NAME";
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>
</div>
<h5>OpenVPN gateway on OpenWrt/LEDE router</h5>
<p>First enroll certificates:</p>
<div class="highlight">
<pre class="code"><code># Derive FQDN from WAN interface's reverse DNS record
FQDN=$(nslookup $(uci get network.wan.ipaddr) | grep "name =" | head -n1 | cut -d "=" -f 2 | xargs)
mkdir -p /etc/certidude/authority/{{ window.location.hostname }}; \
grep -c certidude /etc/sysupgrade.conf || echo /etc/certidude >> /etc/sysupgrade.conf; \
curl -f http://{{ window.location.hostname }}/api/certificate/ -o /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem; \
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" \
--data-binary @/etc/certidude/authority/{{ window.location.hostname }}/server_req.pem \
-o /etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem \
http://{{ window.location.hostname }}/api/request/?wait=yes</code></pre>
</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 %}
<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>
<ul>
{% for name, title, filename in session.authority.builder.profiles %}
<li><a href="/api/build/{{ name }}/{{ filename }}">{{ title }}</a></li>
{% endfor %}
</ul>
{% endif %}
<h5>SCEP</h5>
<p>Use following as the enrollment URL: http://{{ window.location.hostname }}/cgi-bin/pkiclient.exe</p>
<h5>Copy & paste</h5>
<p>Use whatever tools you have available on your platform to generate
keypair and just paste ASCII armored PEM file contents here and hit submit:</p>
<textarea id="request_body" style="width:100%; min-height: 10em;" placeholder="-----BEGIN CERTIFICATE REQUEST-----"></textarea>
</div>
<div class="modal-footer">
<div class="btn-group">
<button type="button" onclick="onSubmitRequest();" class="btn btn-primary"><i class="fa fa-upload"></i> Submit</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal"><i class="fa fa-ban"></i> Close</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="revocation_list_modal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Revocation lists</h4>
</div>
<div class="modal-body">
<p>To fetch <a href="http://{{window.location.hostname}}/api/revoked/">certificate revocation list</a>:</p>
<pre><code>curl http://{{window.location.hostname}}/api/revoked/ > crl.der
curl http://{{window.location.hostname}}/api/revoked/ -L -H "Accept: application/x-pem-file"
curl http://{{window.location.hostname}}/api/revoked/?wait=yes -L -H "Accept: application/x-pem-file" > crl.pem</code></pre>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<section id="about">
<h2>{{ session.user.gn }} {{ session.user.sn }} ({{session.user.name }}) settings</h2>
<p title="Bundles are mainly intended for Android and iOS users">
Click <button id="enroll">here</button> to generate Android or iOS bundle for current user account.</p>
<p>Mails will be sent to: {{ session.user.mail }}</p>
{% if session.authority %}
<h2>Authority certificate</h2>
<p>Several things are hardcoded into the <a href="/api/certificate">certificate</a> and
as such require complete reset of X509 infrastructure if some of them needs to be changed.</p>
<h2>Authority settings</h2>
<p>These can be reconfigured via /etc/certidude/server.conf on the server.</p>
{% if session.authority.mailer %}
<p>Mails will appear from: {{ session.authority.mailer.name }} &lt;{{ session.authority.mailer.address }}&gt;</p>
{% else %}
<p>E-mail disabled</p>
{% endif %}
<p>User enrollment:
{% if session.authority.user_enrollment_allowed %}
{% if session.authority.user_multiple_certificates %}
multiple
{% else %}
single
{% endif %}
allowed
{% else %}
forbidden
{% endif %}
</p>
<p>Machine enrollment:
{% if session.authority.machine_enrollment_allowed %}
allowed
{% else %}
forbidden
{% endif %}
</p>
<p>Certificate attributes:</p>
<ul>
<li>Server certificate lifetime: {{ session.authority.signature.server_certificate_lifetime }} days</li>
<li>Client certificate lifetime: {{ session.authority.signature.client_certificate_lifetime }} days</li>
<li>Revocation list lifetime: {{ session.authority.signature.revocation_list_lifetime }} seconds</li>
</ul>
<p>Authenticated users allowed from:
{% if not session.authority.user_subnets %}
nowhere</p>
{% elif "0.0.0.0/0" in session.authority.user_subnets %}
anywhere</p>
{% else %}
</p>
<ul>
{% for i in session.authority.user_subnets %}
<li>{{ i }}</li>
{% endfor %}
</ul>
{% endif %}
<p>Authority administration is allowed from:
{% if not session.authority.admin_subnets %}
nowhere</p>
{% elif "0.0.0.0/0" in session.authority.admin_subnets %}
anywhere</p>
{% else %}
<ul>
{% for subnet in session.authority.admin_subnets %}
<li>{{ subnet }}</li>
{% endfor %}
</ul>
{% endif %}
<p>Authority administration allowed for:</p>
<ul>
{% for user in session.authority.admin_users %}
<li><a href="mailto:{{ user.mail}}">{{ user.given_name }} {{user.surname }}</a></li>
{% endfor %}
</ul>
</section>
{% else %}
<p>Here you can renew your certificates</p>
{% endif %}
{% set s = session.certificate.identity %}
<div class="row">
<div class="col-sm-6">
<h1>Signed certificates</h1>
<p>Following certificates have been signed:</p>
<div id="signed_certificates">
{% for certificate in session.authority.signed | sort(attribute="signed", reverse=true) %}
{% include "views/signed.html" %}
{% endfor %}
</div>
</div>
<div class="col-sm-6">
<h1>Tokens</h1>
<p>Tokens allow enrolling smartphones and third party devices.</p>
<ul>
<li>You can issue yourself a token to be used on a mobile device</li>
<li>Enter username to issue a token to issue a token for another user</li>
<li>Enter e-mail address to issue a token to guest users outside domain</li>
</ul>
<p>
<div class="input-group">
<input id="token_username" name="username" type="text" class="form-control" placeholder="Username" aria-describedby="sizing-addon2">
<input id="token_mail" name="mail" type="mail" class="form-control" placeholder="Optional e-mail" aria-describedby="sizing-addon2">
<span class="input-group-btn">
<button class="btn btn-secondary" type="button" onClick="onSendToken();"><i class="fa fa-send"></i> Send token</button>
</span>
</div>
</p>
<div id="token_qrcode"></div>
{% if session.authority %}
<h1>Pending requests</h1>
<p>Use Certidude client to apply for a certificate.
{% if not session.authority.request_subnets %}
Request submission disabled.
{% elif "0.0.0.0/0" in session.authority.request_subnets %}
Request submission is enabled.
{% else %}
Request submission allowed from
{% for subnet in session.authority.request_subnets %}{{ subnet }},{% endfor %}.
{% endif %}
{# if session.request_submission_allowed #}
See <a href="#request_submission_modal" data-toggle="modal">here</a> for more information on manual signing request upload.
{# endif #}
{% if session.authority.autosign_subnets %}
{% if "0.0.0.0/0" in session.authority.autosign_subnets %}
All requests are automatically signed.
{% else %}
Requests from
{% for subnet in session.authority.autosign_subnets %}
{{ subnet }},
{% endfor %}
are automatically signed.
{% endif %}
{% endif %}
</p>
<div id="pending_requests">
{% for request in session.authority.requests | sort(attribute="submitted", reverse=true) %}
{% include "views/request.html" %}
{% endfor %}
</div>
<p><h1>Revoked certificates</h1></p>
<p>Following certificates have been revoked,for more information click
<a href="#revocation_list_modal" data-toggle="modal">here</a>.</p>
{% for certificate in session.authority.revoked | sort(attribute="revoked", reverse=true) %}
{% include "views/revoked.html" %}
{% endfor %}
</div>
</div>
<section id="config">
</section>
{% endif %}