certimate/internal/certapply/config.go
2025-09-25 16:09:07 +08:00

124 lines
4.5 KiB
Go

package certapply
import (
"context"
"errors"
"strings"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/certimate-go/certimate/internal/domain"
"github.com/certimate-go/certimate/internal/repository"
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
)
var acmeDirUrls = map[string]string{
string(domain.CAProviderTypeLetsEncrypt): "https://acme-v02.api.letsencrypt.org/directory",
string(domain.CAProviderTypeLetsEncryptStaging): "https://acme-staging-v02.api.letsencrypt.org/directory",
string(domain.CAProviderTypeActalisSSL): "https://acme-api.actalis.com/acme/directory",
string(domain.CAProviderTypeGlobalSignAtlas): "https://emea.acme.atlas.globalsign.com/directory",
string(domain.CAProviderTypeGoogleTrustServices): "https://dv.acme-v02.api.pki.goog/directory",
string(domain.CAProviderTypeSSLCom): "https://acme.ssl.com/sslcom-dv-rsa",
string(domain.CAProviderTypeSSLCom) + "RSA": "https://acme.ssl.com/sslcom-dv-rsa",
string(domain.CAProviderTypeSSLCom) + "ECC": "https://acme.ssl.com/sslcom-dv-ecc",
string(domain.CAProviderTypeSectigo): "https://acme.sectigo.com/v2/DV",
string(domain.CAProviderTypeSectigo) + "DV": "https://acme.sectigo.com/v2/DV",
string(domain.CAProviderTypeSectigo) + "OV": "https://acme.sectigo.com/v2/OV",
string(domain.CAProviderTypeSectigo) + "EV": "https://acme.sectigo.com/v2/EV",
string(domain.CAProviderTypeZeroSSL): "https://acme.zerossl.com/v2/DV90",
}
type ACMEConfigOptions struct {
CAProvider string
CAAccessConfig map[string]any
CAProviderConfig map[string]any
CertifierKeyType certcrypto.KeyType
}
type ACMEConfig struct {
CAProvider domain.CAProviderType
CADirUrl string
EABKid string
EABHmacKey string
CertifierKeyType certcrypto.KeyType
}
func NewACMEConfig(options *ACMEConfigOptions) (*ACMEConfig, error) {
if options == nil {
return nil, errors.New("the options is nil")
}
caProvider := options.CAProvider
caAccessConfig := options.CAAccessConfig
if options.CAProvider == "" {
settingsRepo := repository.NewSettingsRepository()
settings, _ := settingsRepo.GetByName(context.Background(), "sslProvider")
if settings != nil {
sslProviderSettings := settings.Content.AsSSLProvider()
caProvider = string(sslProviderSettings.Provider)
caAccessConfig = sslProviderSettings.Config[sslProviderSettings.Provider]
}
}
if caProvider == "" {
// default CA: Let's Encrypt
caProvider = string(domain.AccessProviderTypeLetsEncrypt)
}
if caAccessConfig == nil {
caAccessConfig = make(map[string]any)
}
ca := &ACMEConfig{CAProvider: domain.CAProviderType(caProvider), CertifierKeyType: options.CertifierKeyType}
switch ca.CAProvider {
case domain.CAProviderTypeSectigo:
credentials := &domain.AccessConfigForGlobalSectigo{}
if err := xmaps.Populate(caAccessConfig, &credentials); err != nil {
return nil, err
} else if strings.EqualFold(credentials.ValidationType, "DV") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSectigo)+"DV"]
} else if strings.EqualFold(credentials.ValidationType, "OV") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSectigo)+"OV"]
} else if strings.EqualFold(credentials.ValidationType, "EV") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSectigo)+"EV"]
} else {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSectigo)]
}
case domain.CAProviderTypeSSLCom:
if strings.HasPrefix(string(options.CertifierKeyType), "RSA") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSSLCom)+"RSA"]
} else if strings.HasPrefix(string(options.CertifierKeyType), "EC") {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSSLCom)+"ECC"]
} else {
ca.CADirUrl = acmeDirUrls[string(domain.CAProviderTypeSSLCom)]
}
case domain.CAProviderTypeACMECA:
credentials := &domain.AccessConfigForACMECA{}
if err := xmaps.Populate(caAccessConfig, &credentials); err != nil {
return nil, err
} else if credentials.Endpoint == "" {
return nil, errors.New("the endpoint of custom ACME CA is empty")
}
ca.CADirUrl = credentials.Endpoint
default:
endpoint := acmeDirUrls[string(ca.CAProvider)]
if endpoint == "" {
return nil, errors.New("the endpoint of the ACME CA provider is empty")
}
ca.CADirUrl = endpoint
}
eab := domain.AccessConfigForACMEExternalAccountBinding{}
if err := xmaps.Populate(caAccessConfig, &eab); err != nil {
return nil, err
}
ca.EABKid = eab.EabKid
ca.EABHmacKey = eab.EabHmacKey
return ca, nil
}