diff --git a/frontend/src/views/domain/cert/IssueCert.vue b/frontend/src/views/domain/cert/IssueCert.vue index 93c38e85..ffc2c716 100644 --- a/frontend/src/views/domain/cert/IssueCert.vue +++ b/frontend/src/views/domain/cert/IssueCert.vue @@ -31,12 +31,6 @@ function job() { return } - if (server_name_more_than_one.value) { - message.error($gettext('server_name parameters more than one')) - issuing_cert.value = false - return - } - const server_name = props.directivesMap['server_name'][0] if (!props.directivesMap['ssl_certificate']) { @@ -102,10 +96,12 @@ const issue_cert = async (server_name: string, callback: Function) => { log($gettext('Getting the certificate, please wait...')) - const ws = websocket('/api/cert/issue/' + server_name, false) + const ws = websocket('/api/cert/issue', false) ws.onopen = () => { - ws.send('go') + ws.send(JSON.stringify({ + server_name: server_name.trim().split(' ') + })) } ws.onmessage = m => { @@ -132,11 +128,6 @@ const issue_cert = async (server_name: string, callback: Function) => { } } -const server_name_more_than_one = computed(() => { - return props.directivesMap['server_name'] && (props.directivesMap['server_name'].length > 1 || - props.directivesMap['server_name'][0].params.trim().indexOf(' ') > 0) -}) - const no_server_name = computed(() => { return props.directivesMap['server_name'].length === 0 }) @@ -154,11 +145,6 @@ const enabled = computed({ } }) -watch(server_name_more_than_one, () => { - emit('update:enabled', false) - onchange(false) -}) - watch(no_server_name, () => { emit('update:enabled', false) onchange(false) @@ -166,7 +152,7 @@ watch(no_server_name, () => { const progressStrokeColor = { from: '#108ee9', - to: '#87d068', + to: '#87d068' } const progressPercent = ref(0) @@ -197,10 +183,10 @@ const modalClosable = ref(false) :loading="issuing_cert" v-model:checked="enabled" @change="onchange" - :disabled="no_server_name||server_name_more_than_one" + :disabled="no_server_name" /> server_name parameter is required - - server_name parameters more than one - diff --git a/server/api/cert.go b/server/api/cert.go index 201c57ef..7a7ad22f 100644 --- a/server/api/cert.go +++ b/server/api/cert.go @@ -1,140 +1,141 @@ package api import ( - "github.com/0xJacky/Nginx-UI/server/model" - "github.com/0xJacky/Nginx-UI/server/pkg/cert" - "github.com/0xJacky/Nginx-UI/server/pkg/nginx" - "github.com/gin-gonic/gin" - "github.com/gorilla/websocket" - "log" - "net/http" + "github.com/0xJacky/Nginx-UI/server/model" + "github.com/0xJacky/Nginx-UI/server/pkg/cert" + "github.com/0xJacky/Nginx-UI/server/pkg/nginx" + "github.com/gin-gonic/gin" + "github.com/gorilla/websocket" + "log" + "net/http" + "strings" ) const ( - Success = "success" - Info = "info" - Error = "error" + Success = "success" + Info = "info" + Error = "error" ) type IssueCertResponse struct { - Status string `json:"status"` - Message string `json:"message"` - SSLCertificate string `json:"ssl_certificate,omitempty"` - SSLCertificateKey string `json:"ssl_certificate_key,omitempty"` + Status string `json:"status"` + Message string `json:"message"` + SSLCertificate string `json:"ssl_certificate,omitempty"` + SSLCertificateKey string `json:"ssl_certificate_key,omitempty"` } func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) { - defer func() { - if err := recover(); err != nil { - log.Println("api.handleIssueCertLogChan recover", err) - } - }() + defer func() { + if err := recover(); err != nil { + log.Println("api.handleIssueCertLogChan recover", err) + } + }() - for logString := range logChan { + for logString := range logChan { - err := conn.WriteJSON(IssueCertResponse{ - Status: Info, - Message: logString, - }) + err := conn.WriteJSON(IssueCertResponse{ + Status: Info, + Message: logString, + }) - if err != nil { - log.Println("Error handleIssueCertLogChan", err) - return - } + if err != nil { + log.Println("Error handleIssueCertLogChan", err) + return + } - } + } } func IssueCert(c *gin.Context) { - domain := c.Param("domain") + var upGrader = websocket.Upgrader{ + CheckOrigin: func(r *http.Request) bool { + return true + }, + } - var upGrader = websocket.Upgrader{ - CheckOrigin: func(r *http.Request) bool { - return true - }, - } + // upgrade http to websocket + ws, err := upGrader.Upgrade(c.Writer, c.Request, nil) + if err != nil { + log.Println(err) + return + } - // upgrade http to websocket - ws, err := upGrader.Upgrade(c.Writer, c.Request, nil) - if err != nil { - log.Println(err) - return - } + defer func(ws *websocket.Conn) { + err := ws.Close() + if err != nil { + log.Println("defer websocket close err", err) + } + }(ws) - defer func(ws *websocket.Conn) { - err := ws.Close() - if err != nil { - log.Println("defer websocket close err", err) - } - }(ws) + // read + var buffer struct { + ServerName []string `json:"server_name"` + } - // read - mt, message, err := ws.ReadMessage() + err = ws.ReadJSON(&buffer) - if err != nil { - log.Println(err) - return - } + if err != nil { + log.Println(err) + return + } - if mt != websocket.TextMessage || string(message) != "go" { - return - } + logChan := make(chan string, 1) + errChan := make(chan error, 1) - logChan := make(chan string, 1) - errChan := make(chan error, 1) + go cert.IssueCert(buffer.ServerName, logChan, errChan) - go cert.IssueCert(domain, logChan, errChan) + domain := strings.Join(buffer.ServerName, "_") - go handleIssueCertLogChan(ws, logChan) + go handleIssueCertLogChan(ws, logChan) - // block, unless errChan closed - for err = range errChan { - log.Println("Error cert.IssueCert", err) + // block, unless errChan closed + for err = range errChan { + log.Println("Error cert.IssueCert", err) - err = ws.WriteJSON(IssueCertResponse{ - Status: Error, - Message: err.Error(), - }) + err = ws.WriteJSON(IssueCertResponse{ + Status: Error, + Message: err.Error(), + }) - if err != nil { - log.Println(err) - return - } + if err != nil { + log.Println(err) + return + } - return - } + return + } - close(logChan) + close(logChan) - sslCertificatePath := nginx.GetNginxConfPath("ssl/" + domain + "/fullchain.cer") - sslCertificateKeyPath := nginx.GetNginxConfPath("ssl/" + domain + "/" + domain + ".key") + sslCertificatePath := nginx.GetNginxConfPath("ssl/" + domain + "/fullchain.cer") + sslCertificateKeyPath := nginx.GetNginxConfPath("ssl/" + domain + "/" + domain + ".key") - certModel, err := model.FirstCert(domain) + certModel, err := model.FirstCert(domain) - if err != nil { - log.Println(err) - return - } + if err != nil { + log.Println(err) + return + } - err = certModel.Updates(&model.Cert{ - SSLCertificatePath: sslCertificatePath, - }) + err = certModel.Updates(&model.Cert{ + SSLCertificatePath: sslCertificatePath, + }) - if err != nil { - log.Println(err) - return - } + if err != nil { + log.Println(err) + return + } - err = ws.WriteJSON(IssueCertResponse{ - Status: Success, - Message: "Issued certificate successfully", - SSLCertificate: sslCertificatePath, - SSLCertificateKey: sslCertificateKeyPath, - }) + err = ws.WriteJSON(IssueCertResponse{ + Status: Success, + Message: "Issued certificate successfully", + SSLCertificate: sslCertificatePath, + SSLCertificateKey: sslCertificateKeyPath, + }) - if err != nil { - log.Println(err) - return - } + if err != nil { + log.Println(err) + return + } } diff --git a/server/pkg/cert/auto_cert.go b/server/pkg/cert/auto_cert.go index 0ba8a171..97eeecf2 100644 --- a/server/pkg/cert/auto_cert.go +++ b/server/pkg/cert/auto_cert.go @@ -56,7 +56,7 @@ func AutoCert() { logChan := make(chan string, 1) errChan := make(chan error, 1) - go IssueCert(domain, logChan, errChan) + go IssueCert([]string{domain}, logChan, errChan) go handleIssueCertLogChan(logChan) diff --git a/server/pkg/cert/cert.go b/server/pkg/cert/cert.go index de2fbd5c..cbdc9910 100644 --- a/server/pkg/cert/cert.go +++ b/server/pkg/cert/cert.go @@ -16,6 +16,7 @@ import ( "log" "os" "path/filepath" + "strings" ) // MyUser You'll need a user or account type that implements acme.User @@ -35,7 +36,7 @@ func (u *MyUser) GetPrivateKey() crypto.PrivateKey { return u.key } -func IssueCert(domain string, logChan chan string, errChan chan error) { +func IssueCert(domain []string, logChan chan string, errChan chan error) { defer func() { if err := recover(); err != nil { log.Println("Issue Cert recover", err) @@ -94,7 +95,7 @@ func IssueCert(domain string, logChan chan string, errChan chan error) { myUser.Registration = reg request := certificate.ObtainRequest{ - Domains: []string{domain}, + Domains: domain, Bundle: true, } @@ -104,7 +105,8 @@ func IssueCert(domain string, logChan chan string, errChan chan error) { errChan <- errors.Wrap(err, "issue cert fail to obtain") return } - saveDir := nginx.GetNginxConfPath("ssl/" + domain) + name := strings.Join(domain, "_") + saveDir := nginx.GetNginxConfPath("ssl/" + name) if _, err = os.Stat(saveDir); os.IsNotExist(err) { err = os.MkdirAll(saveDir, 0755) if err != nil { @@ -125,7 +127,7 @@ func IssueCert(domain string, logChan chan string, errChan chan error) { } logChan <- "Writing certificate private key to disk" - err = os.WriteFile(filepath.Join(saveDir, domain+".key"), + err = os.WriteFile(filepath.Join(saveDir, name+".key"), certificates.PrivateKey, 0644) if err != nil { diff --git a/server/router/routers.go b/server/router/routers.go index f44fd886..7be56211 100644 --- a/server/router/routers.go +++ b/server/router/routers.go @@ -83,7 +83,7 @@ func InitRouter() *gin.Engine { g.GET("template", api.GetTemplate) - g.GET("cert/issue/:domain", api.IssueCert) + g.GET("cert/issue", api.IssueCert) // Add domain to auto-renew cert list g.POST("cert/:domain", api.AddDomainToAutoCert)