mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
wip: support SAN certifications
This commit is contained in:
parent
d7ce452b8b
commit
7d4999f83a
5 changed files with 114 additions and 128 deletions
|
@ -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"
|
||||
/>
|
||||
<a-alert
|
||||
v-if="no_server_name||server_name_more_than_one"
|
||||
v-if="no_server_name"
|
||||
:message="$gettext('Warning')"
|
||||
type="warning"
|
||||
show-icon
|
||||
|
@ -209,9 +195,6 @@ const modalClosable = ref(false)
|
|||
<span v-if="no_server_name" v-translate>
|
||||
server_name parameter is required
|
||||
</span>
|
||||
<span v-if="server_name_more_than_one" v-translate>
|
||||
server_name parameters more than one
|
||||
</span>
|
||||
</template>
|
||||
</a-alert>
|
||||
</a-form-item>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue