mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-08 13:39:53 +00:00
127 lines
3.0 KiB
Go
127 lines
3.0 KiB
Go
package applicant
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/go-acme/lego/v4/lego"
|
|
"github.com/go-acme/lego/v4/registration"
|
|
|
|
"github.com/usual2970/certimate/internal/domain"
|
|
"github.com/usual2970/certimate/internal/pkg/utils/x509"
|
|
"github.com/usual2970/certimate/internal/repository"
|
|
)
|
|
|
|
type acmeUser struct {
|
|
CA string
|
|
Email string
|
|
Registration *registration.Resource
|
|
|
|
privkey string
|
|
}
|
|
|
|
func newAcmeUser(ca, email string) (*acmeUser, error) {
|
|
repo := repository.NewAcmeAccountRepository()
|
|
|
|
applyUser := &acmeUser{
|
|
CA: ca,
|
|
Email: email,
|
|
}
|
|
|
|
acmeAccount, err := repo.GetByCAAndEmail(ca, email)
|
|
if err != nil {
|
|
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
keyStr, err := x509.ConvertECPrivateKeyToPEM(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
applyUser.privkey = keyStr
|
|
return applyUser, nil
|
|
}
|
|
|
|
applyUser.Registration = acmeAccount.Resource
|
|
applyUser.privkey = acmeAccount.Key
|
|
|
|
return applyUser, nil
|
|
}
|
|
|
|
func (u *acmeUser) GetEmail() string {
|
|
return u.Email
|
|
}
|
|
|
|
func (u acmeUser) GetRegistration() *registration.Resource {
|
|
return u.Registration
|
|
}
|
|
|
|
func (u *acmeUser) GetPrivateKey() crypto.PrivateKey {
|
|
rs, _ := x509.ParseECPrivateKeyFromPEM(u.privkey)
|
|
return rs
|
|
}
|
|
|
|
func (u *acmeUser) hasRegistration() bool {
|
|
return u.Registration != nil
|
|
}
|
|
|
|
func (u *acmeUser) getPrivateKeyPEM() string {
|
|
return u.privkey
|
|
}
|
|
|
|
type acmeAccountRepository interface {
|
|
GetByCAAndEmail(ca, email string) (*domain.AcmeAccount, error)
|
|
Save(ca, email, key string, resource *registration.Resource) error
|
|
}
|
|
|
|
func registerAcmeUser(client *lego.Client, sslProvider *acmeSSLProviderConfig, user *acmeUser) (*registration.Resource, error) {
|
|
// TODO: fix 潜在的并发问题
|
|
|
|
var reg *registration.Resource
|
|
var err error
|
|
switch sslProvider.Provider {
|
|
case sslProviderZeroSSL:
|
|
reg, err = client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{
|
|
TermsOfServiceAgreed: true,
|
|
Kid: sslProvider.Config.Zerossl.EabKid,
|
|
HmacEncoded: sslProvider.Config.Zerossl.EabHmacKey,
|
|
})
|
|
case sslProviderGts:
|
|
reg, err = client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{
|
|
TermsOfServiceAgreed: true,
|
|
Kid: sslProvider.Config.Gts.EabKid,
|
|
HmacEncoded: sslProvider.Config.Gts.EabHmacKey,
|
|
})
|
|
|
|
case sslProviderLetsencrypt:
|
|
reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
|
|
|
default:
|
|
err = errors.New("unknown ssl provider")
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
repo := repository.NewAcmeAccountRepository()
|
|
|
|
resp, err := repo.GetByCAAndEmail(sslProvider.Provider, user.GetEmail())
|
|
if err == nil {
|
|
user.privkey = resp.Key
|
|
return resp.Resource, nil
|
|
}
|
|
|
|
if err := repo.Save(sslProvider.Provider, user.GetEmail(), user.getPrivateKeyPEM(), reg); err != nil {
|
|
return nil, fmt.Errorf("failed to save registration: %w", err)
|
|
}
|
|
|
|
return reg, nil
|
|
}
|