Added preliminary interfacing with updown scripts
| @@ -7,7 +7,7 @@ | ||||
| <p>Authority administration is allowed from: {% if authority.admin_subnets %}{% for i in authority.admin_subnets %}{{ i }} {% endfor %}{% else %}anywhere{% endif %} | ||||
| <p>Authority administration allowed for: {% for i in authority.admin_users %}{{ i }} {% endfor %}</p> | ||||
|  | ||||
| {% set s = authority.certificate.subject %} | ||||
| {% set s = authority.certificate.identity %} | ||||
|  | ||||
| <h1>Pending requests</h1> | ||||
|  | ||||
| @@ -23,21 +23,21 @@ | ||||
|  | ||||
| <ul id="signed_certificates"> | ||||
|     {% for j in authority.signed | sort | reverse %} | ||||
|         <li id="certificate_{{ j.sha256sum }}" data-dn="{{ j.subject }}"> | ||||
|             <a class="button" href="/api/{{authority.slug}}/signed/{{j.subject}}/">Fetch</a> | ||||
|             <button onClick="javascript:$.ajax({url:'/api/{{authority.slug}}/signed/{{j.subject.CN}}/',type:'delete'});">Revoke</button> | ||||
|         <li id="certificate_{{ j.sha256sum }}" data-dn="{{ j.identity }}"> | ||||
|             <a class="button icon download" href="/api/ca/{{authority.slug}}/signed/{{j.common_name}}/">Fetch</a> | ||||
|             <button class="icon revoke" onClick="javascript:$(this).addClass('busy');$.ajax({url:'/api/ca/{{authority.slug}}/signed/{{j.common_name}}/',type:'delete'});">Revoke</button> | ||||
|  | ||||
|             <div class="monospace"> | ||||
|             {% include 'iconmonstr-certificate-15-icon.svg' %} | ||||
|             {{j.subject}} | ||||
|             {% include 'img/iconmonstr-certificate-15-icon.svg' %} | ||||
|             {{j.identity}} | ||||
|             </div> | ||||
|  | ||||
|             {% if j.email_address %} | ||||
|             <div class="email">{% include 'iconmonstr-email-2-icon.svg' %} {{ j.email_address }}</div> | ||||
|             <div class="email">{% include 'img/iconmonstr-email-2-icon.svg' %} {{ j.email_address }}</div> | ||||
|             {% endif %} | ||||
|  | ||||
|             <div class="monospace"> | ||||
|             {% include 'iconmonstr-key-2-icon.svg' %} | ||||
|             {% include 'img/iconmonstr-key-2-icon.svg' %} | ||||
|             <span title="SHA-256 of public key"> | ||||
|             {{ j.sha256sum }} | ||||
|             </span> | ||||
| @@ -46,13 +46,12 @@ | ||||
|             </div> | ||||
|  | ||||
|             <div> | ||||
|             {% include 'iconmonstr-flag-3-icon.svg' %} | ||||
|             {% include 'img/iconmonstr-flag-3-icon.svg' %} | ||||
|             {{j.key_usage}} | ||||
|             </div> | ||||
|  | ||||
|  | ||||
|             <div class="status"> | ||||
|                 {% include 'status.html' %} | ||||
|             {% include 'status.html' %} | ||||
|             </div> | ||||
|         </li> | ||||
| 	{% endfor %} | ||||
| @@ -76,7 +75,7 @@ openssl ocsp -issuer authority.pem -CAfile authority.pem -url {{request.url}}/oc | ||||
|     {% for j in authority.revoked %} | ||||
|         <li id="certificate_{{ j.sha256sum }}"> | ||||
|             {{j.changed}} | ||||
|             {{j.serial_number}} <span class="monospace">{{j.distinguished_name}}</span> | ||||
|             {{j.serial_number}} <span class="monospace">{{j.identity}}</span> | ||||
|         </li> | ||||
|     {% else %} | ||||
|         <li>Great job! No certificate signing requests to sign.</li> | ||||
|   | ||||
| @@ -42,7 +42,8 @@ button, .button { | ||||
|     background-color: #eee; | ||||
|     border-radius: 6px; | ||||
|     margin: 2px; | ||||
|     padding: 4px 8px; | ||||
|     padding: 6px 12px; | ||||
|     background-position: 6px; | ||||
|     box-sizing: border-box; | ||||
| } | ||||
|  | ||||
| @@ -140,3 +141,20 @@ li { | ||||
|     clear: both; | ||||
|     border-top: 1px dashed #ccc; | ||||
| } | ||||
|  | ||||
| .icon{ | ||||
|     background-size: 24px; | ||||
|     padding-left: 36px; | ||||
|     background-repeat: no-repeat; | ||||
|     display: block; | ||||
|     vertical-align: text-bottom; | ||||
|     text-decoration: none; | ||||
| } | ||||
|  | ||||
|  | ||||
| .icon.revoke { background-image: url("../img/iconmonstr-x-mark-5-icon.svg"); } | ||||
| .icon.download { background-image: url("../img/iconmonstr-download-12-icon.svg"); } | ||||
| .icon.sign { background-image: url("../img/iconmonstr-pen-10-icon.svg"); } | ||||
|  | ||||
| /* Make sure this is the last one */ | ||||
| .icon.busy{background-image:url("https://software.opensuse.org/assets/ajax-loader-ea46060b6c9f42822a3d58d075c83ea2.gif");} | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								certidude/static/img/ajax-loader.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 5.1 KiB | 
| Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										29
									
								
								certidude/static/img/iconmonstr-download-12-icon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,29 @@ | ||||
| <?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="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"> | ||||
|  | ||||
| <path id="download-12-icon" d="M462,246.575c0,44.318-35.928,80.246-80.246,80.246H331.58v-38.119 | ||||
|  | ||||
| 	c-0.998-43.379,40.92-44.379,59.67-46.379c-27.168-33.334-70.918-48.244-104.611-48.244c-66.546,0-108.17,39.104-108.17,104.808 | ||||
|  | ||||
| 	v27.935h-48.223C85.928,326.821,50,290.894,50,246.575c0-40.982,30.729-74.766,70.396-79.623 | ||||
|  | ||||
| 	c2.891-42.287,49.035-66.355,85.217-45.898c19.236-30.605,53.297-50.953,92.115-50.953c57.107,0,103.932,44.033,108.375,100 | ||||
|  | ||||
| 	C438.516,180.413,462,210.747,462,246.575z M301.58,288.702c0-30.761,6.053-48.484,31.926-56.837 | ||||
|  | ||||
| 	c-20.066-8.452-125.037-28.815-125.037,67.021c0,32.187,0,58.909,0,58.909h-37.408l83.963,84.104l83.965-84.104H301.58 | ||||
|  | ||||
| 	C301.58,357.796,301.58,315.59,301.58,288.702z"/> | ||||
|  | ||||
| </svg> | ||||
|  | ||||
| After Width: | Height: | Size: 1.3 KiB | 
| Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 982 B | 
| Before Width: | Height: | Size: 786 B After Width: | Height: | Size: 786 B | 
| Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										13
									
								
								certidude/static/img/iconmonstr-pen-10-icon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,13 @@ | ||||
| <?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="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"> | ||||
| <path id="pen-10-icon" d="M244.558,199.493l67.827,67.826l-73.17,134.531c0,0-90.805,23.4-147.694,60.027l-14.185-14.182 | ||||
| 	l68.113-68.105c5.975-5.982,13.726-9.773,22.11-10.807c4.642-0.582,9.128-2.621,12.696-6.205c8.538-8.547,8.546-22.4-0.002-30.951 | ||||
| 	c-8.549-8.543-22.407-8.543-30.959-0.002c-3.573,3.572-5.623,8.061-6.199,12.693c-1.028,8.371-4.834,16.15-10.8,22.117 | ||||
| 	l-68.104,68.105L50,420.354c37.028-57.496,60.021-147.693,60.021-147.693L244.558,199.493z M315.896,50.122 | ||||
| 	c-22.784,44.143-53.014,100-53.014,100l98.872,98.869c0,0,55.909-30.086,100.246-52.766L315.896,50.122z"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1016 B | 
| Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										21
									
								
								certidude/static/img/iconmonstr-x-mark-5-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="x-mark-5-icon" d="M432.546,133.462L367.133,76.39L254.078,210.715L140.967,73.702l-61.513,65.068 | ||||
|  | ||||
| 	c33.791,43.885,78.146,89.797,123.688,132.465L82.993,413.987l19.865,22.629c29.251-20.31,87.839-65.578,150.312-120.092 | ||||
|  | ||||
| 	c63.662,55.812,122.861,101.336,151.301,121.773l21.438-19.443L303.804,270.95C352.439,225.709,399.308,177.442,432.546,133.462z"/> | ||||
|  | ||||
| </svg> | ||||
|  | ||||
| After Width: | Height: | Size: 1001 B | 
| @@ -20,14 +20,40 @@ $(document).ready(function() { | ||||
|                 success: function(authority, status, xhr) { | ||||
|                     console.info("Got CA:", authority); | ||||
|  | ||||
|                     console.info("Opening EventSource from:", "/api/ca/" + authority.slug); | ||||
|                     console.info("Opening EventSource from:", authority.event_channel); | ||||
|  | ||||
|                     var source = new EventSource("/api/" + authority.slug); | ||||
|                     var source = new EventSource(authority.event_channel); | ||||
|  | ||||
|                     source.onmessage = function(event) { | ||||
|                         console.log("Received server-sent event:", event); | ||||
|                     } | ||||
|  | ||||
|                     source.addEventListener("up-client", function(e) { | ||||
|                         console.log("Adding security association:" + e.data); | ||||
|                         var lease = JSON.parse(e.data); | ||||
|                         var $status = $("#signed_certificates [data-dn='" + lease.identity + "'] .status"); | ||||
|                         $status.html(nunjucks.render('status.html', { | ||||
|                             lease: { | ||||
|                                 address: lease.address, | ||||
|                                 identity: lease.identity, | ||||
|                                 acquired: new Date(), | ||||
|                                 released: null | ||||
|                             }})); | ||||
|                     }); | ||||
|  | ||||
|                     source.addEventListener("down-client", function(e) { | ||||
|                         console.log("Removing security association:" + e.data); | ||||
|                         var lease = JSON.parse(e.data); | ||||
|                         var $status = $("#signed_certificates [data-dn='" + lease.identity + "'] .status"); | ||||
|                         $status.html(nunjucks.render('status.html', { | ||||
|                             lease: { | ||||
|                                 address: lease.address, | ||||
|                                 identity: lease.identity, | ||||
|                                 acquired: null, | ||||
|                                 released: new Date() | ||||
|                             }})); | ||||
|                     }); | ||||
|  | ||||
|                     source.addEventListener("request_deleted", function(e) { | ||||
|                         console.log("Removing deleted request #" + e.data); | ||||
|                         $("#request_" + e.data).remove(); | ||||
| @@ -39,13 +65,13 @@ $(document).ready(function() { | ||||
|  | ||||
|                     source.addEventListener("request_signed", function(e) { | ||||
|                         console.log("Request signed:", e.data); | ||||
|                         $("#request_" + e.data).remove(); | ||||
|                         $("#request_" + e.data).slideUp("normal", function() { $(this).remove(); }); | ||||
|                         // TODO: Insert <li> to signed certs list | ||||
|                     }); | ||||
|  | ||||
|                     source.addEventListener("certificate_revoked", function(e) { | ||||
|                         console.log("Removing revoked certificate #" + e.data); | ||||
|                         $("#certificate_" + e.data).remove(); | ||||
|                         $("#certificate_" + e.data).slideUp("normal", function() { $(this).remove(); }); | ||||
|                     }); | ||||
|  | ||||
|                     $("#container").html(nunjucks.render('authority.html', { authority: authority, session: session })); | ||||
| @@ -57,7 +83,7 @@ $(document).ready(function() { | ||||
|                         success: function(leases, status, xhr) { | ||||
|                             console.info("Got leases:", leases); | ||||
|                             for (var j = 0; j < leases.length; j++) { | ||||
|                                 var $status = $("#signed_certificates [data-dn='" + leases[j].dn + "'] .status"); | ||||
|                                 var $status = $("#signed_certificates [data-dn='" + leases[j].identity + "'] .status"); | ||||
|                                 if (!$status.length) { | ||||
|                                     console.info("Detected rogue client:", leases[j]); | ||||
|                                     continue; | ||||
| @@ -65,7 +91,7 @@ $(document).ready(function() { | ||||
|                                 $status.html(nunjucks.render('status.html', { | ||||
|                                     lease: { | ||||
|                                         address: leases[j].address, | ||||
|                                         dn: leases[j].dn, | ||||
|                                         identity: leases[j].identity, | ||||
|                                         acquired: new Date(leases[j].acquired).toLocaleString(), | ||||
|                                         released: leases[j].released ? new Date(leases[j].released).toLocaleString() : null | ||||
|                                     }})); | ||||
|   | ||||
| @@ -1,25 +1,25 @@ | ||||
| <li id="request_{{ j.md5sum }}"> | ||||
|  | ||||
| <a class="button" href="/api/{{authority.slug}}/request/{{j.common_name}}/">Fetch</a> | ||||
| <a class="button icon download" href="/api/ca/{{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> | ||||
| <button class="icon sign" onClick="javascript:$(this).addClass('busy');$.ajax({url:'/api/ca/{{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> | ||||
| <button class="icon revoke" onClick="javascript:$(this).addClass('busy');$.ajax({url:'/api/ca/{{authority.slug}}/request/{{j.common_name}}/',type:'delete'});">Delete</button> | ||||
|  | ||||
|  | ||||
| <div class="monospace"> | ||||
| {% include 'iconmonstr-certificate-15-icon.svg' %} | ||||
| {{j.subject}} | ||||
| {% include 'img/iconmonstr-certificate-15-icon.svg' %} | ||||
| {{j.identity}} | ||||
| </div> | ||||
|  | ||||
| {% if j.email_address %} | ||||
| <div class="email">{% include 'iconmonstr-email-2-icon.svg' %} {{ j.email_address }}</div> | ||||
| <div class="email">{% include 'img/iconmonstr-email-2-icon.svg' %} {{ j.email_address }}</div> | ||||
| {% endif %} | ||||
|  | ||||
| <div class="monospace"> | ||||
| {% include 'iconmonstr-key-2-icon.svg' %} | ||||
| {% include 'img/iconmonstr-key-2-icon.svg' %} | ||||
| <span title="SHA-1 of public key"> | ||||
| {{ j.sha256sum }} | ||||
| </span> | ||||
| @@ -30,7 +30,7 @@ | ||||
| {% set key_usage = j.key_usage %} | ||||
| {% if key_usage %} | ||||
| <div> | ||||
| {% include 'iconmonstr-flag-3-icon.svg' %} | ||||
| {% include 'img/iconmonstr-flag-3-icon.svg' %} | ||||
| {{j.key_usage}} | ||||
| </div> | ||||
| {% endif %} | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <svg height="32" width="32"> | ||||
|     <circle cx="16" cy="16" r="13" stroke="black" stroke-width="3" fill="{% if lease %}{% if lease.released %}green{%else %}red{% endif %}{% else %}yellow{% endif %}" /> | ||||
|     <circle cx="16" cy="16" r="13" stroke="black" stroke-width="3" fill="{% if lease %}{% if lease.released %}red{%else %}green{% endif %}{% else %}yellow{% endif %}" /> | ||||
| </svg> | ||||
|  | ||||
| <span> | ||||
|   | ||||
| Before Width: | Height: | Size: 428 B After Width: | Height: | Size: 428 B |