diff --git a/actions.go b/actions.go index 234b541..d952974 100644 --- a/actions.go +++ b/actions.go @@ -1,4 +1,4 @@ -//LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2024 Ruel Tmeizeh All Rights Reserved +//LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2025 Ruel Tmeizeh All Rights Reserved package main import ( @@ -48,7 +48,7 @@ func writeServers() error { return nil } -func sendFileToAllServers(filePath, cert_idx string) error { +func sendFileToAllServers(filePath, cert_idx_str string) error { var theError error numservers := len(servers) c := make(chan string) @@ -65,7 +65,7 @@ func sendFileToAllServers(filePath, cert_idx string) error { } log.Println("Parallel execution send file to server: " + srv + "...") - err := sendFileToServer(filePath, srv, cert_idx) + err := sendFileToServer(filePath, srv, cert_idx_str) if err != nil { log.Println(err.Error()) theError = err @@ -92,7 +92,7 @@ func sendFileToAllServers(filePath, cert_idx string) error { return theError //if any one or more fail, return an error for it (the last one that fails) } -func sendFileToServer(filePath, server, cert_idx string) error { +func sendFileToServer(filePath, server, cert_idx_str string) error { log.Println("Send file " + filePath + " to " + server + " starting...") _, fileName := path.Split(filePath) @@ -103,8 +103,8 @@ func sendFileToServer(filePath, server, cert_idx string) error { } //url := syncScheme + server + ":" + syncPort + "/api/file/upload/" + fileType + "/" + fmt.Sprintf("%02d", cert_idx) - url := syncScheme + server + ":" + syncPort + "/api/file/upload/" + fileTypeOrACL + "/" + cert_idx - if len(cert_idx) == 0 { // file is missing cert index number string, so is an ACL file + url := syncScheme + server + ":" + syncPort + "/api/file/upload/" + fileTypeOrACL + "/" + cert_idx_str + if len(cert_idx_str) == 0 { // file is missing cert index number string, so is an ACL file url = syncScheme + server + ":" + syncPort + "/api/file/upload/" + fileTypeOrACL } log.Println("Send file '" + filePath + "' to " + url + "...") @@ -198,7 +198,6 @@ func renew(cert_idx int) error { if server == appconf.Hostname { continue } - //domain_cert_location += ";davs:leapi:" + appconf.SecretKey + ":" + server + ":" + syncPort + ":/api/file/upload/cert" domain_cert_location += ";ssh:" + appconf.Username + "@" + server + ":" + appconf.TLSCertPath + fmt.Sprintf("%02d", cert_idx) + ".crt" } } else { //file sync type is HTTPS @@ -216,7 +215,6 @@ func renew(cert_idx int) error { if server == appconf.Hostname { continue } - //domain_key_location += ";davs:leapi:" + appconf.SecretKey + ":" + server + ":" + syncPort + ":/api/file/upload/key" domain_key_location += ";ssh:" + appconf.Username + "@" + server + ":" + appconf.TLSKeyPath + fmt.Sprintf("%02d", cert_idx) + ".key" } } else { //file sync type is HTTPS @@ -233,7 +231,6 @@ func renew(cert_idx int) error { if server == appconf.Hostname { continue } - //domain_chain_location += ";davs:leapi:" + appconf.SecretKey + ":" + server + ":" + syncPort + ":/api/file/upload/chain" domain_chain_location += ";ssh:" + appconf.Username + "@" + server + ":" + appconf.TLSChainPath + fmt.Sprintf("%02d", cert_idx) + ".crt" } } else { //file sync type is HTTPS @@ -244,16 +241,13 @@ func renew(cert_idx int) error { return errors.New("RENEW: error setting DOMAIN_CHAIN_LOCATION environment variable: " + err.Error()) } - //domain_pem_location := appconf.TLSPEMPath + fmt.Sprintf("%02d", cert_idx) + ".pem" - domain_fullpem_location := appconf.TLSPEMPath + fmt.Sprintf("%02d", cert_idx) + ".crt" + domain_fullpem_location := appconf.TLSPEMPath + fmt.Sprintf("%02d", cert_idx) + ".pem" if appconf.SyncType == "ssh" { for _, server := range servers { if server == appconf.Hostname { continue } - //domain_pem_location += ";davs:leapi:" + appconf.SecretKey + ":" + server + ":" + syncPort + ":/api/file/upload/pem" - //domain_fullpem_location += ";ssh:" + appconf.Username + "@" + server + ":" + appconf.TLSPEMPath + fmt.Sprintf("%02d", cert_idx) + ".pem" - domain_fullpem_location += ";ssh:" + appconf.Username + "@" + server + ":" + appconf.TLSPEMPath + fmt.Sprintf("%02d", cert_idx) + ".crt" + domain_fullpem_location += ";ssh:" + appconf.Username + "@" + server + ":" + appconf.TLSPEMPath + fmt.Sprintf("%02d", cert_idx) + ".pem" } } else { //file sync type is HTTPS domain_fullpem_location += ";davs:" + appconf.Username + ":" + appconf.SecretKey + ":" + appconf.Hostname + ":" + appconf.HTTPS_ServerPort + ":/api/file/sync/pem/" + fmt.Sprintf("%02d", cert_idx) @@ -264,13 +258,12 @@ func renew(cert_idx int) error { } //these parameters don't seem to be respected by GetSSL from environment variables, so write them to config file: - ca_cert_location := appconf.TLSCAPath + ".crt" + ca_cert_location := appconf.TLSCAPath + fmt.Sprintf("%02d", cert_idx) + ".crt" if appconf.SyncType == "ssh" { for _, server := range servers { if server == appconf.Hostname { continue } - //ca_cert_location += ";davs:leapi:" + appconf.SecretKey + ":" + server + ":" + syncPort + ":/api/file/upload/ca" ca_cert_location += ";ssh:" + appconf.Username + "@" + server + ":" + appconf.TLSCAPath + fmt.Sprintf("%02d", cert_idx) + ".crt" } } else { //file sync type is HTTPS @@ -285,7 +278,7 @@ func renew(cert_idx int) error { //old ssh method; requires ssh key //reload_command += "; ssh " + appconf.Username + "@" + server + " '" + appconf.ReloadCommand + "'" //new method; calls LEAPI to trigger reload - reload_command += " ; curl -s -k -X POST -H 'Authorization: Bearer " + appconf.SecretKey + "' " + syncScheme + server + "/api/reload" + reload_command += " ; curl -s -k -X POST -H 'Authorization: Bearer " + appconf.SecretKey + "' " + syncScheme + server + ":" + appconf.HTTPS_ServerPort + "/api/reload" //reload_command += "; 'curl -s -X POST -H \\\"Authorization: Bearer " + appconf.SecretKey + "\\\" " + syncScheme + server + "/api/reload" } @@ -298,7 +291,7 @@ func renew(cert_idx int) error { configFile = "CA=\"" + ca_server + "\"\n" configFile += "USE_SINGLE_ACL=\"true\"\n" - configFile += "CA_CERT_LOCATION=\"" + appconf.TLSCAPath + "\"\n" + configFile += "CA_CERT_LOCATION=\"" + ca_cert_location + "\"\n" configFile += "RELOAD_CMD=\"" + reload_command + "\"\n" configFile += "RENEW_ALLOW=\"" + appconf.RenewAllow + "\"\n" configFile += "CHECK_REMOTE=\"false\"\n" diff --git a/amqp.go b/amqp.go index 5d86609..3f5c222 100644 --- a/amqp.go +++ b/amqp.go @@ -1,3 +1,4 @@ +//LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2025 Ruel Tmeizeh All Rights Reserved package main import ( @@ -159,7 +160,7 @@ func amqp() { ///////////////////////////////////////////// // RabbitMQ Publish Test sigch := make(chan os.Signal, 1) - signal.Notify(sigch, syscall.SIGUSR1, syscall.SIGUSR2) + signal.Notify(sigch, syscall.SIGUSR2) //create test message to send pubtest := KzMessage{ diff --git a/api.go b/api.go index 0b43d38..e2b1525 100644 --- a/api.go +++ b/api.go @@ -1,4 +1,4 @@ -//LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2024 Ruel Tmeizeh All Rights Reserved +//LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2025 Ruel Tmeizeh All Rights Reserved package main import ( @@ -10,6 +10,7 @@ import ( "os" "path" "strings" + "sync" "time" "github.com/labstack/echo/v4" @@ -162,21 +163,21 @@ func apiDelDns(c echo.Context) error { //Receive file and store it func apiUpload(c echo.Context) error { fileType := c.Param("fileType") - cert_idx := c.Param("cert_idx") + cert_idx_str := c.Param("cert_idx") r := c.Request() var filePath string switch fileType { case "ca": - filePath = appconf.TLSCAPath + fmt.Sprintf("%02d", cert_idx) + ".crt" + filePath = appconf.TLSCAPath + cert_idx_str + ".crt" case "chain": - filePath = appconf.TLSChainPath + fmt.Sprintf("%02d", cert_idx) + ".crt" + filePath = appconf.TLSChainPath + cert_idx_str + ".crt" case "key": - filePath = appconf.TLSKeyPath + fmt.Sprintf("%02d", cert_idx) + ".key" + filePath = appconf.TLSKeyPath + cert_idx_str + ".key" case "cert": - filePath = appconf.TLSCertPath + fmt.Sprintf("%02d", cert_idx) + ".crt" + filePath = appconf.TLSCertPath + cert_idx_str + ".crt" case "pem": - filePath = appconf.TLSPEMPath + fmt.Sprintf("%02d", cert_idx) + ".pem" + filePath = appconf.TLSPEMPath + cert_idx_str + ".pem" default: //ACL //return c.JSON(errorOut(http.StatusBadRequest, "Invalid filetype/URL.")) filePath = appconf.LetsEncryptValidationPath + "/" + fileType @@ -206,8 +207,8 @@ func apiUpload(c echo.Context) error { return c.JSON(errorOut(http.StatusInternalServerError, "Could not write file: "+err.Error())) } - log.Println("Received PUT to " + r.RequestURI) - log.Println("Writing to " + filePath) + log.Println("Received PUT to: " + r.RequestURI) + log.Println("Writing to: " + filePath) return c.JSON(okOut()) } diff --git a/main.go b/main.go index 820d335..ce7f461 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,4 @@ -//LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2024 Ruel Tmeizeh All Rights Reserved +// LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2025 Ruel Tmeizeh All Rights Reserved package main import ( @@ -23,7 +23,7 @@ import ( ) const appname string = "leapi" -const version string = "1.3.3" +const version string = "1.3.4" const serverVersion string = "RuhNet LE API v" + version const apiVersion int = 1 const website string = "https://ruhnet.co" @@ -390,7 +390,7 @@ func (f *LEAPIConfig) checkConfig() { } } -//This middleware adds headers to the response, for server version and CORS origin. +// This middleware adds headers to the response, for server version and CORS origin. func serverHeaders(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { c.Response().Header().Set(echo.HeaderServer, serverVersion) diff --git a/sync.go b/sync.go index ed32919..36f3077 100644 --- a/sync.go +++ b/sync.go @@ -1,4 +1,4 @@ -//LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2024 Ruel Tmeizeh All Rights Reserved +// LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2025 Ruel Tmeizeh All Rights Reserved package main import ( @@ -123,6 +123,9 @@ func syncServersFromHost(host string) error { log.Println(err.Error()) return errors.New("Couldn't parse response body from host " + host + ": " + err.Error()) } + if len(result.Data) > 0 { // if there is data to sync, reset our local server's cache + servers = nil + } for _, data := range result.Data { switch server := data.(type) { case string: @@ -177,10 +180,23 @@ func syncDomainsFromHost(host string) error { log.Println(err.Error()) return errors.New("Couldn't parse response body from host " + host + ": " + err.Error()) } + if len(result.Data) > 0 { // if there is data to sync, reset our local server's cache + certgroups = nil + } for _, data := range result.Data { - switch cg := data.(type) { - case interface{}: - certgroups = append(certgroups, cg.(CertGroup)) + //fmt.Printf("\ndomain sync data: %+v\n", data) + var cg CertGroup + switch cg_raw := data.(type) { + case interface{}: // put into json string, then from there into a CertGroup struct + cg_json, err := json.Marshal(cg_raw) + if err != nil { + log.Println(err.Error()) + } + err = json.Unmarshal(cg_json, &cg) + if err != nil { + log.Println(err.Error()) + } + certgroups = append(certgroups, cg) } } diff --git a/util.go b/util.go index c0c589d..a6942ee 100644 --- a/util.go +++ b/util.go @@ -1,3 +1,4 @@ +//LEAPI - ACME Certificate Renewal Control API - Copyright 2022-2025 Ruel Tmeizeh All Rights Reserved package main import (