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

This commit is contained in:
Jacky 2024-04-30 17:16:14 +08:00
parent 3e90b838fd
commit 49b41d6eb7
No known key found for this signature in database
GPG key ID: 215C21B10DF38B4D
6 changed files with 60 additions and 57 deletions

View file

@ -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 () => {

View file

@ -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,

View file

@ -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)
}

View file

@ -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
}

View file

@ -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,
},
}
}

View file

@ -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