diff --git a/app/src/views/certificate/ACMEUserSelector.vue b/app/src/views/certificate/ACMEUserSelector.vue index f87f9302c..215c31e72 100644 --- a/app/src/views/certificate/ACMEUserSelector.vue +++ b/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 () => { diff --git a/internal/cert/cert.go b/internal/cert/cert.go index 3664b1250..f8b80ad2f 100644 --- a/internal/cert/cert.go +++ b/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, diff --git a/internal/cert/payload.go b/internal/cert/payload.go index ade08fc7c..730d4c40c 100644 --- a/internal/cert/payload.go +++ b/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) } diff --git a/internal/cert/register.go b/internal/cert/register.go index 45b4ee025..3cddd7ea6 100644 --- a/internal/cert/register.go +++ b/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 +} diff --git a/internal/cert/user.go b/internal/cert/user.go deleted file mode 100644 index 20ff556f4..000000000 --- a/internal/cert/user.go +++ /dev/null @@ -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, - }, - } -} diff --git a/model/acme_user.go b/model/acme_user.go index 8e80a9ece..ac86c98ef 100644 --- a/model/acme_user.go +++ b/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