123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- <h3><i class="ui lock icon"></i> TLS / SSL Certificates</h3>
- <p>Setup TLS cert for different domains of your reverse proxy server names</p>
- <div class="ui divider"></div>
- <h4>Default Certificates</h4>
- <small>When there are no matching certificate for the requested server name, reverse proxy router will always fallback to this one.<br>Note that you need both of them uploaded for it to fallback properly</small></p>
- <table class="ui very basic celled table">
- <thead>
- <tr><th>Key Type</th>
- <th>Exists</th>
- </tr></thead>
- <tbody>
- <tr>
- <td><i class="globe icon"></i> Default Public Key</td>
- <td id="pubkeyExists"></td>
- </tr>
- <tr>
- <td><i class="lock icon"></i> Default Private Key</td>
- <td id="prikeyExists"></td>
- </tr>
- </tbody>
- </table>
- <button class="ui button" onclick="uploadPublicKey();"><i class="globe icon"></i> Upload Public Key</button>
- <button class="ui black button" onclick="uploadPrivateKey();"><i class="lock icon"></i> Upload Private Key</button>
- <div class="ui divider"></div>
- <h4>Sub-domain Certificates</h4>
- <p>Provide certificates for multiple domains reverse proxy</p>
- <div class="ui fluid form">
- <div class="three fields">
- <div class="field">
- <label>Server Name (Domain)</label>
- <input type="text" id="certdomain" placeholder="example.com / blog.example.com">
- </div>
- <div class="field">
- <label>Public Key</label>
- <input type="file" id="pubkeySelector" onchange="handleFileSelect(event, 'pub')">
- </div>
- <div class="field">
- <label>Private Key</label>
- <input type="file" id="prikeySelector" onchange="handleFileSelect(event, 'pri')">
- </div>
- </div>
- <button class="ui teal button" onclick="handleDomainUploadByKeypress();"><i class="ui upload icon"></i> Upload</button>
- </div>
- <div id="certUploadSuccMsg" class="ui green message" style="display:none;">
- <i class="ui checkmark icon"></i> Certificate for domain <span id="certUploadingDomain"></span> uploaded.
- </div>
- <br>
- <div>
- <table class="ui very basic celled table">
- <thead>
- <tr><th>Domain</th>
- <th>Last Update</th>
- <th>Remove</th>
- </tr></thead>
- <tbody id="certifiedDomainList">
- </tbody>
- </table>
- <button class="ui green basic button" onclick="initManagedDomainCertificateList();"><i class="refresh icon"></i> Refresh List</button>
- </div>
- <div class="ui message">
- <h4><i class="info circle icon"></i> Sub-domain Certificates</h4>
- If you have 3rd or even 4th level subdomains like <code>blog.example.com</code> or <code>en.blog.example.com</code> ,
- depending on your certificates coverage, you might need to setup them one by one (i.e. having two seperate certificate for <code>a.example.com</code> and <code>b.example.com</code>).<br>
- If you have a wildcard certificate that covers <code>*.example.com</code>, you can just enter <code>example.com</code> as server name in the form below to add a certificate.
- </div>
- <script>
- var uploadPendingPublicKey = undefined;
- var uploadPendingPrivateKey = undefined;
- //Delete the certificate by its domain
- function deleteCertificate(domain){
- if (confirm("Confirm delete certificate for " + domain + " ?")){
- $.ajax({
- url: "/cert/delete",
- method: "POST",
- data: {domain: domain},
- success: function(data){
- if (data.error != undefined){
- alert(data.error);
- }else{
- initManagedDomainCertificateList();
- }
- }
- });
- }
-
- }
- //List the stored certificates
- function initManagedDomainCertificateList(){
- $("#certifiedDomainList").html("");
- $.get("/cert/list?date=true", function(data){
- if (data.error != undefined){
- alert(data.error);
- }else{
- data.forEach(entry => {
- $("#certifiedDomainList").append(`<tr>
- <td>${entry.Domain}</td>
- <td>${entry.LastModifiedDate}</td>
- <td><button title="Delete key-pair" class="ui mini basic red icon button" onclick="deleteCertificate('${entry.Domain}');"><i class="ui red trash icon"></i></button></td>
- </tr>`);
- })
- }
- })
- }
- initManagedDomainCertificateList();
- function handleDomainUploadByKeypress(){
- handleDomainKeysUpload(function(){
- $("#certUploadingDomain").text($("#certdomain").val().trim());
- //After uploaded, reset the file selector
- document.getElementById('pubkeySelector').value = '';
- document.getElementById('prikeySelector').value = '';
- document.getElementById('certdomain').value = '';
- uploadPendingPublicKey = undefined;
- uploadPendingPrivateKey = undefined;
- //Show succ
- $("#certUploadSuccMsg").stop().finish().slideDown("fast").delay(3000).slideUp("fast");
- initManagedDomainCertificateList();
- });
- }
- //Handle domain keys upload
- function handleDomainKeysUpload(callback=undefined){
- let domain = $("#certdomain").val();
- if (domain.trim() == ""){
- alert("Missing domain.");
- return;
- }
- if (uploadPendingPublicKey && uploadPendingPrivateKey && typeof uploadPendingPublicKey === 'object' && typeof uploadPendingPrivateKey === 'object') {
- const publicKeyForm = new FormData();
- publicKeyForm.append('file', uploadPendingPublicKey, 'publicKey');
- const privateKeyForm = new FormData();
- privateKeyForm.append('file', uploadPendingPrivateKey, 'privateKey');
- const publicKeyRequest = new XMLHttpRequest();
- publicKeyRequest.open('POST', '/cert/upload?ktype=pub&domain=' + domain);
- publicKeyRequest.onreadystatechange = function() {
- if (publicKeyRequest.readyState === XMLHttpRequest.DONE) {
- if (publicKeyRequest.status !== 200) {
- alert('Error uploading public key: ' + publicKeyRequest.statusText);
- }
- if (callback != undefined){
- callback();
- }
-
- }
- };
- publicKeyRequest.send(publicKeyForm);
- const privateKeyRequest = new XMLHttpRequest();
- privateKeyRequest.open('POST', '/cert/upload?ktype=pri&domain=' + domain);
- privateKeyRequest.onreadystatechange = function() {
- if (privateKeyRequest.readyState === XMLHttpRequest.DONE) {
- if (privateKeyRequest.status !== 200) {
- alert('Error uploading private key: ' + privateKeyRequest.statusText);
- }
- if (callback != undefined){
- callback();
- }
- }
- };
- privateKeyRequest.send(privateKeyForm);
- } else {
- alert('One or both of the files is missing or not a file object');
- }
- }
- //Handlers for selecting domain based key pairs
- //ktype = {"pub" / "pri"}
- function handleFileSelect(event, ktype="pub") {
- const file = event.target.files[0];
- //const fileNameInput = document.getElementById('selected-file-name');
- if (ktype == "pub"){
- uploadPendingPublicKey = file;
- }else if (ktype == "pri"){
- uploadPendingPrivateKey = file;
- }
-
-
- //fileNameInput.value = file.name;
- }
- //Check if the default keypairs exists
- function initDefaultKeypairCheck(){
- $.get("/cert/checkDefault", function(data){
- let tick = `<i class="ui green checkmark icon"></i>`;
- let cross = `<i class="ui red times icon"></i>`;
- $("#pubkeyExists").html(data.DefaultPubExists?tick:cross);
- $("#prikeyExists").html(data.DefaultPriExists?tick:cross);
- });
- }
- initDefaultKeypairCheck();
- function uploadPrivateKey(){
- // create file input element
- const input = document.createElement('input');
- input.type = 'file';
-
- // add change listener to file input
- input.addEventListener('change', () => {
- // create form data object
- const formData = new FormData();
-
- // add selected file to form data
- formData.append('file', input.files[0]);
- // send form data to server
- fetch('/cert/upload?ktype=pri', {
- method: 'POST',
- body: formData
- })
- .then(response => {
- initDefaultKeypairCheck();
- if (response.ok) {
- alert('File upload successful!');
- } else {
- response.text().then(text => {
- alert(text);
- });
- //console.log(response.text());
- //alert('File upload failed!');
- }
- })
- .catch(error => {
- alert('An error occurred while uploading the file.');
- console.error(error);
- });
- });
-
- // click file input to open file selector
- input.click();
- }
- function uploadPublicKey() {
- // create file input element
- const input = document.createElement('input');
- input.type = 'file';
-
- // add change listener to file input
- input.addEventListener('change', () => {
- // create form data object
- const formData = new FormData();
-
- // add selected file to form data
- formData.append('file', input.files[0]);
- // send form data to server
- fetch('/cert/upload?ktype=pub', {
- method: 'POST',
- body: formData
- })
- .then(response => {
- if (response.ok) {
- alert('File upload successful!');
- initDefaultKeypairCheck();
- } else {
- response.text().then(text => {
- alert(text);
- });
- //console.log(response.text());
- //alert('File upload failed!');
- }
- })
- .catch(error => {
- alert('An error occurred while uploading the file.');
- console.error(error);
- });
- });
-
- // click file input to open file selector
- input.click();
- }
- </script>
|