mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-10 18:05:48 +02:00
137 lines
3.4 KiB
Go
137 lines
3.4 KiB
Go
package cert
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/0xJacky/Nginx-UI/internal/helper"
|
|
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
|
"github.com/0xJacky/Nginx-UI/internal/notification"
|
|
"github.com/0xJacky/Nginx-UI/internal/transport"
|
|
"github.com/0xJacky/Nginx-UI/model"
|
|
"github.com/0xJacky/Nginx-UI/query"
|
|
"github.com/go-acme/lego/v4/certcrypto"
|
|
"github.com/uozi-tech/cosy/logger"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
)
|
|
|
|
type SyncCertificatePayload struct {
|
|
Name string `json:"name"`
|
|
SSLCertificatePath string `json:"ssl_certificate_path"`
|
|
SSLCertificateKeyPath string `json:"ssl_certificate_key_path"`
|
|
SSLCertificate string `json:"ssl_certificate"`
|
|
SSLCertificateKey string `json:"ssl_certificate_key"`
|
|
KeyType certcrypto.KeyType `json:"key_type"`
|
|
}
|
|
|
|
func SyncToRemoteServer(c *model.Cert) (err error) {
|
|
if c.SSLCertificatePath == "" || c.SSLCertificateKeyPath == "" || len(c.SyncNodeIds) == 0 {
|
|
return
|
|
}
|
|
|
|
nginxConfPath := nginx.GetConfPath()
|
|
if !helper.IsUnderDirectory(c.SSLCertificatePath, nginxConfPath) {
|
|
return fmt.Errorf("ssl_certificate_path: %s is not under the nginx conf path: %s",
|
|
c.SSLCertificatePath, nginxConfPath)
|
|
}
|
|
|
|
if !helper.IsUnderDirectory(c.SSLCertificateKeyPath, nginxConfPath) {
|
|
return fmt.Errorf("ssl_certificate_key_path: %s is not under the nginx conf path: %s",
|
|
c.SSLCertificateKeyPath, nginxConfPath)
|
|
}
|
|
|
|
certBytes, err := os.ReadFile(c.SSLCertificatePath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
keyBytes, err := os.ReadFile(c.SSLCertificateKeyPath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
payload := &SyncCertificatePayload{
|
|
Name: c.Name,
|
|
SSLCertificatePath: c.SSLCertificatePath,
|
|
SSLCertificateKeyPath: c.SSLCertificateKeyPath,
|
|
SSLCertificate: string(certBytes),
|
|
SSLCertificateKey: string(keyBytes),
|
|
KeyType: c.KeyType,
|
|
}
|
|
|
|
payloadBytes, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
q := query.Environment
|
|
envs, _ := q.Where(q.ID.In(c.SyncNodeIds...)).Find()
|
|
for _, env := range envs {
|
|
go func() {
|
|
err := deploy(env, c, payloadBytes)
|
|
if err != nil {
|
|
logger.Error(err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
type SyncNotificationPayload struct {
|
|
StatusCode int `json:"status_code"`
|
|
CertName string `json:"cert_name"`
|
|
EnvName string `json:"env_name"`
|
|
RespBody string `json:"resp_body"`
|
|
}
|
|
|
|
func deploy(env *model.Environment, c *model.Cert, payloadBytes []byte) (err error) {
|
|
t, err := transport.NewTransport()
|
|
if err != nil {
|
|
return
|
|
}
|
|
client := http.Client{
|
|
Transport: t,
|
|
}
|
|
url, err := env.GetUrl("/api/cert_sync")
|
|
if err != nil {
|
|
return
|
|
}
|
|
req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(payloadBytes))
|
|
if err != nil {
|
|
return
|
|
}
|
|
req.Header.Set("X-Node-Secret", env.Token)
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
respBody, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
notificationPayload := &SyncNotificationPayload{
|
|
StatusCode: resp.StatusCode,
|
|
CertName: c.Name,
|
|
EnvName: env.Name,
|
|
RespBody: string(respBody),
|
|
}
|
|
|
|
notificationPayloadBytes, err := json.Marshal(notificationPayload)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
notification.Error("Sync Certificate Error", string(notificationPayloadBytes))
|
|
return
|
|
}
|
|
|
|
notification.Success("Sync Certificate Success", string(notificationPayloadBytes))
|
|
|
|
return
|
|
}
|