mirror of
https://github.com/outbackdingo/labca.git
synced 2026-01-27 18:19:33 +00:00
Update LabCA GUI for several recent boulder changes
This commit is contained in:
@@ -33,8 +33,7 @@ type IssuerLoc struct {
|
||||
|
||||
// From boulder: issuance/issuer.go
|
||||
type IssuerConfig struct {
|
||||
UseForRSALeaves bool `json:"useForRSALeaves"`
|
||||
UseForECDSALeaves bool `json:"useForECDSALeaves"`
|
||||
Active bool `json:"active"`
|
||||
|
||||
IssuerURL string `validate:"required,url" json:"issuerURL,omitempty"`
|
||||
OCSPURL string `validate:"required,url" json:"ocspURL,omitempty"`
|
||||
@@ -56,14 +55,13 @@ type CAConfig struct {
|
||||
|
||||
// CertDetails contains info about each certificate for use in the GUI
|
||||
type CertDetails struct {
|
||||
CertFile string
|
||||
BaseName string
|
||||
Subject string
|
||||
IsRoot bool
|
||||
UseForRSA bool
|
||||
UseForECDSA bool
|
||||
NotAfter string
|
||||
Details string
|
||||
CertFile string
|
||||
BaseName string
|
||||
Subject string
|
||||
IsRoot bool
|
||||
ActiveIssuer bool
|
||||
NotAfter string
|
||||
Details string
|
||||
}
|
||||
|
||||
type CertChain struct {
|
||||
@@ -139,8 +137,7 @@ func enhanceChains(chains []CertChain) []CertChain {
|
||||
for k := 0; k < len(chains); k++ {
|
||||
for n := 0; n < len(chains[k].IssuerCerts); n++ {
|
||||
if chains[k].IssuerCerts[n].CertFile == rawChains[i].Location.CertFile {
|
||||
chains[k].IssuerCerts[n].UseForRSA = rawChains[i].UseForRSALeaves
|
||||
chains[k].IssuerCerts[n].UseForECDSA = rawChains[i].UseForECDSALeaves
|
||||
chains[k].IssuerCerts[n].ActiveIssuer = rawChains[i].Active
|
||||
certFile := locateFile(rawChains[i].Location.CertFile)
|
||||
if d, err := getCertFileDetails(certFile); err == nil {
|
||||
chains[k].IssuerCerts[n].Details = d
|
||||
@@ -235,7 +232,7 @@ func getChains() []CertChain {
|
||||
return chains
|
||||
}
|
||||
|
||||
func setUseForLeavesFile(filename, forRSA, forECDSA string) error {
|
||||
func setUseForLeavesFile(filename, active string) error {
|
||||
caConf, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
@@ -251,30 +248,20 @@ func setUseForLeavesFile(filename, forRSA, forECDSA string) error {
|
||||
}
|
||||
|
||||
// Make sure that the named certificate(s) exist
|
||||
foundRSA := false
|
||||
foundECDSA := false
|
||||
foundActive := false
|
||||
for i := 0; i < len(result.CA.Issuance.Issuers); i++ {
|
||||
if strings.Contains(result.CA.Issuance.Issuers[i].Location.CertFile, forRSA) {
|
||||
foundRSA = true
|
||||
}
|
||||
if strings.Contains(result.CA.Issuance.Issuers[i].Location.CertFile, forECDSA) {
|
||||
foundECDSA = true
|
||||
if strings.Contains(result.CA.Issuance.Issuers[i].Location.CertFile, active) {
|
||||
foundActive = true
|
||||
}
|
||||
}
|
||||
if !foundRSA {
|
||||
return errors.New("certificate '" + forRSA + "' not found in ca file")
|
||||
}
|
||||
if !foundECDSA {
|
||||
return errors.New("certificate '" + forECDSA + "' not found in ca file")
|
||||
if !foundActive {
|
||||
return errors.New("certificate '" + active + "' not found in ca file")
|
||||
}
|
||||
|
||||
// Now set the flags for the named certificate(s)
|
||||
for i := 0; i < len(result.CA.Issuance.Issuers); i++ {
|
||||
if forRSA != "" {
|
||||
result.CA.Issuance.Issuers[i].UseForRSALeaves = strings.Contains(result.CA.Issuance.Issuers[i].Location.CertFile, forRSA)
|
||||
}
|
||||
if forECDSA != "" {
|
||||
result.CA.Issuance.Issuers[i].UseForECDSALeaves = strings.Contains(result.CA.Issuance.Issuers[i].Location.CertFile, forECDSA)
|
||||
if active != "" {
|
||||
result.CA.Issuance.Issuers[i].Active = strings.Contains(result.CA.Issuance.Issuers[i].Location.CertFile, active)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,25 +289,22 @@ func setUseForLeavesFile(filename, forRSA, forECDSA string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setUseForLeaves(forRSA, forECDSA string) error {
|
||||
func setUseForLeaves(active string) error {
|
||||
if err := exec.Command("cp", "-f", caConfFile, caConfFile+"_BAK").Run(); err != nil {
|
||||
return errors.New("could not create ca backup file: " + err.Error())
|
||||
}
|
||||
|
||||
if err := setUseForLeavesFile(caConfFile, forRSA, forECDSA); err != nil {
|
||||
if err := setUseForLeavesFile(caConfFile, active); err != nil {
|
||||
exec.Command("mv", caConfFile+"_BAK", caConfFile).Run()
|
||||
return err
|
||||
}
|
||||
|
||||
exec.Command("rm", caConfFile+"_BAK").Run()
|
||||
|
||||
if forRSA != "" {
|
||||
viper.Set("certs.issuerRSA", forRSA)
|
||||
if active != "" {
|
||||
viper.Set("certs.activeIssuer", active)
|
||||
}
|
||||
if forECDSA != "" {
|
||||
viper.Set("certs.issuerECDSA", forECDSA)
|
||||
}
|
||||
if forRSA != "" || forECDSA != "" {
|
||||
if active != "" {
|
||||
viper.WriteConfig()
|
||||
}
|
||||
|
||||
|
||||
@@ -194,6 +194,7 @@ func _parseComponents(data string) []Component {
|
||||
if len(parts) < 6 {
|
||||
components = append(components, Component{Name: "Boulder (ACME)"})
|
||||
components = append(components, Component{Name: "Consul (Boulder)"})
|
||||
components = append(components, Component{Name: "pkilint (Boulder)"})
|
||||
components = append(components, Component{Name: "LabCA Application"})
|
||||
components = append(components, Component{Name: "LabCA Controller"})
|
||||
components = append(components, Component{Name: "MySQL Database"})
|
||||
@@ -261,8 +262,19 @@ func _parseComponents(data string) []Component {
|
||||
consulClass = ""
|
||||
}
|
||||
|
||||
pkilint, err := time.Parse(time.RFC3339Nano, parts[6])
|
||||
pkilintReal := ""
|
||||
pkilintNice := "stopped"
|
||||
pkilintClass := "error"
|
||||
if err == nil {
|
||||
pkilintReal = pkilint.Format("02-Jan-2006 15:04:05 MST")
|
||||
pkilintNice = humanize.RelTime(pkilint, time.Now(), "", "")
|
||||
pkilintClass = ""
|
||||
}
|
||||
|
||||
components = append(components, Component{Name: "Boulder (ACME)", Timestamp: boulderReal, TimestampRel: boulderNice, Class: boulderClass})
|
||||
components = append(components, Component{Name: "Consul (Boulder)", Timestamp: consulReal, TimestampRel: consulNice, Class: consulClass})
|
||||
components = append(components, Component{Name: "pkilint (Boulder)", Timestamp: pkilintReal, TimestampRel: pkilintNice, Class: pkilintClass})
|
||||
components = append(components, Component{Name: "LabCA Application", Timestamp: labcaReal, TimestampRel: labcaNice, Class: labcaClass})
|
||||
components = append(components, Component{Name: "LabCA Controller", Timestamp: svcReal, TimestampRel: svcNice, Class: svcClass})
|
||||
components = append(components, Component{Name: "MySQL Database", Timestamp: mysqlReal, TimestampRel: mysqlNice, Class: mysqlClass})
|
||||
@@ -472,6 +484,9 @@ func parseDockerStats(data string) []AjaxStat {
|
||||
if strings.Contains(docker.Name, "-bconsul-") {
|
||||
stat.Name = "Consul (Boulder)"
|
||||
}
|
||||
if strings.Contains(docker.Name, "-bpkilint-") {
|
||||
stat.Name = "pkilint (Boulder)"
|
||||
}
|
||||
if strings.Contains(docker.Name, "labca-gui-") {
|
||||
stat.Name = "LabCA Application"
|
||||
}
|
||||
|
||||
18
gui/main.go
18
gui/main.go
@@ -1078,6 +1078,7 @@ func (res *Result) ManageComponents(w http.ResponseWriter, r *http.Request, acti
|
||||
(components[i].Name == "Boulder (ACME)" && (action == "boulder-start" || action == "boulder-stop" || action == "boulder-restart")) ||
|
||||
(components[i].Name == "LabCA Application" && action == "labca-restart") ||
|
||||
(components[i].Name == "Consul (Boulder)" && action == "consul-restart") ||
|
||||
(components[i].Name == "pkilint (Boulder)" && action == "pkilint-restart") ||
|
||||
(components[i].Name == "MySQL Database" && action == "mysql-restart") {
|
||||
res.Timestamp = components[i].Timestamp
|
||||
res.TimestampRel = components[i].TimestampRel
|
||||
@@ -1203,7 +1204,7 @@ func updateLeaveIssuersHandler(w http.ResponseWriter, r *http.Request) {
|
||||
Error string
|
||||
}{Success: true}
|
||||
|
||||
if err := setUseForLeaves(r.Form.Get("rsa"), r.Form.Get("ecdsa")); err != nil {
|
||||
if err := setUseForLeaves(r.Form.Get("active")); err != nil {
|
||||
res.Success = false
|
||||
res.Error = err.Error()
|
||||
} else {
|
||||
@@ -1359,6 +1360,7 @@ func _managePost(w http.ResponseWriter, r *http.Request) {
|
||||
"cert-export",
|
||||
"mysql-restart",
|
||||
"consul-restart",
|
||||
"pkilint-restart",
|
||||
"nginx-reload",
|
||||
"nginx-restart",
|
||||
"svc-restart",
|
||||
@@ -1552,6 +1554,18 @@ func _manageGet(w http.ResponseWriter, r *http.Request) {
|
||||
components[i].Buttons = append(components[i].Buttons, btn)
|
||||
}
|
||||
|
||||
if components[i].Name == "pkilint (Boulder)" {
|
||||
components[i].LogURL = ""
|
||||
components[i].LogTitle = ""
|
||||
|
||||
btn := make(map[string]interface{})
|
||||
btn["Class"] = "btn-warning"
|
||||
btn["Id"] = "pkilint-restart"
|
||||
btn["Title"] = "Restart the internal pkilint helper"
|
||||
btn["Label"] = "Restart"
|
||||
components[i].Buttons = append(components[i].Buttons, btn)
|
||||
}
|
||||
|
||||
if components[i].Name == "MySQL Database" {
|
||||
components[i].LogURL = ""
|
||||
components[i].LogTitle = ""
|
||||
@@ -3549,4 +3563,4 @@ func main() {
|
||||
} else {
|
||||
log.Fatal(srv.ListenAndServe())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,8 +165,7 @@
|
||||
<tr>
|
||||
<th>Subject</th>
|
||||
<th></th>
|
||||
<th>Issue RSA</th>
|
||||
<th>Issue ECDSA</th>
|
||||
<th>Active</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{{ range $item := .CertificateChains }}
|
||||
@@ -179,7 +178,6 @@
|
||||
<a href="/certs/{{ $item.RootCert.BaseName }}.pem" title="Download this certificate">download</a>
|
||||
</td>
|
||||
<td class="vmiddle"></td>
|
||||
<td class="vmiddle"></td>
|
||||
<td class="vmiddle">
|
||||
<button class="btn btn-outline btn-reg btn-success export-cert-key" type="button" title="Export this certificate and key" data-name="{{ $item.RootCert.BaseName }}" data-subject="{{ $item.RootCert.Subject }}">Export</button>
|
||||
<button class="btn btn-outline btn-reg btn-warning renew-cert" type="button" title="Generate new version with extended lifetime" data-name="{{ $item.RootCert.BaseName }}" data-rootname="{{ $item.RootCert.BaseName }}" data-subject="{{ $item.RootCert.Subject }}" data-rootsubject="{{ $item.RootCert.Subject }}" data-notbefore="{{ $item.RootCert.NotAfter }}" data-isroot="true">Renew</button>
|
||||
@@ -198,8 +196,7 @@
|
||||
<td class="vmiddle">
|
||||
<a href="/certs/{{ $subitem.BaseName }}.pem" title="Download this certificate">download</a>
|
||||
</td>
|
||||
<td class="vmiddle center"><input type="radio" id="rsa-{{ $subitem.BaseName }}" name="issue-rsa" value="{{ $subitem.BaseName }}" title="Use this certificate for issueing RSA leave certificates" {{ if $subitem.UseForRSA }}data-orig="true" checked{{ end }}/></td>
|
||||
<td class="vmiddle center"><input type="radio" id="ecdsa-{{ $subitem.BaseName }}" name="issue-ecdsa" value="{{ $subitem.BaseName }}" title="Use this certificate for issueing ECDSA leave certificates" {{ if $subitem.UseForECDSA }}data-orig="true" checked{{ end }}/></td>
|
||||
<td class="vmiddle center"><input type="radio" id="active-{{ $subitem.BaseName }}" name="issue-active" value="{{ $subitem.BaseName }}" title="Use this certificate for issueing leave certificates" {{ if $subitem.ActiveIssuer }}data-orig="true" checked{{ end }}/></td>
|
||||
<td class="vmiddle">
|
||||
<button class="btn btn-outline btn-reg btn-success export-cert-key" type="button" title="Export this certificate and key" data-name="{{ $subitem.BaseName }}" data-subject="{{ $subitem.Subject }}">Export</button>
|
||||
<button class="btn btn-outline btn-reg btn-warning renew-cert" type="button" title="Generate new version with extended lifetime" data-name="{{ $subitem.BaseName }}" data-rootname="{{ $item.RootCert.BaseName }}" data-subject="{{ $subitem.Subject }}" data-rootsubject="{{ $item.RootCert.Subject }}" data-notbefore="{{ $subitem.NotAfter }}" data-notafter="{{ $item.RootCert.NotAfter }}" data-isroot="false">Renew</button>
|
||||
@@ -527,10 +524,8 @@
|
||||
<h4>Are you sure?</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span>×</span></button>
|
||||
<form enctype="multipart/form-data" id="modal-leaves-form" method="POST">
|
||||
<input type="hidden" id="new-rsa-issuer" name="new-rsa-issuer">
|
||||
<input type="hidden" id="new-ecdsa-issuer" name="new-ecdsa-issuer">
|
||||
<span id="want-new-rsa-issuer" class="hidden">• Change the RSA issuer certificate<br/></span>
|
||||
<span id="want-new-ecdsa-issuer" class="hidden">• Change the ECDSA issuer certificate<br/></span>
|
||||
<input type="hidden" id="new-active-issuer" name="new-active-issuer">
|
||||
<span id="want-new-active-issuer" class="hidden">• Change the active issuer certificate<br/></span>
|
||||
<span class="error" id="modal-leaves-error" style="display: none;"></span><br/>
|
||||
<input class="btn btn-default btn-reg btn-warning btn-6em" value="Change" id="modal-leaves-done"/>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal" id="cancel-leaves">Cancel</button>
|
||||
@@ -614,49 +609,29 @@
|
||||
{{ end }}
|
||||
|
||||
function leave_issuer_changed() {
|
||||
iss_rsa = "";
|
||||
iss_ecdsa = "";
|
||||
iss_rsa_changed = false;
|
||||
iss_ecdsa_changed = false;
|
||||
iss_active = "";
|
||||
iss_active_changed = false;
|
||||
|
||||
$('input[type=radio][name=issue-rsa]').each(function() {
|
||||
$('input[type=radio][name=issue-active]').each(function() {
|
||||
if ($(this).prop('checked') && !$(this).data('orig')) {
|
||||
iss_rsa = $(this).val();
|
||||
iss_rsa_changed = true;
|
||||
}
|
||||
});
|
||||
$('input[type=radio][name=issue-ecdsa]').each(function() {
|
||||
if ($(this).prop('checked') && !$(this).data('orig')) {
|
||||
iss_ecdsa = $(this).val();
|
||||
iss_ecdsa_changed = true;
|
||||
iss_active = $(this).val();
|
||||
iss_active_changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (iss_rsa_changed || iss_ecdsa_changed) {
|
||||
$("#new-rsa-issuer").val(iss_rsa);
|
||||
if (iss_rsa_changed) {
|
||||
$("#want-new-rsa-issuer").removeClass("hidden").show();
|
||||
} else {
|
||||
$("#want-new-rsa-issuer").hide();
|
||||
}
|
||||
$("#new-ecdsa-issuer").val(iss_ecdsa);
|
||||
if (iss_ecdsa_changed) {
|
||||
$("#want-new-ecdsa-issuer").removeClass("hidden").show();
|
||||
} else {
|
||||
$("#want-new-ecdsa-issuer").hide();
|
||||
}
|
||||
if (iss_active_changed) {
|
||||
$("#new-active-issuer").val(iss_active);
|
||||
$("#want-new-active-issuer").removeClass("hidden").show();
|
||||
|
||||
$('#modal-leaves').modal('show');
|
||||
} else {
|
||||
$("#want-new-active-issuer").hide();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$('input[type=radio][name=issue-rsa]').change(function() {
|
||||
return leave_issuer_changed();
|
||||
});
|
||||
|
||||
$('input[type=radio][name=issue-ecdsa]').change(function() {
|
||||
$('input[type=radio][name=issue-active]').change(function() {
|
||||
return leave_issuer_changed();
|
||||
});
|
||||
|
||||
@@ -1313,7 +1288,7 @@
|
||||
return true;
|
||||
|
||||
} else if ($(evt.target).attr("id") == "modal-leaves-done") {
|
||||
if ($("#want-new-rsa-issuer").hasClass("hidden") && $("#want-new-ecdsa-issuer").hasClass("hidden")) {
|
||||
if ($("#want-new-active-issuer").hasClass("hidden")) {
|
||||
$('#modal-spinner').modal('hide');
|
||||
$('#modal-leaves').modal('hide');
|
||||
} else {
|
||||
@@ -1328,10 +1303,7 @@
|
||||
try {
|
||||
res = JSON.parse(req.response);
|
||||
if (res.Success) {
|
||||
$('input[type=radio][name=issue-rsa]').each(function() {
|
||||
$(this).data('orig', $(this).prop('checked'))
|
||||
});
|
||||
$('input[type=radio][name=issue-ecdsa]').each(function() {
|
||||
$('input[type=radio][name=issue-active]').each(function() {
|
||||
$(this).data('orig', $(this).prop('checked'))
|
||||
});
|
||||
$('#modal-leaves').modal('hide');
|
||||
@@ -1368,7 +1340,7 @@
|
||||
$("#modal-leaves-error").removeClass("hidden").show().text("Error communicating with backend server");
|
||||
};
|
||||
|
||||
req.send("action=update-leave-issuers" + "&rsa=" + $("#new-rsa-issuer").val() + "&ecdsa=" + $("#new-ecdsa-issuer").val());
|
||||
req.send("action=update-leave-issuers" + "&active=" + $("#new-active-issuer").val());
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1669,4 +1641,4 @@
|
||||
pwduxHandlers('#password-strength', '#new-password', ['#username', '#accemail']);
|
||||
});
|
||||
</script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
Reference in New Issue
Block a user