mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-06 23:57:21 +02:00
add custom acme feature in backend
This commit is contained in:
parent
a3d55a3274
commit
352995e852
@ -8,7 +8,6 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
@ -28,6 +27,11 @@ import (
|
|||||||
"imuslab.com/zoraxy/mod/utils"
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CertificateInfoJSON struct {
|
||||||
|
AcmeName string `json:"acme_name"`
|
||||||
|
AcmeUrl string `json:"acme_url"`
|
||||||
|
}
|
||||||
|
|
||||||
// ACMEUser represents a user in the ACME system.
|
// ACMEUser represents a user in the ACME system.
|
||||||
type ACMEUser struct {
|
type ACMEUser struct {
|
||||||
Email string
|
Email string
|
||||||
@ -65,7 +69,7 @@ func NewACME(acmeServer string, port string) *ACMEHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ObtainCert obtains a certificate for the specified domains.
|
// ObtainCert obtains a certificate for the specified domains.
|
||||||
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, ca string) (bool, error) {
|
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string) (bool, error) {
|
||||||
log.Println("[ACME] Obtaining certificate...")
|
log.Println("[ACME] Obtaining certificate...")
|
||||||
|
|
||||||
// generate private key
|
// generate private key
|
||||||
@ -84,17 +88,23 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
|
|||||||
// create config
|
// create config
|
||||||
config := lego.NewConfig(&adminUser)
|
config := lego.NewConfig(&adminUser)
|
||||||
|
|
||||||
// setup who is the issuer and the key type
|
// setup the custom ACME url endpoint.
|
||||||
config.CADirURL = a.DefaultAcmeServer
|
if caUrl != "" {
|
||||||
|
config.CADirURL = caUrl
|
||||||
|
}
|
||||||
|
|
||||||
//Overwrite the CADir URL if set
|
// if not custom ACME url, load it from ca.json
|
||||||
if ca != "" {
|
if caName == "custom" {
|
||||||
caLinkOverwrite, err := loadCAApiServerFromName(ca)
|
log.Println("[INFO] Using Custom ACME" + caUrl + " for CA Directory URL")
|
||||||
|
} else {
|
||||||
|
caLinkOverwrite, err := loadCAApiServerFromName(caName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
config.CADirURL = caLinkOverwrite
|
config.CADirURL = caLinkOverwrite
|
||||||
log.Println("[INFO] Using " + caLinkOverwrite + " for CA Directory URL")
|
log.Println("[INFO] Using " + caLinkOverwrite + " for CA Directory URL")
|
||||||
} else {
|
} else {
|
||||||
return false, errors.New("CA " + ca + " is not supported. Please contribute to the source code and add this CA's directory link.")
|
// (caName == "" || caUrl == "") will use default acme
|
||||||
|
config.CADirURL = a.DefaultAcmeServer
|
||||||
|
log.Println("[INFO] Using Default ACME" + a.DefaultAcmeServer + " for CA Directory URL")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +155,24 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save certificate's ACME info for renew usage
|
||||||
|
certInfo := &CertificateInfoJSON{
|
||||||
|
AcmeName: caName,
|
||||||
|
AcmeUrl: caUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
certInfoBytes, err := json.Marshal(certInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile("./conf/certs/"+certificateName+".json", certInfoBytes, 0777)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,14 +278,24 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var caUrl string
|
||||||
|
|
||||||
ca, err := utils.PostPara(r, "ca")
|
ca, err := utils.PostPara(r, "ca")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("CA not set. Using default (Let's Encrypt)")
|
log.Println("CA not set. Using default")
|
||||||
ca = "Let's Encrypt"
|
ca, caUrl = "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ca == "custom" {
|
||||||
|
caUrl, err = utils.PostPara(r, "ca_url")
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Custom CA set but no URL provide, Using default")
|
||||||
|
ca, caUrl = "", ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
domains := strings.Split(domainPara, ",")
|
domains := strings.Split(domainPara, ",")
|
||||||
result, err := a.ObtainCert(domains, filename, email, ca)
|
result, err := a.ObtainCert(domains, filename, email, ca, caUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.SendErrorResponse(w, jsonEscape(err.Error()))
|
utils.SendErrorResponse(w, jsonEscape(err.Error()))
|
||||||
return
|
return
|
||||||
@ -285,4 +323,20 @@ func IsPortInUse(port int) bool {
|
|||||||
}
|
}
|
||||||
defer listener.Close()
|
defer listener.Close()
|
||||||
return false // Port is not in use
|
return false // Port is not in use
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadCertInfoJSON(filename string) (*CertificateInfoJSON, error) {
|
||||||
|
|
||||||
|
certInfoBytes, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
certInfo := &CertificateInfoJSON{}
|
||||||
|
if err = json.Unmarshal(certInfoBytes, certInfo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return certInfo, nil
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package acme
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
@ -355,7 +356,16 @@ func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, erro
|
|||||||
log.Println("Renewing " + expiredCert.Filepath + " (Might take a few minutes)")
|
log.Println("Renewing " + expiredCert.Filepath + " (Might take a few minutes)")
|
||||||
fileName := filepath.Base(expiredCert.Filepath)
|
fileName := filepath.Base(expiredCert.Filepath)
|
||||||
certName := fileName[:len(fileName)-len(filepath.Ext(fileName))]
|
certName := fileName[:len(fileName)-len(filepath.Ext(fileName))]
|
||||||
_, err := a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, expiredCert.CA)
|
|
||||||
|
// Load certificate info for ACME detail
|
||||||
|
certInfoFilename := fmt.Sprintf("%s/%s.json", filepath.Dir(expiredCert.Filepath), certName)
|
||||||
|
certInfo, err := loadCertInfoJSON(certInfoFilename)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Renew %s certificate error, can't get the ACME detail for cert: %v, using default ACME", certName, err)
|
||||||
|
certInfo = &CertificateInfoJSON{}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, certInfo.AcmeName, certInfo.AcmeUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Renew " + fileName + "(" + strings.Join(expiredCert.Domains, ",") + ") failed: " + err.Error())
|
log.Println("Renew " + fileName + "(" + strings.Join(expiredCert.Domains, ",") + ") failed: " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user