Implemented essential functionality
12
certidude/templates/client-to-site.ovpn
Normal file
@@ -0,0 +1,12 @@
|
||||
client
|
||||
remote {{remote}}
|
||||
proto {{proto}}
|
||||
dev tap0
|
||||
nobind
|
||||
key {{key_path}}
|
||||
cert {{certificate_path}}
|
||||
ca {{authority_path}}
|
||||
comp-lzo
|
||||
user nobody
|
||||
group nogroup
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="48px" height="48px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
width="32px" height="32px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<path id="certificate-15" d="M374.021,384.08c-4.527,29.103-16.648,55.725-36.043,77.92c-1.125-7.912-4.359-15.591-7.428-21.727
|
||||
c-7.023,3.705-15.439,5.666-22.799,5.666c-1.559,0-3.102-0.084-4.543-0.268c20.586-21.459,30.746-43.688,33.729-73.294
|
||||
c4.828,1.341,10.697,2.046,18.072,2.046C362.119,379.285,364.918,382.319,374.021,384.08z M457.709,445.672
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
21
certidude/templates/iconmonstr-email-2-icon.svg
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<!-- The icon can be used freely in both personal and commercial projects with no attribution required, but always appreciated.
|
||||
You may NOT sub-license, resell, rent, redistribute or otherwise transfer the icon without express written permission from iconmonstr.com -->
|
||||
|
||||
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
|
||||
width="32px" height="32px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
|
||||
|
||||
<path id="email-2-icon" d="M49.744,103.407v305.186H50.1h411.156h1V103.407H49.744z M415.533,138.407L255.947,260.465
|
||||
|
||||
L96.473,138.407H415.533z M84.744,173.506l85.504,65.441L84.744,324.45V173.506z M85.1,373.593l113.186-113.186l57.654,44.127
|
||||
|
||||
l57.375-43.882l112.941,112.94H85.1z M427.256,325.097l-85.896-85.896l85.896-65.695V325.097z"/>
|
||||
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 982 B |
11
certidude/templates/iconmonstr-flag-3-icon.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- License Agreement at http://iconmonstr.com/license/ -->
|
||||
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="32px" height="32px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
|
||||
<path id="flag-3-icon" d="M120.204,462H74.085V50h46.119V462z M437.915,80.746c0,0-29.079,25.642-67.324,25.642
|
||||
c-60.271,0-61.627-51.923-131.596-51.923c-37.832,0-73.106,17.577-88.045,30.381c0,12.64,0,216.762,0,216.762
|
||||
c21.204-14.696,53.426-30.144,88.286-30.144c66.08,0,75.343,49.388,134.242,49.388c38.042,0,64.437-24.369,64.437-24.369V80.746z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 786 B |
15
certidude/templates/iconmonstr-key-2-icon.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- The icon can be used freely in both personal and commercial projects with no attribution required, but always appreciated.
|
||||
You may NOT sub-license, resell, rent, redistribute or otherwise transfer the icon without express written permission from iconmonstr.com -->
|
||||
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="32px" height="32px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
|
||||
<path id="key-2-icon" stroke="#000000" stroke-miterlimit="10" d="M286.529,325.486l-45.314,45.314h-43.873l0.002,43.872
|
||||
l-45.746-0.001v41.345l-100.004-0.001l150.078-150.076c-4.578-4.686-10.061-11.391-13.691-17.423L50,426.498v-40.939
|
||||
l145.736-145.736C212.174,278.996,244.713,310.705,286.529,325.486z M425.646,92.339c48.473,48.473,48.471,127.064-0.002,175.535
|
||||
c-48.477,48.476-127.061,48.476-175.537,0.001c-48.473-48.472-48.475-127.062,0-175.537
|
||||
C298.58,43.865,377.172,43.865,425.646,92.339z M400.73,117.165c-12.023-12.021-31.516-12.021-43.537,0
|
||||
c-12.021,12.022-12.021,31.517,0,43.538s31.514,12.021,43.537-0.001C412.754,148.68,412.75,129.188,400.73,117.165z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -5,7 +5,7 @@ You may NOT sub-license, resell, rent, redistribute or otherwise transfer the ic
|
||||
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="48px" height="48px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
|
||||
width="32px" height="32px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
|
||||
<path id="time-13-icon" d="M361.629,172.206c15.555-19.627,24.121-44.229,24.121-69.273V50h-259.5v52.933
|
||||
c0,25.044,8.566,49.646,24.121,69.273l50.056,63.166c9.206,11.617,9.271,27.895,0.159,39.584l-50.768,65.13
|
||||
c-15.198,19.497-23.568,43.85-23.568,68.571V462h259.5v-53.343c0-24.722-8.37-49.073-23.567-68.571l-50.769-65.13
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -9,17 +9,22 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>Certidude server</title>
|
||||
<style type="text/css">
|
||||
svg {
|
||||
position: relative;
|
||||
top: 0.5em;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
margin: 1em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
button, .button {
|
||||
color: #000;
|
||||
float: right;
|
||||
@@ -31,50 +36,53 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monospace {
|
||||
font-family: 'Ubuntu Mono', monospace;
|
||||
font-size: 80%;
|
||||
button:disabled, .button:disabled {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
|
||||
.monospace {
|
||||
font-family: 'Ubuntu Mono', courier, monospace;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: block;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #44c;
|
||||
}
|
||||
|
||||
|
||||
footer a {
|
||||
color: #aaf;
|
||||
}
|
||||
|
||||
|
||||
html,body {
|
||||
margin: 0;
|
||||
padding: 0 0 1em 0;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
background: #222;
|
||||
background-image: url('http://fc00.deviantart.net/fs71/i/2013/078/9/6/free_hexa_pattern_cc0_by_black_light_studio-d4ig12f.png');
|
||||
background-position: center;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
|
||||
.comment {
|
||||
color: #aaf;
|
||||
}
|
||||
|
||||
|
||||
table th, table td {
|
||||
border: 1px solid #ccc;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
|
||||
h1, h2, th {
|
||||
font-family: 'Gentium';
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 22pt;
|
||||
@@ -83,17 +91,17 @@
|
||||
h2 {
|
||||
font-size: 18pt;
|
||||
}
|
||||
|
||||
|
||||
h2 svg {
|
||||
position: relative;
|
||||
top: 16px;
|
||||
}
|
||||
|
||||
|
||||
p, td, footer, li, button {
|
||||
font-family: 'PT Sans Narrow';
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
border: 1px solid #000;
|
||||
@@ -104,10 +112,10 @@
|
||||
border-radius: 6px;
|
||||
margin: 0 0;
|
||||
}
|
||||
|
||||
#container {
|
||||
|
||||
margin: 1em;
|
||||
#container {
|
||||
max-width: 60em;
|
||||
margin: 1em auto;
|
||||
background: #fff;
|
||||
padding: 1em;
|
||||
border-style: solid;
|
||||
@@ -115,7 +123,7 @@
|
||||
border-color: #aaa;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
|
||||
li {
|
||||
margin: 4px 0;
|
||||
padding: 4px 0;
|
||||
@@ -123,14 +131,7 @@
|
||||
border-top: 1px dashed #ccc;
|
||||
}
|
||||
|
||||
li .details {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
li:hover .details {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -140,18 +141,37 @@
|
||||
|
||||
{% set s = authority.certificate.subject %}
|
||||
|
||||
<p>To submit new certificate signing request:</p>
|
||||
<!--
|
||||
<p>To submit new certificate signing request first set common name, eg:</p>
|
||||
<pre>
|
||||
export CN=$(hostname)
|
||||
openssl genrsa -out $CN.key 4096
|
||||
openssl req -new -sha256 -key $CN.key -out $CN.csr -subj "{% if s.C %}/C={{ s.C}}{% endif %}{% if s.ST %}/ST={{ s.ST}}{% endif %}{% if s.L %}/L={{s.L}}{% endif %}{% if s.O %}/O={{ s.O}}{% endif %}{% if s.OU %}/OU={{ s.OU}}{% endif %}/CN=$CN"
|
||||
curl -H "Content-Type: application/pkcs10" -X POST -d "$(cat $CN.csr)" {{ request.url }}/request/
|
||||
</pre>
|
||||
|
||||
<p>After signing the request</p>
|
||||
<p>Generate key and submit using standard shell tools:</p>
|
||||
|
||||
<pre>
|
||||
curl -f {{ request.url }}/signed/$CN > $CN.crt
|
||||
curl {{request.url}}/certificate/ > ca.crt
|
||||
openssl genrsa -out $CN.key 4096
|
||||
openssl req -new -sha256 -key $CN.key -out $CN.csr -subj "{% if s.C %}/C={{s.C}}{% endif %}{% if s.ST %}/ST={{s.ST}}{% endif %}{% if s.L %}/L={{s.L}}{% endif %}{% if s.O %}/O={{s.O}}{% endif %}{% if s.OU %}/OU={{s.OU}}{% endif %}/CN=$CN"
|
||||
wget --header "Content-Type: application/pkcs10" --post-data="$(cat $CN.csr)" http://localhost:9090/api/buujaa/request/?autosign=1\&wait=30 -O $CN.crt
|
||||
openssl verify -CAfile ca.crt $CN.crt
|
||||
</pre>
|
||||
-->
|
||||
|
||||
<p>Assuming you have Certidude installed</p>
|
||||
|
||||
<pre>
|
||||
certidude setup client {{request.url}}
|
||||
</pre>
|
||||
|
||||
<p>To set up OpenVPN server</p>
|
||||
<pre>
|
||||
certidude setup openvpn server {{request.url}}
|
||||
</pre>
|
||||
|
||||
<p>Or to set up OpenVPN client</p>
|
||||
<pre>
|
||||
certidude setup openvpn client {{request.url}}
|
||||
</pre>
|
||||
|
||||
<h1>Pending requests</h1>
|
||||
@@ -159,46 +179,123 @@ curl -f {{ request.url }}/signed/$CN > $CN.crt
|
||||
<ul>
|
||||
{% for j in authority.get_requests() %}
|
||||
<li>
|
||||
{% include 'iconmonstr-time-13-icon.svg' %}
|
||||
<span class="monospace">{{ j.get_dn() }}</span>
|
||||
<span class="monospace details" title="SHA-1 of public key">{{ j.get_pubkey_fingerprint().upper() }}</span>
|
||||
<a class="button" href="/api/{{authority.slug}}/request/{{j.common_name}}/">Fetch</a>
|
||||
{% if j.signable %}
|
||||
<button onClick="javascript:$.ajax({url:'/api/{{authority.slug}}/request/{{j.common_name}}/',type:'patch'});">Sign</button>
|
||||
{% else %}
|
||||
<button title="Please use certidude command-line utility to sign unusual requests" disabled>Sign</button>
|
||||
{% endif %}
|
||||
<button onClick="javascript:$.ajax({url:'/api/{{authority.slug}}/request/{{j.common_name}}/',type:'delete'});">Delete</button>
|
||||
|
||||
<a class="button" href="/api/{{authority.slug}}/request/{{j.subject.CN}}/">Fetch</a>
|
||||
<button onClick="javascript:$.ajax({url:'/api/{{authority.slug}}/request/{{j.subject.CN}}/',type:'patch'});">Sign</button>
|
||||
<button>Delete</button>
|
||||
<br/>
|
||||
<span>{{ j.key_length() }}-bit {{ j.key_type() }}</span>
|
||||
|
||||
<div class="monospace">
|
||||
{% include 'iconmonstr-certificate-15-icon.svg' %}
|
||||
{{j.distinguished_name}}
|
||||
</div>
|
||||
|
||||
{% if j.email_address %}
|
||||
<div class="email">{% include 'iconmonstr-email-2-icon.svg' %} {{ j.email_address }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="monospace">
|
||||
{% include 'iconmonstr-key-2-icon.svg' %}
|
||||
<span title="SHA-1 of public key">
|
||||
{{ j.fingerprint() }}
|
||||
</span>
|
||||
{{ j.key_length }}-bit
|
||||
{{ j.key_type }}
|
||||
</div>
|
||||
|
||||
{% set key_usage = j.key_usage %}
|
||||
{% if key_usage %}
|
||||
<div>
|
||||
{% include 'iconmonstr-flag-3-icon.svg' %}
|
||||
{{j.key_usage}}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</li>
|
||||
{% else %}
|
||||
<li>Great job! No certificate signing requests to sign.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h1>Signed certificates</h1>
|
||||
|
||||
|
||||
|
||||
<p>You can fetch a certificate by <i>common name</i> signing the request</p>
|
||||
|
||||
<pre>
|
||||
curl -f {{request.url}}/signed/$CN > $CN.crt
|
||||
</pre>
|
||||
|
||||
<ul>
|
||||
{% for j in authority.get_signed() | sort | reverse %}
|
||||
<li>
|
||||
|
||||
{% include 'iconmonstr-certificate-15-icon.svg' %}
|
||||
{{ j.serial}} <span class="monospace">{{ j.get_dn() }}</span>
|
||||
<span class="monospace details" title="SHA-1 of public key">{{ j.get_pubkey_fingerprint() }}</span>
|
||||
|
||||
{{ j.key_length() }}-bit {{ j.key_type() }}
|
||||
<a class="button" href="/api/{{authority.slug}}/signed/{{j.subject.CN}}/">Fetch</a>
|
||||
<button onClick="javascript:$.ajax({url:'/api/{{authority.slug}}/signed/{{j.subject.CN}}/',type:'delete'});">Revoke</button>
|
||||
|
||||
{% for key, value in j.get_extensions() %}
|
||||
{{key}}={{value}},
|
||||
{% endfor %}
|
||||
|
||||
<div class="monospace">
|
||||
{% include 'iconmonstr-certificate-15-icon.svg' %}
|
||||
{{j.distinguished_name}}
|
||||
</div>
|
||||
|
||||
{% if j.email_address %}
|
||||
<div class="email">{% include 'iconmonstr-email-2-icon.svg' %} {{ j.email_address }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="monospace">
|
||||
{% include 'iconmonstr-key-2-icon.svg' %}
|
||||
<span title="SHA-1 of public key">
|
||||
{{ j.fingerprint() }}
|
||||
</span>
|
||||
{{ j.key_length }}-bit
|
||||
{{ j.key_type }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% include 'iconmonstr-flag-3-icon.svg' %}
|
||||
{{j.key_usage}}
|
||||
</div>
|
||||
|
||||
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h1>Revoked certificates</h1>
|
||||
|
||||
<p>To fetch certificate revocation list:</p>
|
||||
<pre>
|
||||
curl {{request.url}}/revoked/ | openssl crl -text -noout
|
||||
</pre>
|
||||
<!--
|
||||
<p>To perform online certificate status request</p>
|
||||
|
||||
<pre>
|
||||
curl {{request.url}}/certificate/ > ca.pem
|
||||
openssl ocsp -issuer ca.pem -CAfile ca.pem -url {{request.url}}/ocsp/ -serial 0x
|
||||
</pre>
|
||||
-->
|
||||
<ul>
|
||||
{% for serial, reason, timestamp in authority.get_revoked() %}
|
||||
<li>{{ serial}} {{ reason }} {{ timestamp}} </li>
|
||||
{% for j in authority.get_revoked() %}
|
||||
<li>
|
||||
{{j.changed}}
|
||||
{{j.serial_number}} <span class="monospace">{{j.distinguished_name}}</span>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>Great job! No certificate signing requests to sign.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<footer>
|
||||
<a href="http://github.com/laurivosandi/certidude">Certidude</a> by
|
||||
<a href="http://github.com/laurivosandi/">Lauri Võsandi</a>
|
||||
</footer>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
32
certidude/templates/openssl.cnf
Normal file
@@ -0,0 +1,32 @@
|
||||
[CA_{{slug}}]
|
||||
default_days = 1825
|
||||
dir = {{directory}}
|
||||
private_key = $dir/ca_key.pem
|
||||
certificate = $dir/ca_crt.pem
|
||||
new_certs_dir = $dir/requests/
|
||||
revoked_certs_dir = $dir/revoked/
|
||||
certs = $dir/signed/
|
||||
crl = $dir/ca_crl.pem
|
||||
serial = $dir/serial
|
||||
{% if crl_distribution_points %}
|
||||
crlDistributionPoints = {{crl_distribution_points}}{% endif %}
|
||||
{% if email_address %}
|
||||
emailAddress = {{email_address}}{% endif %}
|
||||
x509_extensions = {{slug}}_cert
|
||||
policy = poliy_{{slug}}
|
||||
autosign_whitelist = 127.
|
||||
inbox = {{inbox}}
|
||||
outbox = {{outbox}}
|
||||
|
||||
[policy_{{slug}}]
|
||||
countryName = match
|
||||
stateOrProvinceName = match
|
||||
organizationName = match
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[{{slug}}_cert]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation,digitalSignature,keyEncipherment
|
||||
extendedKeyUsage = clientAuth
|
||||
16
certidude/templates/site-to-client.ovpn
Normal file
@@ -0,0 +1,16 @@
|
||||
mode server
|
||||
tls-server
|
||||
proto {{proto}}
|
||||
port {{port}}
|
||||
dev tap0
|
||||
local {{local}}
|
||||
key {{key_path}}
|
||||
cert {{certificate_path}}
|
||||
ca {{authority_path}}
|
||||
comp-lzo
|
||||
user nobody
|
||||
group nogroup
|
||||
ifconfig-pool-persist /tmp/openvpn-leases.txt
|
||||
ifconfig {{subnet_first}} {{subnet.netmask}}
|
||||
server-bridge {{subnet_first}} {{subnet.netmask}} {{subnet_second}} {{subnet_last}}
|
||||
|
||||