From d4e52a2d871ccaa15f8822374505379cb4fbdd5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Mon, 24 Jun 2024 23:46:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20ZeroSSL=E6=94=AF=E6=8C=81=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=8E=B7=E5=8F=96EAB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/http/requests/cert/user_store.go | 4 +-- app/http/requests/cert/user_update.go | 4 +-- internal/services/cert.go | 38 +++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/app/http/requests/cert/user_store.go b/app/http/requests/cert/user_store.go index bb7e1585..06335266 100644 --- a/app/http/requests/cert/user_store.go +++ b/app/http/requests/cert/user_store.go @@ -21,8 +21,8 @@ func (r *UserStore) Rules(ctx http.Context) map[string]string { return map[string]string{ "ca": "required|in:letsencrypt,zerossl,sslcom,google,buypass", "email": "required|email", - "kid": "required_unless:ca,letsencrypt,buypass", - "hmac_encoded": "required_unless:ca,letsencrypt,buypass", + "kid": "required_if:ca,sslcom,google", + "hmac_encoded": "required_if:ca,sslcom,google", "key_type": "required|in:P256,P384,2048,4096", } } diff --git a/app/http/requests/cert/user_update.go b/app/http/requests/cert/user_update.go index 3f39a6d2..055b7efc 100644 --- a/app/http/requests/cert/user_update.go +++ b/app/http/requests/cert/user_update.go @@ -23,8 +23,8 @@ func (r *UserUpdate) Rules(ctx http.Context) map[string]string { "id": "required|uint|min:1|exists:cert_users,id", "ca": "required|in:letsencrypt,zerossl,sslcom,google,buypass", "email": "required|email", - "kid": "required_unless:ca,letsencrypt,buypass", - "hmac_encoded": "required_unless:ca,letsencrypt,buypass", + "kid": "required_if:ca,sslcom,google", + "hmac_encoded": "required_if:ca,sslcom,google", "key_type": "required|in:P256,P384,2048,4096", } } diff --git a/internal/services/cert.go b/internal/services/cert.go index 7926b0ca..d98ceea9 100644 --- a/internal/services/cert.go +++ b/internal/services/cert.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/go-resty/resty/v2" "github.com/goravel/framework/facades" requests "github.com/TheTNB/panel/app/http/requests/cert" @@ -43,7 +44,11 @@ func (s *CertImpl) UserStore(request requests.UserStore) error { case "buypass": client, err = acme.NewRegisterAccount(context.Background(), user.Email, acme.CABuypass, nil, acme.KeyType(user.KeyType)) case "zerossl": - client, err = acme.NewRegisterAccount(context.Background(), user.Email, acme.CAZeroSSL, &acme.EAB{KeyID: user.Kid, MACKey: user.HmacEncoded}, acme.KeyType(user.KeyType)) + eab, err := s.getZeroSSLEAB(user.Email) + if err != nil { + return err + } + client, err = acme.NewRegisterAccount(context.Background(), user.Email, acme.CAZeroSSL, eab, acme.KeyType(user.KeyType)) case "sslcom": client, err = acme.NewRegisterAccount(context.Background(), user.Email, acme.CASSLcom, &acme.EAB{KeyID: user.Kid, MACKey: user.HmacEncoded}, acme.KeyType(user.KeyType)) case "google": @@ -86,7 +91,11 @@ func (s *CertImpl) UserUpdate(request requests.UserUpdate) error { case "buypass": client, err = acme.NewRegisterAccount(context.Background(), user.Email, acme.CABuypass, nil, acme.KeyType(user.KeyType)) case "zerossl": - client, err = acme.NewRegisterAccount(context.Background(), user.Email, acme.CAZeroSSL, &acme.EAB{KeyID: user.Kid, MACKey: user.HmacEncoded}, acme.KeyType(user.KeyType)) + eab, err := s.getZeroSSLEAB(user.Email) + if err != nil { + return err + } + client, err = acme.NewRegisterAccount(context.Background(), user.Email, acme.CAZeroSSL, eab, acme.KeyType(user.KeyType)) case "sslcom": client, err = acme.NewRegisterAccount(context.Background(), user.Email, acme.CASSLcom, &acme.EAB{KeyID: user.Kid, MACKey: user.HmacEncoded}, acme.KeyType(user.KeyType)) case "google": @@ -108,6 +117,31 @@ func (s *CertImpl) UserUpdate(request requests.UserUpdate) error { return facades.Orm().Query().Save(&user) } +// getZeroSSLEAB 获取 ZeroSSL EAB +func (s *CertImpl) getZeroSSLEAB(email string) (*acme.EAB, error) { + type data struct { + Success bool `json:"success"` + EabKid string `json:"eab_kid"` + EabHmacKey string `json:"eab_hmac_key"` + } + client := resty.New() + client.SetTimeout(5 * time.Second) + client.SetRetryCount(2) + + resp, err := client.R().SetFormData(map[string]string{ + "email": email, + }).SetResult(&data{}).Post("https://api.zerossl.com/acme/eab-credentials-email") + if err != nil || !resp.IsSuccess() { + return &acme.EAB{}, errors.New("获取ZeroSSL EAB失败") + } + eab := resp.Result().(*data) + if !eab.Success { + return &acme.EAB{}, errors.New("获取ZeroSSL EAB失败") + } + + return &acme.EAB{KeyID: eab.EabKid, MACKey: eab.EabHmacKey}, nil +} + // UserShow 根据 ID 获取用户 func (s *CertImpl) UserShow(ID uint) (models.CertUser, error) { var user models.CertUser