Files
labca/gui/templates/views/cert.tmpl
2025-02-02 20:25:38 +01:00

355 lines
15 KiB
Cheetah

{{ define "body" }}
</div>
<div class="col-md-6 col-sm-12">
{{with .CertificateInfo}}
<h3>{{ if .IsRoot }}<b>Root</b>{{ else }}<b>Issuer</b> (2nd level){{ end }} Certificate</h3>
{{ if not .IsRoot }}
Root Subject: <span id="root-subject-display">{{ .RootSubject }}</span><br><br>
{{ end }}
<ul class="nav nav-tabs">
<li class="{{ if eq .CreateType "generate" }}active{{ end }}">
<a data-toggle="tab" href="#generate">Generate</a>
</li>
<li class="{{ if eq .CreateType "import" }}active{{ end }}">
<a data-toggle="tab" href="#import">Import</a>
</li>
<li class="{{ if eq .CreateType "upload" }}active{{ end }}">
<a data-toggle="tab" href="#upload">Upload</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade {{ if eq .CreateType "generate" }}active in{{ end }}" id="generate">
<br/>
<form role="form" class="form-cert" enctype="multipart/form-data" method="POST">
<input type="hidden" name="cert" value="{{ if .IsRoot }}root{{ else }}issuer{{ end }}">
<input type="hidden" name="createtype" value="generate">
<input type="hidden" name="keep-root-online" id="keep-root-online">
<input type="hidden" name="ack-rootkey" id="ack-rootkey">
<input type="hidden" name="rootkey" id="rootkey">
<input type="hidden" name="rootpassphrase" id="rootpassphrase">
{{ if not .IsRoot }}
<input type="hidden" name="root-subject" id="root-subject" value="{{ .RootSubject }}">
<input type="hidden" name="root-enddate" id="root-enddate" value="{{ .RootEnddate }}">
{{ end }}
<div class="form-group">
<label for="keytype">Key type and size:</label>
<select class="form-control" id="keytype" name="keytype" required autocomplete="off">
{{ $selected := .KeyType }}
{{ range $key, $value := .KeyTypes }}
<option value="{{ $key }}"{{ if eq $key $selected }} selected="selected"{{ end }}>{{ $value }}</option>
{{ end }}
</select>
{{ with .Errors.KeyType }}
<span class="error">{{ . }}</span>
{{ end }}
</div>
<div class="form-group">
<label for="c">Country (2-Letter code):</label>
<input class="form-control" type="text" id="c" name="c" value="{{ .Country }}" maxlength="2" required {{ if and (ne .Country "") (.IsRootGenerated) }}readonly{{ end }}>
{{ with .Errors.Country }}
<span class="error">{{ . }}</span>
{{ end }}
</div>
<div class="form-group">
<label for="o">Organization:</label>
<input class="form-control" type="text" id="o" name="o" value="{{ .Organization }}" required {{ if and (ne .Organization "") (.IsRootGenerated) }}readonly{{ end }}>
{{ with .Errors.Organization }}
<span class="error">{{ . }}</span>
{{ end }}
</div>
<div class="form-group">
<label for="cn">Common Name:</label>
<input class="form-control" type="text" id="cn" name="cn" value="{{ .CommonName }}" required>
{{ with .Errors.CommonName }}
<span class="error">{{ . }}</span>
{{ end }}
</div>
<div class="form-group">
<label for="numdays">Validity (days):</label>
<input class="form-control" type="text" id="numdays" name="numdays" value="{{ .NumDays }}" required>
End date: <span id="validity-enddate"></span><br>
<span class="error hidden" id="numdays-error">{{ .Errors.numdays }}</span>
</div>
<div>
{{ with .Errors.Generate }}
<span class="error">{{ . }}</span><br/>
{{ end }}
<input class="btn btn-default" type="submit" value="Generate" name="generate" id="generatebtn">
{{ if and (not .IsRoot) .IsFirst }}
<input class="btn btn-danger btn-right" type="submit" value="Revert Root" name="revertroot" id="revertroot">
{{ end }}
</div>
</form>
</div>
<div class="tab-pane fade {{ if eq .CreateType "import" }}active in{{ end }}" id="import">
<br/>
<form role="form" class="form-cert" enctype="multipart/form-data" method="POST">
<input type="hidden" name="cert" value="{{ if .IsRoot }}root{{ else }}issuer{{ end }}">
<input type="hidden" name="createtype" value="import">
<p>
Here you can import a certificate that was exported from another LabCA instance, either in the .pfx (PKCS#12) or in the .zip format.<br/>
If you have separate key and certificate files, use the
<a href="#upload" onClick='$(".nav-tabs > li:nth-child(3) > a:nth-child(1)").click()'>Upload</a> tab.
</p>
<div class="form-group">
<label for="import">Certificate:
{{ with .Errors.Import }}
<span class="error"><br/>{{ . }}</span>
{{ end }}
</label>
<input class="form-control non-fluid" type="file" id="import" name="import" required/>
</div>
<div class="form-group">
<label for="import-pwd">File password (optional):
<input class="form-control non-fluid" type="password" id="import-pwd" name="import-pwd"/>
</div>
<div>
<input class="btn btn-default" type="submit" value="Import">
</div>
</form>
</div>
<div class="tab-pane fade {{ if eq .CreateType "upload" }}active in{{ end }}" id="upload">
<br/>
<form role="form" class="form-cert" enctype="multipart/form-data" method="POST">
<input type="hidden" name="cert" value="{{ if .IsRoot }}root{{ else }}issuer{{ end }}">
<input type="hidden" name="createtype" value="upload">
<div class="form-group">
<label for="certificate">Certificate (in PEM format):
{{ with .Errors.Certificate }}
<span class="error"><br/>{{ . }}</span>
{{ end }}
</label>
<textarea class="form-control" id="certificate" name="certificate" rows="10" cols="80" required>{{ .Certificate }}</textarea>
</div>
<div class="form-group">
<label for="key">Key (in PEM format):
{{ with .Errors.Key }}
<span class="error"><br/>{{ . }}</span>
{{ end }}
</label>
<textarea class="form-control" id="key" name="key" rows="10" cols="80" required>{{ .Key }}</textarea>
</div>
<div class="form-group">
<label for="passphrase">Passphrase (optional):
{{ with .Errors.Passphrase }}
<span class="error"><br/>{{ . }}</span>
{{ end }}
</label>
<input class="form-control" type="password" id="passphrase" name="passphrase" value="">
</div>
<div class="form-group" style="display: none;">
You should provide the Root CRL here as well, but this can also be done later<br>
<label for="crl">Root CRL (optional):
{{ with .Errors.CRL }}
<span class="error"><br/>{{ . }}</span>
{{ end }}
</label>
<textarea class="form-control" id="crl" name="crl" rows="10" cols="80">{{ .CRL }}</textarea>
</div>
<div>
{{ with .Errors.Upload }}
<span class="error">{{ . }}</span><br/>
{{ end }}
<input class="btn btn-default" type="submit" id="cert-submit" value="Upload">
</div>
</form>
</div>
</div>
<p id="processing" class="hidden"><br/>Setting up LabCA and applying configuration. This will take a minute...<br/>
<img id="restart-spinner" src="static/img/spinner.gif" height="36"></p>
{{end}}
{{ if ne .RootKey nil }}
<div id="modal-rootkey" class="modal fade" data-backdrop="static" data-keyboard="false" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content modal-rootkey-content">
<h4>Root Key</h4>
<p>This is the generated private key for the Root CA certificate. <span class="error"><b>Copy it now and store
it in a secure, private and offline location!</b></span> After setting up the Issuer CA certificate in the next
step, we will delete the key from the system.<br/>
When we need the key for certain operations in the future, we will ask for it.</p>
<textarea class="form-control" rows="10" cols="80" readonly>{{ .RootKey }}</textarea>
<input type="checkbox" id="modal-keep-root-online"> Keep the root key on the LabCA server (INSECURE)<br/>
{{ with .CertificateInfo.Errors.Modal }}
<span class="error">{{ . }}</span><br/>
{{ end }}
<input class="btn btn-default btn-reg" value="OK" id="modal-rootkey-done"/>
</div>
</div>
</div>
{{ end }}
{{ if and (not .CertificateInfo.IsRoot) (ne .CSR nil) }}
<div id="modal-csr" class="modal fade" data-backdrop="static" data-keyboard="false" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content modal-csr-content">
<h4>CSR</h4>
<textarea class="form-control" rows="10" cols="80" readonly>{{ .CSR }}</textarea>
<p>Please have this CSR signed by the offline Root CA. Then you can close this dialog and upload the resulting certificate.</p>
{{ with .CertificateInfo.Errors.Modal }}
<span class="error">{{ . }}</span><br/>
{{ end }}
<input class="btn btn-default btn-reg" value="OK" id="modal-csr-done"/>
</div>
</div>
</div>
{{ end }}
{{ if .GetRootKey }}
<div id="modal-root-key" class="modal fade" data-backdrop="static" data-keyboard="false" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content modal-root-key-content">
<h4>Root Key Required</h4>
<p>Please provide the Root CA key file in PEM format. As soon as we are done with it, it will be removed from the system again.</p>
<textarea class="form-control" id="modal-rootkey" rows="10" cols="80"></textarea>
<div class="form-group">
<label for="modal-rootpassphrase">Passphrase (optional):</label>
<input class="form-control" type="password" id="modal-rootpassphrase" value="">
</div>
{{ with .CertificateInfo.Errors.Modal }}
<span class="error">{{ . }}</span><br/>
{{ end }}
<input class="btn btn-default btn-reg" value="Upload" id="modal-root-key-upload"/>
</div>
</div>
</div>
{{ end }}
{{ template "partials/progress.tmpl" . }}
{{end}}
{{ define "tail" }}
<script>
$(function() {
$("ul.nav").click(function() {
setTimeout(function() {
$(window).resize();
}, 250);
});
{{ if ne .CSR nil }}
$("#modal-csr").modal("show");
{{ end }}
$("#modal-csr-done").click(function() {
$('.nav-tabs a[href="#upload"]').tab('show');
$("#key").val("").parent().hide();
$("#passphrase").val("").parent().hide();
$("#crl").val("").parent().show();
$("#modal-csr").modal("hide");
});
{{ if ne .RootKey nil }}
$("#modal-rootkey").modal("show");
{{ end }}
$("#modal-rootkey-done").click(function() {
$("#ack-rootkey").val("yes");
$("#keep-root-online").val($("#modal-keep-root-online").prop("checked"));
$("#modal-rootkey").modal("hide");
$("#generatebtn").click();
});
{{ if .GetRootKey }}
$("#modal-root-key").modal("show");
{{ end }}
$("#modal-root-key-upload").click(function() {
$("#rootkey").val($("#modal-rootkey").val());
$("#rootpassphrase").val($("#modal-rootpassphrase").val());
$("#modal-root-key").modal("hide");
$("#generatebtn").click();
});
$("#revertroot").click(function() {
if (!window.confirm("Do you really want to remove the Root CA certificate?")) {
return false;
}
$("#c").removeAttr("required");
$("#o").removeAttr("required");
});
{{ if not .CertificateInfo.IsRoot }}
$(".form-cert").submit(function() {
$("#processing").removeClass("hidden");
});
{{end}}
function updateEndDate() {
// Determine new end date
x = new Date();
x.setDate(x.getDate() + parseInt($('#numdays').val()))
$('#validity-enddate').text(x.toUTCString());
try {
if (($("#root-enddate").val() != undefined) && ($("#root-enddate").val().length > 0)) {
r = new Date($("#root-enddate").val());
if (x > r) {
$("#numdays-error").text("Validity cannot exceed root certificate end date");
$("#numdays-error").removeClass('hidden').show();
} else {
$("#numdays-error").text("");
if (!$("#numdays-error").hasClass('hidden')) {
$("#numdays-error").hide().addClass('hidden');
}
}
} else {
$("#numdays-error").text("");
if (!$("#numdays-error").hasClass('hidden')) {
$("#numdays-error").hide().addClass('hidden');
}
}
} catch(e) {
console.log(e);
}
$("#generatebtn").prop('disabled', !$("#numdays-error").hasClass('hidden'));
}
$.fn.inputFilter = function(callback, errMsg) {
return this.on("input keydown keyup mousedown mouseup select contextmenu drop focusout", function(e) {
if (callback(this.value)) {
// Accepted value
if (["keydown","mousedown","focusout"].indexOf(e.type) >= 0){
$("#numdays-error").text("");
if (!$("#numdays-error").hasClass('hidden')) {
$("#numdays-error").hide().addClass('hidden');
}
}
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
updateEndDate();
} else if (this.hasOwnProperty("oldValue")) {
// Rejected value - restore the previous one
$("#numdays-error").text(errMsg);
if ($("#numdays-error").hasClass('hidden')) {
$("#numdays-error").removeClass('hidden').show();
}
this.value = this.oldValue;
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
} else {
// Rejected value - nothing to restore
this.value = "";
}
});
};
$("#numdays").inputFilter(function(value) {
return /^\d*$/.test(value); // Allow digits only, using a RegExp
},"Only digits are allowed");
$("#certificate").change(function() {
$("#cert-submit").prop('disabled', ($("#certificate").val() == "" && $("#key").val() == ""));
})
$("#key").change(function() {
$("#cert-submit").prop('disabled', ($("#certificate").val() == "" && $("#key").val() == ""));
})
updateEndDate();
});
</script>
{{end}}