diff --git a/checkcrl b/checkcrl
index 53b6af2..8cf9c5f 100755
--- a/checkcrl
+++ b/checkcrl
@@ -2,6 +2,15 @@
set -e
+if [ -e data/root-ca.crl ] && [ ! -e /var/www/html/crl/root-ca.crl ]; then
+ cp -p data/root-ca.crl /var/www/html/crl/root-ca.crl
+ touch /var/www/html/crl
+fi
+if [ -e data/root-ca.crl ] && [ data/root-ca.crl -nt /var/www/html/crl/root-ca.crl ]; then
+ cp -p data/root-ca.crl /var/www/html/crl/root-ca.crl
+ touch /var/www/html/crl
+fi
+
cd /var/www/html
if [ crl/ -nt certs/index.html ]; then
echo "Updating certs/index.html with latest CRL info..."
diff --git a/commander b/commander
index aef9f03..9c92e62 100755
--- a/commander
+++ b/commander
@@ -239,6 +239,14 @@ case $txt in
nohup /labca/install -b $branch &>>$LOGFILE
fi
;;
+"gen-issuer-crl")
+ cd /opt/boulder
+ docker compose exec -i boulder ./bin/boulder crl-updater --config labca/config/crl-updater.json -runOnce -debug-addr :18021 &>>$LOGFILE
+ /opt/labca/checkcrl &>>$LOGFILE
+ ;;
+"check-crl")
+ /opt/labca/checkcrl &>>$LOGFILE
+ ;;
*)
echo "Unknown command '$txt'. ERROR!"
exit 1
diff --git a/gui/apply-boulder b/gui/apply-boulder
index d5dc047..6274b44 100755
--- a/gui/apply-boulder
+++ b/gui/apply-boulder
@@ -183,6 +183,9 @@ rm -f test-root.p8
if [ -e $PKI_INT_CERT_BASE.key ]; then
cp -p $PKI_INT_CERT_BASE.key test-ca.key
+ if [ ! -e $PKI_INT_CERT_BASE.key.der ]; then
+ openssl pkey -in $PKI_INT_CERT_BASE.key -out $PKI_INT_CERT_BASE.key.der -outform der
+ fi
cp -p $PKI_INT_CERT_BASE.key.der test-ca.key.der
cp -p $PKI_INT_CERT_BASE.pem test-ca.pem
openssl rsa -in $PKI_INT_CERT_BASE.key -pubout > test-ca.pubkey.pem 2>/dev/null || openssl ec -in $PKI_INT_CERT_BASE.key -pubout > test-ca.pubkey.pem
@@ -190,6 +193,9 @@ if [ -e $PKI_INT_CERT_BASE.key ]; then
fi
if [ -e $PKI_ROOT_CERT_BASE.key ]; then
cp -p $PKI_ROOT_CERT_BASE.key test-root.key
+ if [ ! -e $PKI_ROOT_CERT_BASE.key.der ]; then
+ openssl pkey -in $PKI_ROOT_CERT_BASE.key -out $PKI_ROOT_CERT_BASE.key.der -outform der
+ fi
cp -p $PKI_ROOT_CERT_BASE.key.der test-root.key.der
openssl rsa -in $PKI_ROOT_CERT_BASE.key -pubout > test-root.pubkey.pem 2>/dev/null || openssl ec -in $PKI_ROOT_CERT_BASE.key -pubout > test-root.pubkey.pem
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in test-root.key -out test-root.p8
diff --git a/gui/certificate.go b/gui/certificate.go
index 5111244..00ee587 100644
--- a/gui/certificate.go
+++ b/gui/certificate.go
@@ -664,7 +664,6 @@ func (ci *CertificateInfo) Create(path string, certBase string, wasCSR bool) err
keyFileExists = false
}
if keyFileExists {
- // TODO: make option in GUI to trigger crl creation!
if _, err := exeCmd("openssl ca -config " + path + "openssl.cnf -gencrl -keyfile " + path + certBase + ".key -cert " + path + certBase + ".pem -out " + path + certBase + ".crl"); err != nil {
return reportError(err)
}
diff --git a/gui/main.go b/gui/main.go
index 2e7493f..72b266e 100644
--- a/gui/main.go
+++ b/gui/main.go
@@ -1039,6 +1039,95 @@ func _checkUpdatesHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(res)
}
+func generateCRLHandler(w http.ResponseWriter, r *http.Request, isRoot bool) {
+ res := struct {
+ Success bool
+ Errors map[string]string
+ }{Success: true, Errors: make(map[string]string)}
+
+ if isRoot {
+ path := "data/"
+ certBase := "root-ca"
+ keyFileExists := true
+ if _, err := os.Stat(path + certBase + ".key"); os.IsNotExist(err) {
+ keyFileExists = false
+ }
+ if keyFileExists {
+ if _, err := exeCmd("openssl ca -config " + path + "openssl.cnf -gencrl -keyfile " + path + certBase + ".key -cert " + path + certBase + ".pem -out " + path + certBase + ".crl"); err != nil {
+ res.Success = false
+ res.Errors["CRL"] = "Could not generate Root CRL - see logs"
+ }
+ } else {
+ if r.Form.Get("rootkey") == "" {
+ res.Success = false
+ res.Errors["CRL"] = "NO_ROOT_KEY"
+ } else {
+ rootci := &CertificateInfo{
+ IsRoot: true,
+ Key: r.Form.Get("rootkey"),
+ Passphrase: r.Form.Get("rootpassphrase"),
+ }
+ if !rootci.StoreRootKey(path) {
+ res.Success = false
+ res.Errors["CRL"] = rootci.Errors["Modal"]
+ } else {
+ // Generate CRL now that we have the key
+ if _, err := exeCmd("openssl ca -config " + path + "openssl.cnf -gencrl -keyfile " + path + certBase + ".key -cert " + path + certBase + ".pem -out " + path + certBase + ".crl"); err != nil {
+ res.Success = false
+ res.Errors["CRL"] = "Could not generate Root CRL - see logs"
+ }
+ // Remove the Root Key if we want to keep it offline
+ if viper.GetBool("keep_root_offline") {
+ if _, err := os.Stat(path + certBase + ".key"); !os.IsNotExist(err) {
+ fmt.Println("Removing private Root key from the system...")
+ if _, err := exeCmd("rm " + path + certBase + ".key"); err != nil {
+ log.Printf("_certCreate: error deleting root key: %v", err)
+ }
+ }
+ if _, err := os.Stat(path + certBase + ".key.der"); !os.IsNotExist(err) {
+ if _, err := exeCmd("rm " + path + certBase + ".key.der"); err != nil {
+ log.Printf("_certCreate: error deleting root key (DER format): %v", err)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ _hostCommand(w, r, "check-crl")
+
+ } else { // !isRoot
+ if !_hostCommand(w, r, "gen-issuer-crl") {
+ res.Success = false
+ res.Errors["CRL"] = "Failed to generate CRL - see logs"
+ }
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(res)
+}
+
+func uploadCRLHandler(w http.ResponseWriter, r *http.Request) {
+ res := struct {
+ Success bool
+ Errors map[string]string
+ }{Success: true, Errors: make(map[string]string)}
+
+ rootci := &CertificateInfo{
+ IsRoot: true,
+ CRL: r.Form.Get("crl"),
+ }
+ if !rootci.StoreCRL("data/") {
+ res.Success = false
+ res.Errors["CRL"] = rootci.Errors["Modal"]
+ }
+
+ _hostCommand(w, r, "check-crl")
+
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(res)
+}
+
func _managePostDispatch(w http.ResponseWriter, r *http.Request, action string) bool {
if action == "backup-restore" || action == "backup-delete" || action == "backup-now" {
_backupHandler(w, r)
@@ -1080,6 +1169,21 @@ func _managePostDispatch(w http.ResponseWriter, r *http.Request, action string)
return true
}
+ if action == "upload-root-crl" {
+ uploadCRLHandler(w, r)
+ return true
+ }
+
+ if action == "gen-root-crl" {
+ generateCRLHandler(w, r, true)
+ return true
+ }
+
+ if action == "gen-issuer-crl" {
+ generateCRLHandler(w, r, false)
+ return true
+ }
+
return false
}
@@ -1113,6 +1217,9 @@ func _managePost(w http.ResponseWriter, r *http.Request) {
"send-email",
"version-check",
"version-update",
+ "upload-root-crl",
+ "gen-root-crl",
+ "gen-issuer-crl",
} {
if a == action {
actionKnown = true
@@ -1599,7 +1706,8 @@ func _certCreate(w http.ResponseWriter, r *http.Request, certBase string, isRoot
if r.Form.Get("revertroot") != "" {
// From issuer certificate creation page it is possible to remove the root again and start over
- exeCmd("rm data/root-ca.key") // Does not necessarily exist
+ exeCmd("rm data/root-ca.key") // Does not necessarily exist
+ exeCmd("rm data/root-ca.key.der") // Does not necessarily exist
if _, err := exeCmd("rm data/root-ca.pem"); err != nil {
errorHandler(w, r, err, http.StatusInternalServerError)
return false
@@ -1614,13 +1722,8 @@ func _certCreate(w http.ResponseWriter, r *http.Request, certBase string, isRoot
}
} else if r.Form.Get("ack-rootkey") == "yes" {
// Root Key was shown, do we need to keep it online?
- if r.Form.Get("keep-root-online") == "true" {
- sess, _ := sessionStore.Get(r, "labca")
- sess.Values["root-online"] = true
- if err := sess.Save(r, w); err != nil {
- log.Printf("cannot save session: %s\n", err)
- }
- }
+ viper.Set("keep_root_offline", r.Form.Get("keep-root-online") != "true")
+ viper.WriteConfig()
// Undo what setupHandler did when showing the public key...
_, errPem := os.Stat("data/root-ca.pem")
@@ -1792,13 +1895,18 @@ func _certCreate(w http.ResponseWriter, r *http.Request, certBase string, isRoot
log.Printf("_certCreate: could not calculate IssuerNameID: %v", err)
}
- if session.Values["root-online"] != true {
+ if viper.GetBool("keep_root_offline") {
if _, err := os.Stat(path + "../root-ca.key"); !os.IsNotExist(err) {
fmt.Println("Removing private Root key from the system...")
if _, err := exeCmd("rm " + path + "../root-ca.key"); err != nil {
log.Printf("_certCreate: error deleting root key: %v", err)
}
}
+ if _, err := os.Stat(path + "../root-ca.key.der"); !os.IsNotExist(err) {
+ if _, err := exeCmd("rm " + path + "../root-ca.key.der"); err != nil {
+ log.Printf("_certCreate: error deleting root key (DER format): %v", err)
+ }
+ }
}
}
diff --git a/gui/templates/views/cert.tmpl b/gui/templates/views/cert.tmpl
index 8261595..6ab86c9 100644
--- a/gui/templates/views/cert.tmpl
+++ b/gui/templates/views/cert.tmpl
@@ -170,7 +170,7 @@
step, we will delete the key from the system.
When we need the key for certain operations in the future, we will ask for it.