فهرست منبع

feat: support not-only Let's Encrypt service #16

Jacky 1 سال پیش
والد
کامیت
49b41d6eb7
6فایلهای تغییر یافته به همراه60 افزوده شده و 57 حذف شده
  1. 2 3
      app/src/views/certificate/ACMEUserSelector.vue
  2. 8 29
      internal/cert/cert.go
  3. 20 0
      internal/cert/payload.go
  4. 18 7
      internal/cert/register.go
  5. 0 18
      internal/cert/user.go
  6. 12 0
      model/acme_user.go

+ 2 - 3
app/src/views/certificate/ACMEUserSelector.vue

@@ -34,9 +34,8 @@ const mounted = ref(false)
 watch(id, init)
 
 watch(current, () => {
-  data.value.acme_user_id = current.value.id
-  if (!mounted.value)
-    data.value.acme_user_id = 0
+  if (mounted.value)
+    data.value.acme_user_id = current.value.id
 })
 
 onMounted(async () => {

+ 8 - 29
internal/cert/cert.go

@@ -1,14 +1,10 @@
 package cert
 
 import (
-	"crypto/ecdsa"
-	"crypto/elliptic"
-	"crypto/rand"
 	"crypto/tls"
 	"github.com/0xJacky/Nginx-UI/internal/cert/dns"
 	"github.com/0xJacky/Nginx-UI/internal/logger"
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
-	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/0xJacky/Nginx-UI/settings"
 	"github.com/go-acme/lego/v4/certificate"
@@ -16,7 +12,6 @@ import (
 	"github.com/go-acme/lego/v4/lego"
 	legolog "github.com/go-acme/lego/v4/log"
 	dnsproviders "github.com/go-acme/lego/v4/providers/dns"
-	"github.com/go-acme/lego/v4/registration"
 	"github.com/pkg/errors"
 	"log"
 	"net/http"
@@ -51,22 +46,13 @@ func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error)
 
 	domain := payload.ServerName
 
-	// Create a user. New accounts need an email and private key to start.
-	l.Println("[INFO] [Nginx UI] Generating private key for registering account")
-	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	l.Println("[INFO] [Nginx UI] Preparing lego configurations")
+	user, err := payload.GetACMEUser()
 	if err != nil {
-		errChan <- errors.Wrap(err, "issue cert generate key error")
+		errChan <- errors.Wrap(err, "issue cert get acme user error")
 		return
 	}
-
-	l.Println("[INFO] [Nginx UI] Preparing lego configurations")
-	user := newUser(settings.ServerSettings.Email)
-
-	user.Key = model.PrivateKey{
-		X: privateKey.PublicKey.X,
-		Y: privateKey.PublicKey.Y,
-		D: privateKey.D,
-	}
+	l.Printf("[INFO] [Nginx UI] ACME User: %s, CA Dir: %s\n", user.Email, user.CADir)
 
 	// Start a goroutine to fetch and process logs from channel
 	go func() {
@@ -77,14 +63,16 @@ func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error)
 
 	config := lego.NewConfig(user)
 
-	config.CADirURL = settings.ServerSettings.GetCADir()
+	config.CADirURL = user.CADir
+
+	// Skip TLS check
 	if config.HTTPClient != nil {
 		config.HTTPClient.Transport = &http.Transport{
 			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
 		}
 	}
 
-	config.Certificate.KeyType = payload.KeyType
+	config.Certificate.KeyType = payload.GetKeyType()
 
 	l.Println("[INFO] [Nginx UI] Creating client facilitates communication with the CA server")
 	// A client facilitates communication with the CA server.
@@ -146,15 +134,6 @@ func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error)
 		return
 	}
 
-	// New users will need to register
-	l.Println("[INFO] [Nginx UI] Registering user")
-	reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
-	if err != nil {
-		errChan <- errors.Wrap(err, "register error")
-		return
-	}
-	user.Registration = *reg
-
 	request := certificate.ObtainRequest{
 		Domains: domain,
 		Bundle:  true,

+ 20 - 0
internal/cert/payload.go

@@ -2,6 +2,9 @@ package cert
 
 import (
 	"github.com/0xJacky/Nginx-UI/internal/helper"
+	"github.com/0xJacky/Nginx-UI/internal/logger"
+	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/go-acme/lego/v4/certcrypto"
 )
 
@@ -9,9 +12,26 @@ type ConfigPayload struct {
 	ServerName      []string           `json:"server_name"`
 	ChallengeMethod string             `json:"challenge_method"`
 	DNSCredentialID int                `json:"dns_credential_id"`
+	ACMEUserID      int                `json:"acme_user_id"`
 	KeyType         certcrypto.KeyType `json:"key_type"`
 }
 
+func (c *ConfigPayload) GetACMEUser() (user *model.AcmeUser, err error) {
+	u := query.AcmeUser
+	// if acme_user_id == 0, use default user
+	if c.ACMEUserID == 0 {
+		return GetDefaultACMEUser()
+	}
+	// use the acme_user_id to get the acme user
+	user, err = u.Where(u.ID.Eq(c.ACMEUserID)).First()
+	// if acme_user not exist, use default user
+	if err != nil {
+		logger.Error(err)
+		return GetDefaultACMEUser()
+	}
+	return
+}
+
 func (c *ConfigPayload) GetKeyType() certcrypto.KeyType {
 	return helper.GetKeyType(c.KeyType)
 }

+ 18 - 7
internal/cert/register.go

@@ -29,12 +29,10 @@ func InitRegister() {
 	}
 
 	// Create a new user
-	user := &User{
-		AcmeUser: model.AcmeUser{
-			Name:  "System Initial User",
-			Email: settings.ServerSettings.Email,
-			CADir: settings.ServerSettings.GetCADir(),
-		},
+	user := &model.AcmeUser{
+		Name:  "System Initial User",
+		Email: settings.ServerSettings.Email,
+		CADir: settings.ServerSettings.GetCADir(),
 	}
 
 	err = user.Register()
@@ -43,7 +41,7 @@ func InitRegister() {
 		return
 	}
 
-	err = u.Create(&user.AcmeUser)
+	err = u.Create(user)
 	if err != nil {
 		logger.Error(err)
 		return
@@ -51,3 +49,16 @@ func InitRegister() {
 
 	logger.Info("ACME Default User registered")
 }
+
+func GetDefaultACMEUser() (user *model.AcmeUser, err error) {
+	u := query.AcmeUser
+	user, err = u.Where(u.Email.Eq(settings.ServerSettings.Email),
+		u.CADir.Eq(settings.ServerSettings.GetCADir())).First()
+
+	if err != nil {
+		err = errors.Wrap(err, "get default user error")
+		return
+	}
+
+	return
+}

+ 0 - 18
internal/cert/user.go

@@ -1,18 +0,0 @@
-package cert
-
-import (
-    "github.com/0xJacky/Nginx-UI/model"
-)
-
-// User You'll need a user or account type that implements acme.User
-type User struct {
-    model.AcmeUser
-}
-
-func newUser(email string) *User {
-    return &User{
-        AcmeUser: model.AcmeUser{
-            Email: email,
-        },
-    }
-}

+ 12 - 0
model/acme_user.go

@@ -5,9 +5,11 @@ import (
 	"crypto/ecdsa"
 	"crypto/elliptic"
 	"crypto/rand"
+	"crypto/tls"
 	"github.com/go-acme/lego/v4/lego"
 	"github.com/go-acme/lego/v4/registration"
 	"math/big"
+	"net/http"
 )
 
 type PrivateKey struct {
@@ -55,6 +57,16 @@ func (u *AcmeUser) Register() error {
 	}
 
 	config := lego.NewConfig(u)
+	config.CADirURL = u.CADir
+	u.Registration = registration.Resource{}
+
+	// Skip TLS check
+	if config.HTTPClient != nil {
+		config.HTTPClient.Transport = &http.Transport{
+			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+		}
+	}
+
 	client, err := lego.NewClient(config)
 	if err != nil {
 		return err