change work dir

This commit is contained in:
0xJacky 2022-02-18 18:04:13 +08:00
parent ce850f5e59
commit 08b54b5bbb
31 changed files with 260 additions and 259 deletions

12
main.go
View file

@ -3,10 +3,10 @@ package main
import ( import (
"context" "context"
"flag" "flag"
"github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/server/model"
"github.com/0xJacky/Nginx-UI/router" "github.com/0xJacky/Nginx-UI/server/router"
"github.com/0xJacky/Nginx-UI/settings" "github.com/0xJacky/Nginx-UI/server/settings"
"github.com/0xJacky/Nginx-UI/tool" tool2 "github.com/0xJacky/Nginx-UI/server/tool"
"log" "log"
"net/http" "net/http"
"os/signal" "os/signal"
@ -31,9 +31,9 @@ func main() {
Handler: router.InitRouter(), Handler: router.InitRouter(),
} }
log.Printf("nginx config dir path: %s", tool.GetNginxConfPath("")) log.Printf("nginx config dir path: %s", tool2.GetNginxConfPath(""))
go tool.AutoCert() go tool2.AutoCert()
// Initializing the server in a goroutine so that // Initializing the server in a goroutine so that
// it won't block the graceful shutdown handling below // it won't block the graceful shutdown handling below

View file

@ -6,5 +6,6 @@ After=network.target
[Service] [Service]
Type=simple Type=simple
ExecStart=/usr/local/bin/nginx-ui -d /usr/local/etc/nginx-ui ExecStart=/usr/local/bin/nginx-ui -d /usr/local/etc/nginx-ui
Restart=on-failure
TimeoutStopSec=5 TimeoutStopSec=5
KillMode=mixed KillMode=mixed

View file

@ -1,7 +1,7 @@
package api package api
import ( import (
"github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/server/model"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"net/http" "net/http"

View file

@ -1,7 +1,7 @@
package api package api
import ( import (
"github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/server/model"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/unknwon/com" "github.com/unknwon/com"
"net/http" "net/http"

View file

@ -2,7 +2,7 @@ package api
import ( import (
"encoding/json" "encoding/json"
"github.com/0xJacky/Nginx-UI/tool" tool2 "github.com/0xJacky/Nginx-UI/server/tool"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"log" "log"
@ -13,7 +13,7 @@ import (
func CertInfo(c *gin.Context) { func CertInfo(c *gin.Context) {
domain := c.Param("domain") domain := c.Param("domain")
key := tool.GetCertInfo(domain) key := tool2.GetCertInfo(domain)
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"subject_name": key.Subject.CommonName, "subject_name": key.Subject.CommonName,
@ -55,7 +55,7 @@ func IssueCert(c *gin.Context) {
if string(message) == "go" { if string(message) == "go" {
var m []byte var m []byte
err = tool.IssueCert(domain) err = tool2.IssueCert(domain)
if err != nil { if err != nil {
m, err = json.Marshal(gin.H{ m, err = json.Marshal(gin.H{
"status": "error", "status": "error",
@ -78,7 +78,7 @@ func IssueCert(c *gin.Context) {
return return
} }
sslCertificatePath := tool.GetNginxConfPath("ssl/" + domain + "/fullchain.cer") sslCertificatePath := tool2.GetNginxConfPath("ssl/" + domain + "/fullchain.cer")
_, err = os.Stat(sslCertificatePath) _, err = os.Stat(sslCertificatePath)
if err != nil { if err != nil {
@ -104,7 +104,7 @@ func IssueCert(c *gin.Context) {
return return
} }
sslCertificateKeyPath := tool.GetNginxConfPath("ssl/" + domain + "/" + domain + ".key") sslCertificateKeyPath := tool2.GetNginxConfPath("ssl/" + domain + "/" + domain + ".key")
_, err = os.Stat(sslCertificateKeyPath) _, err = os.Stat(sslCertificateKeyPath)
if err != nil { if err != nil {

View file

@ -1,7 +1,7 @@
package api package api
import ( import (
"github.com/0xJacky/Nginx-UI/tool" tool2 "github.com/0xJacky/Nginx-UI/server/tool"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"io/ioutil" "io/ioutil"
"log" "log"
@ -19,7 +19,7 @@ func GetConfigs(c *gin.Context) {
"modify": "time", "modify": "time",
} }
configFiles, err := ioutil.ReadDir(tool.GetNginxConfPath("/")) configFiles, err := ioutil.ReadDir(tool2.GetNginxConfPath("/"))
if err != nil { if err != nil {
ErrHandler(c, err) ErrHandler(c, err)
@ -40,7 +40,7 @@ func GetConfigs(c *gin.Context) {
} }
} }
configs = tool.Sort(orderBy, sort, mySort[orderBy], configs) configs = tool2.Sort(orderBy, sort, mySort[orderBy], configs)
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"configs": configs, "configs": configs,
@ -49,7 +49,7 @@ func GetConfigs(c *gin.Context) {
func GetConfig(c *gin.Context) { func GetConfig(c *gin.Context) {
name := c.Param("name") name := c.Param("name")
path := filepath.Join(tool.GetNginxConfPath("/"), name) path := filepath.Join(tool2.GetNginxConfPath("/"), name)
content, err := ioutil.ReadFile(path) content, err := ioutil.ReadFile(path)
@ -80,7 +80,7 @@ func AddConfig(c *gin.Context) {
name := request.Name name := request.Name
content := request.Content content := request.Content
path := filepath.Join(tool.GetNginxConfPath("/"), name) path := filepath.Join(tool2.GetNginxConfPath("/"), name)
log.Println(path) log.Println(path)
if _, err = os.Stat(path); err == nil { if _, err = os.Stat(path); err == nil {
@ -98,7 +98,7 @@ func AddConfig(c *gin.Context) {
} }
} }
output := tool.ReloadNginx() output := tool2.ReloadNginx()
if output != "" { if output != "" {
c.JSON(http.StatusInternalServerError, gin.H{ c.JSON(http.StatusInternalServerError, gin.H{
@ -126,7 +126,7 @@ func EditConfig(c *gin.Context) {
ErrHandler(c, err) ErrHandler(c, err)
return return
} }
path := filepath.Join(tool.GetNginxConfPath("/"), name) path := filepath.Join(tool2.GetNginxConfPath("/"), name)
content := request.Content content := request.Content
origContent, err := ioutil.ReadFile(path) origContent, err := ioutil.ReadFile(path)
@ -144,7 +144,7 @@ func EditConfig(c *gin.Context) {
} }
} }
output := tool.ReloadNginx() output := tool2.ReloadNginx()
if output != "" { if output != "" {
c.JSON(http.StatusInternalServerError, gin.H{ c.JSON(http.StatusInternalServerError, gin.H{

View file

@ -1,8 +1,8 @@
package api package api
import ( import (
"github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/server/model"
"github.com/0xJacky/Nginx-UI/tool" tool2 "github.com/0xJacky/Nginx-UI/server/tool"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -20,14 +20,14 @@ func GetDomains(c *gin.Context) {
"modify": "time", "modify": "time",
} }
configFiles, err := ioutil.ReadDir(tool.GetNginxConfPath("sites-available")) configFiles, err := ioutil.ReadDir(tool2.GetNginxConfPath("sites-available"))
if err != nil { if err != nil {
ErrHandler(c, err) ErrHandler(c, err)
return return
} }
enabledConfig, err := ioutil.ReadDir(filepath.Join(tool.GetNginxConfPath("sites-enabled"))) enabledConfig, err := ioutil.ReadDir(filepath.Join(tool2.GetNginxConfPath("sites-enabled")))
enabledConfigMap := make(map[string]bool) enabledConfigMap := make(map[string]bool)
for i := range enabledConfig { for i := range enabledConfig {
@ -53,7 +53,7 @@ func GetDomains(c *gin.Context) {
} }
} }
configs = tool.Sort(orderBy, sort, mySort[orderBy], configs) configs = tool2.Sort(orderBy, sort, mySort[orderBy], configs)
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"configs": configs, "configs": configs,
@ -62,10 +62,10 @@ func GetDomains(c *gin.Context) {
func GetDomain(c *gin.Context) { func GetDomain(c *gin.Context) {
name := c.Param("name") name := c.Param("name")
path := filepath.Join(tool.GetNginxConfPath("sites-available"), name) path := filepath.Join(tool2.GetNginxConfPath("sites-available"), name)
enabled := true enabled := true
if _, err := os.Stat(filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) { if _, err := os.Stat(filepath.Join(tool2.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) {
enabled = false enabled = false
} }
@ -98,7 +98,7 @@ func EditDomain(c *gin.Context) {
name := c.Param("name") name := c.Param("name")
request := make(gin.H) request := make(gin.H)
err = c.BindJSON(&request) err = c.BindJSON(&request)
path := filepath.Join(tool.GetNginxConfPath("sites-available"), name) path := filepath.Join(tool2.GetNginxConfPath("sites-available"), name)
err = ioutil.WriteFile(path, []byte(request["content"].(string)), 0644) err = ioutil.WriteFile(path, []byte(request["content"].(string)), 0644)
if err != nil { if err != nil {
@ -106,10 +106,10 @@ func EditDomain(c *gin.Context) {
return return
} }
enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), name) enabledConfigFilePath := filepath.Join(tool2.GetNginxConfPath("sites-enabled"), name)
if _, err = os.Stat(enabledConfigFilePath); err == nil { if _, err = os.Stat(enabledConfigFilePath); err == nil {
// 测试配置文件 // 测试配置文件
err = tool.TestNginxConf(enabledConfigFilePath) err = tool2.TestNginxConf(enabledConfigFilePath)
if err != nil { if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{ c.JSON(http.StatusInternalServerError, gin.H{
"message": err.Error(), "message": err.Error(),
@ -117,7 +117,7 @@ func EditDomain(c *gin.Context) {
return return
} }
output := tool.ReloadNginx() output := tool2.ReloadNginx()
if output != "" { if output != "" {
c.JSON(http.StatusInternalServerError, gin.H{ c.JSON(http.StatusInternalServerError, gin.H{
@ -131,8 +131,8 @@ func EditDomain(c *gin.Context) {
} }
func EnableDomain(c *gin.Context) { func EnableDomain(c *gin.Context) {
configFilePath := filepath.Join(tool.GetNginxConfPath("sites-available"), c.Param("name")) configFilePath := filepath.Join(tool2.GetNginxConfPath("sites-available"), c.Param("name"))
enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), c.Param("name")) enabledConfigFilePath := filepath.Join(tool2.GetNginxConfPath("sites-enabled"), c.Param("name"))
_, err := os.Stat(configFilePath) _, err := os.Stat(configFilePath)
@ -149,7 +149,7 @@ func EnableDomain(c *gin.Context) {
} }
// 测试配置文件,不通过则撤回启用 // 测试配置文件,不通过则撤回启用
err = tool.TestNginxConf(enabledConfigFilePath) err = tool2.TestNginxConf(enabledConfigFilePath)
if err != nil { if err != nil {
_ = os.Remove(enabledConfigFilePath) _ = os.Remove(enabledConfigFilePath)
c.JSON(http.StatusInternalServerError, gin.H{ c.JSON(http.StatusInternalServerError, gin.H{
@ -158,7 +158,7 @@ func EnableDomain(c *gin.Context) {
return return
} }
output := tool.ReloadNginx() output := tool2.ReloadNginx()
if output != "" { if output != "" {
c.JSON(http.StatusInternalServerError, gin.H{ c.JSON(http.StatusInternalServerError, gin.H{
@ -173,7 +173,7 @@ func EnableDomain(c *gin.Context) {
} }
func DisableDomain(c *gin.Context) { func DisableDomain(c *gin.Context) {
enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), c.Param("name")) enabledConfigFilePath := filepath.Join(tool2.GetNginxConfPath("sites-enabled"), c.Param("name"))
_, err := os.Stat(enabledConfigFilePath) _, err := os.Stat(enabledConfigFilePath)
@ -189,7 +189,7 @@ func DisableDomain(c *gin.Context) {
return return
} }
output := tool.ReloadNginx() output := tool2.ReloadNginx()
if output != "" { if output != "" {
c.JSON(http.StatusInternalServerError, gin.H{ c.JSON(http.StatusInternalServerError, gin.H{
@ -206,8 +206,8 @@ func DisableDomain(c *gin.Context) {
func DeleteDomain(c *gin.Context) { func DeleteDomain(c *gin.Context) {
var err error var err error
name := c.Param("name") name := c.Param("name")
availablePath := filepath.Join(tool.GetNginxConfPath("sites-available"), name) availablePath := filepath.Join(tool2.GetNginxConfPath("sites-available"), name)
enabledPath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), name) enabledPath := filepath.Join(tool2.GetNginxConfPath("sites-enabled"), name)
if _, err = os.Stat(availablePath); os.IsNotExist(err) { if _, err = os.Stat(availablePath); os.IsNotExist(err) {
c.JSON(http.StatusNotFound, gin.H{ c.JSON(http.StatusNotFound, gin.H{

View file

@ -1,8 +1,8 @@
package api package api
import ( import (
"github.com/0xJacky/Nginx-UI/model" model2 "github.com/0xJacky/Nginx-UI/server/model"
"github.com/0xJacky/Nginx-UI/settings" "github.com/0xJacky/Nginx-UI/server/settings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@ -54,9 +54,9 @@ func InstallNginxUI(c *gin.Context) {
return return
} }
curd := model.NewCurd(&model.Auth{}) curd := model2.NewCurd(&model2.Auth{})
pwd, _ := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost) pwd, _ := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
err = curd.Add(&model.Auth{ err = curd.Add(&model2.Auth{
Name: json.Username, Name: json.Username,
Password: string(pwd), Password: string(pwd),
}) })

View file

@ -1,7 +1,7 @@
package api package api
import ( import (
"github.com/0xJacky/Nginx-UI/settings" "github.com/0xJacky/Nginx-UI/server/settings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"io/ioutil" "io/ioutil"
"net/http" "net/http"

View file

@ -2,7 +2,7 @@ package api
import ( import (
"errors" "errors"
"github.com/0xJacky/Nginx-UI/model" model2 "github.com/0xJacky/Nginx-UI/server/model"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/spf13/cast" "github.com/spf13/cast"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@ -10,9 +10,9 @@ import (
) )
func GetUsers(c *gin.Context) { func GetUsers(c *gin.Context) {
curd := model.NewCurd(&model.Auth{}) curd := model2.NewCurd(&model2.Auth{})
var list []model.Auth var list []model2.Auth
err := curd.GetList(&list) err := curd.GetList(&list)
if err != nil { if err != nil {
@ -25,10 +25,10 @@ func GetUsers(c *gin.Context) {
} }
func GetUser(c *gin.Context) { func GetUser(c *gin.Context) {
curd := model.NewCurd(&model.Auth{}) curd := model2.NewCurd(&model2.Auth{})
id := c.Param("id") id := c.Param("id")
var user model.Auth var user model2.Auth
err := curd.First(&user, id) err := curd.First(&user, id)
if err != nil { if err != nil {
@ -49,7 +49,7 @@ func AddUser(c *gin.Context) {
if !ok { if !ok {
return return
} }
curd := model.NewCurd(&model.Auth{}) curd := model2.NewCurd(&model2.Auth{})
pwd, err := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost) pwd, err := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
if err != nil { if err != nil {
@ -58,7 +58,7 @@ func AddUser(c *gin.Context) {
} }
json.Password = string(pwd) json.Password = string(pwd)
user := model.Auth{ user := model2.Auth{
Name: json.Name, Name: json.Name,
Password: json.Password, Password: json.Password,
} }
@ -80,9 +80,9 @@ func EditUser(c *gin.Context) {
if !ok { if !ok {
return return
} }
curd := model.NewCurd(&model.Auth{}) curd := model2.NewCurd(&model2.Auth{})
var user, edit model.Auth var user, edit model2.Auth
err := curd.First(&user, c.Param("id")) err := curd.First(&user, c.Param("id"))
@ -120,8 +120,8 @@ func DeleteUser(c *gin.Context) {
ErrHandler(c, errors.New("不允许删除默认账户")) ErrHandler(c, errors.New("不允许删除默认账户"))
return return
} }
curd := model.NewCurd(&model.Auth{}) curd := model2.NewCurd(&model2.Auth{})
err := curd.Delete(&model.Auth{}, "id", id) err := curd.Delete(&model2.Auth{}, "id", id)
if err != nil { if err != nil {
ErrHandler(c, err) ErrHandler(c, err)
return return

View file

@ -1,7 +1,7 @@
package model package model
import ( import (
"github.com/0xJacky/Nginx-UI/settings" "github.com/0xJacky/Nginx-UI/server/settings"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"time" "time"
) )

View file

@ -1,7 +1,7 @@
package model package model
import ( import (
"github.com/0xJacky/Nginx-UI/settings" "github.com/0xJacky/Nginx-UI/server/settings"
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"

View file

@ -3,9 +3,9 @@ package router
import ( import (
"bufio" "bufio"
"encoding/base64" "encoding/base64"
"github.com/0xJacky/Nginx-UI/api"
"github.com/0xJacky/Nginx-UI/frontend" "github.com/0xJacky/Nginx-UI/frontend"
"github.com/0xJacky/Nginx-UI/model" api2 "github.com/0xJacky/Nginx-UI/server/api"
"github.com/0xJacky/Nginx-UI/server/model"
"github.com/gin-contrib/static" "github.com/gin-contrib/static"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"io/fs" "io/fs"
@ -87,46 +87,46 @@ func InitRouter() *gin.Engine {
g := r.Group("/api") g := r.Group("/api")
{ {
g.GET("install", api.InstallLockCheck) g.GET("install", api2.InstallLockCheck)
g.POST("install", api.InstallNginxUI) g.POST("install", api2.InstallNginxUI)
g.POST("/login", api.Login) g.POST("/login", api2.Login)
g.DELETE("/logout", api.Logout) g.DELETE("/logout", api2.Logout)
g := g.Group("/", authRequired()) g := g.Group("/", authRequired())
{ {
g.GET("/analytic", api.Analytic) g.GET("/analytic", api2.Analytic)
g.GET("/users", api.GetUsers) g.GET("/users", api2.GetUsers)
g.GET("/user/:id", api.GetUser) g.GET("/user/:id", api2.GetUser)
g.POST("/user", api.AddUser) g.POST("/user", api2.AddUser)
g.POST("/user/:id", api.EditUser) g.POST("/user/:id", api2.EditUser)
g.DELETE("/user/:id", api.DeleteUser) g.DELETE("/user/:id", api2.DeleteUser)
g.GET("domains", api.GetDomains) g.GET("domains", api2.GetDomains)
g.GET("domain/:name", api.GetDomain) g.GET("domain/:name", api2.GetDomain)
g.POST("domain/:name", api.EditDomain) g.POST("domain/:name", api2.EditDomain)
g.POST("domain/:name/enable", api.EnableDomain) g.POST("domain/:name/enable", api2.EnableDomain)
g.POST("domain/:name/disable", api.DisableDomain) g.POST("domain/:name/disable", api2.DisableDomain)
g.DELETE("domain/:name", api.DeleteDomain) g.DELETE("domain/:name", api2.DeleteDomain)
g.GET("configs", api.GetConfigs) g.GET("configs", api2.GetConfigs)
g.GET("config/:name", api.GetConfig) g.GET("config/:name", api2.GetConfig)
g.POST("config", api.AddConfig) g.POST("config", api2.AddConfig)
g.POST("config/:name", api.EditConfig) g.POST("config/:name", api2.EditConfig)
g.GET("backups", api.GetFileBackupList) g.GET("backups", api2.GetFileBackupList)
g.GET("backup/:id", api.GetFileBackup) g.GET("backup/:id", api2.GetFileBackup)
g.GET("template/:name", api.GetTemplate) g.GET("template/:name", api2.GetTemplate)
g.GET("cert/issue/:domain", api.IssueCert) g.GET("cert/issue/:domain", api2.IssueCert)
g.GET("cert/:domain/info", api.CertInfo) g.GET("cert/:domain/info", api2.CertInfo)
// 添加域名到自动续期列表 // 添加域名到自动续期列表
g.POST("cert/:domain", api.AddDomainToAutoCert) g.POST("cert/:domain", api2.AddDomainToAutoCert)
// 从自动续期列表中删除域名 // 从自动续期列表中删除域名
g.DELETE("cert/:domain", api.RemoveDomainFromAutoCert) g.DELETE("cert/:domain", api2.RemoveDomainFromAutoCert)
} }
} }

View file

@ -2,7 +2,7 @@ package test
import ( import (
"fmt" "fmt"
"github.com/0xJacky/Nginx-UI/tool" "github.com/0xJacky/Nginx-UI/server/tool"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"

View file

@ -2,7 +2,7 @@ package test
import ( import (
"fmt" "fmt"
"github.com/0xJacky/Nginx-UI/tool" "github.com/0xJacky/Nginx-UI/server/tool"
"log" "log"
"os" "os"
"os/exec" "os/exec"

169
server/tool/cert.go Normal file
View file

@ -0,0 +1,169 @@
package tool
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"github.com/0xJacky/Nginx-UI/server/model"
"github.com/0xJacky/Nginx-UI/server/settings"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge/http01"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"time"
)
// MyUser You'll need a user or account type that implements acme.User
type MyUser struct {
Email string
Registration *registration.Resource
key crypto.PrivateKey
}
func (u *MyUser) GetEmail() string {
return u.Email
}
func (u MyUser) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
return u.key
}
func AutoCert() {
for {
log.Println("[AutoCert] Start")
autoCertList := model.GetAutoCertList()
for i := range autoCertList {
domain := autoCertList[i].Domain
key := GetCertInfo(domain)
// 未到一个月
if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
continue
}
// 过一个月了
err := IssueCert(domain)
if err != nil {
log.Println(err)
}
}
time.Sleep(1 * time.Hour)
}
}
func GetCertInfo(domain string) (key *x509.Certificate) {
ts := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: ts}
response, err := client.Get("https://" + domain)
if err != nil {
return
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
log.Println(err)
return
}
}(response.Body)
key = response.TLS.PeerCertificates[0]
return
}
func IssueCert(domain string) error {
// Create a user. New accounts need an email and private key to start.
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Println(err)
return err
}
myUser := MyUser{
Email: settings.ServerSettings.Email,
key: privateKey,
}
config := lego.NewConfig(&myUser)
//config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
config.Certificate.KeyType = certcrypto.RSA2048
// A client facilitates communication with the CA server.
client, err := lego.NewClient(config)
if err != nil {
log.Println(err)
return err
}
err = client.Challenge.SetHTTP01Provider(
http01.NewProviderServer("",
settings.ServerSettings.HTTPChallengePort,
),
)
if err != nil {
log.Println(err)
return err
}
// New users will need to register
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
log.Println(err)
return err
}
myUser.Registration = reg
request := certificate.ObtainRequest{
Domains: []string{domain},
Bundle: true,
}
certificates, err := client.Certificate.Obtain(request)
if err != nil {
log.Println(err)
return err
}
saveDir := GetNginxConfPath("ssl/" + domain)
if _, err := os.Stat(saveDir); os.IsNotExist(err) {
err = os.Mkdir(saveDir, 0755)
if err != nil {
log.Println("fail to create", saveDir)
return err
}
}
// Each certificate comes back with the cert bytes, the bytes of the client's
// private key, and a certificate URL. SAVE THESE TO DISK.
err = ioutil.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
certificates.Certificate, 0644)
if err != nil {
log.Println(err)
return err
}
err = ioutil.WriteFile(filepath.Join(saveDir, domain+".key"),
certificates.PrivateKey, 0644)
if err != nil {
log.Println(err)
return err
}
ReloadNginx()
return nil
}

View file

@ -1,169 +0,0 @@
package tool
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"github.com/0xJacky/Nginx-UI/model"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge/http01"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"time"
)
// MyUser You'll need a user or account type that implements acme.User
type MyUser struct {
Email string
Registration *registration.Resource
key crypto.PrivateKey
}
func (u *MyUser) GetEmail() string {
return u.Email
}
func (u MyUser) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
return u.key
}
func AutoCert() {
for {
log.Println("[AutoCert] Start")
autoCertList := model.GetAutoCertList()
for i := range autoCertList {
domain := autoCertList[i].Domain
key := GetCertInfo(domain)
// 未到一个月
if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
continue
}
// 过一个月了
err := IssueCert(domain)
if err != nil {
log.Println(err)
}
}
time.Sleep(1 * time.Hour)
}
}
func GetCertInfo(domain string) (key *x509.Certificate) {
ts := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: ts}
response, err := client.Get("https://" + domain)
if err != nil {
return
}
defer func(Body io.ReadCloser) {
err = Body.Close()
if err != nil {
log.Println(err)
return
}
}(response.Body)
key = response.TLS.PeerCertificates[0]
return
}
func IssueCert(domain string) error {
// Create a user. New accounts need an email and private key to start.
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Println(err)
return err
}
myUser := MyUser{
Email: settings.ServerSettings.Email,
key: privateKey,
}
config := lego.NewConfig(&myUser)
//config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
config.Certificate.KeyType = certcrypto.RSA2048
// A client facilitates communication with the CA server.
client, err := lego.NewClient(config)
if err != nil {
log.Println(err)
return err
}
err = client.Challenge.SetHTTP01Provider(
http01.NewProviderServer("",
settings.ServerSettings.HTTPChallengePort,
),
)
if err != nil {
log.Println(err)
return err
}
// New users will need to register
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
log.Println(err)
return err
}
myUser.Registration = reg
request := certificate.ObtainRequest{
Domains: []string{domain},
Bundle: true,
}
certificates, err := client.Certificate.Obtain(request)
if err != nil {
log.Println(err)
return err
}
saveDir := GetNginxConfPath("ssl/" + domain)
if _, err := os.Stat(saveDir); os.IsNotExist(err) {
err = os.Mkdir(saveDir, 0755)
if err != nil {
log.Println("fail to create", saveDir)
return err
}
}
// Each certificate comes back with the cert bytes, the bytes of the client's
// private key, and a certificate URL. SAVE THESE TO DISK.
err = ioutil.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
certificates.Certificate, 0644)
if err != nil {
log.Println(err)
return err
}
err = ioutil.WriteFile(filepath.Join(saveDir, domain+".key"),
certificates.PrivateKey, 0644)
if err != nil {
log.Println(err)
return err
}
ReloadNginx()
return nil
}