feat: enhance certificate model with acmeCA field

This commit is contained in:
Fu Diwei 2026-06-09 09:50:53 +08:00 committed by RHQYZ
parent 4584dafcee
commit 95d4bcdb66
8 changed files with 67 additions and 6 deletions

View File

@ -59,6 +59,7 @@ type ObtainCertificateRequest struct {
}
type ObtainCertificateResponse struct {
CAProvider domain.CAProviderType
CSR string
FullChainCertificate string
IssuerCertificate string
@ -183,6 +184,7 @@ func (c *ACMEClient) ObtainCertificate(ctx context.Context, request *ObtainCerti
}
return &ObtainCertificateResponse{
CAProvider: domain.CAProviderType(c.account.CA),
CSR: strings.TrimSpace(string(resp.CSR)),
FullChainCertificate: strings.TrimSpace(string(resp.Certificate)),
IssuerCertificate: strings.TrimSpace(string(resp.IssuerCertificate)),

View File

@ -235,7 +235,7 @@ func (s *CertificateService) RevokeCertificate(ctx context.Context, req *dtos.Ce
return nil, fmt.Errorf("could not revoke a certificate which is already revoked")
}
acmeAccount, err := s.acmeAccountRepo.GetByAcctUrl(ctx, certificate.ACMEAcctUrl)
acmeAccount, err := s.acmeAccountRepo.GetByCAAndAcctUrl(ctx, certificate.CA, certificate.ACMEAcctUrl)
if err != nil {
return nil, fmt.Errorf("failed to revoke certificate: could not find acme account: %w", err)
}

View File

@ -9,7 +9,7 @@ import (
)
type acmeAccountRepository interface {
GetByAcctUrl(ctx context.Context, acctUrl string) (*domain.ACMEAccount, error)
GetByCAAndAcctUrl(ctx context.Context, ca string, acctUrl string) (*domain.ACMEAccount, error)
}
type certificateRepository interface {

View File

@ -31,6 +31,7 @@ type Certificate struct {
ValidityNotBefore time.Time `db:"validityNotBefore" json:"validityNotBefore"`
ValidityNotAfter time.Time `db:"validityNotAfter" json:"validityNotAfter"`
ValidityInterval int32 `db:"validityInterval" json:"validityInterval"`
CA string `db:"ca" json:"ca"`
ACMEAcctUrl string `db:"acmeAcctUrl" json:"acmeAcctUrl"`
ACMECertUrl string `db:"acmeCertUrl" json:"acmeCertUrl"`
IsRenewed bool `db:"isRenewed" json:"isRenewed"`

View File

@ -36,11 +36,11 @@ func (r *ACMEAccountRepository) GetByCAAndEmail(ctx context.Context, ca, caDirUr
return r.castRecordToModel(record)
}
func (r *ACMEAccountRepository) GetByAcctUrl(ctx context.Context, acctUrl string) (*domain.ACMEAccount, error) {
func (r *ACMEAccountRepository) GetByCAAndAcctUrl(ctx context.Context, ca string, acctUrl string) (*domain.ACMEAccount, error) {
record, err := app.GetApp().FindFirstRecordByFilter(
domain.CollectionNameACMEAccount,
"acmeAcctUrl={:acmeAcctUrl}",
dbx.Params{"acmeAcctUrl": acctUrl},
"ca={:ca} && acmeAcctUrl={:acmeAcctUrl}",
dbx.Params{"ca": ca, "acmeAcctUrl": acctUrl},
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {

View File

@ -107,6 +107,7 @@ func (r *CertificateRepository) Save(ctx context.Context, certificate *domain.Ce
record.Set("validityNotBefore", certificate.ValidityNotBefore)
record.Set("validityNotAfter", certificate.ValidityNotAfter)
record.Set("validityInterval", certificate.ValidityInterval)
record.Set("ca", certificate.CA)
record.Set("acmeAcctUrl", certificate.ACMEAcctUrl)
record.Set("acmeCertUrl", certificate.ACMECertUrl)
record.Set("isRenewed", certificate.IsRenewed)
@ -172,6 +173,7 @@ func (r *CertificateRepository) castRecordToModel(record *core.Record) (*domain.
ValidityNotBefore: record.GetDateTime("validityNotBefore").Time(),
ValidityNotAfter: record.GetDateTime("validityNotAfter").Time(),
ValidityInterval: int32(record.GetInt("validityInterval")),
CA: record.GetString("ca"),
ACMEAcctUrl: record.GetString("acmeAcctUrl"),
ACMECertUrl: record.GetString("acmeCertUrl"),
IsRenewed: record.GetBool("isRenewed"),

View File

@ -109,6 +109,7 @@ func (ne *bizApplyNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeExe
Certificate: obtainResp.FullChainCertificate,
PrivateKey: obtainResp.PrivateKey,
IssuerCertificate: obtainResp.IssuerCertificate,
CA: obtainResp.CAProvider.String(),
ACMEAcctUrl: obtainResp.ACMEAcctUrl,
ACMECertUrl: obtainResp.ACMECertUrl,
WorkflowId: execCtx.WorkflowId,

View File

@ -2,7 +2,9 @@ package migrations
import (
"errors"
"strings"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
@ -93,6 +95,7 @@ func init() {
// - add field `subjectName`
// - add field `issuerName`
// - add field `validationPolicy`
// - add field `ca`
{
collection, err := app.FindCollectionByNameOrId("4szxr9x43tpj6np")
if err != nil {
@ -207,6 +210,24 @@ func init() {
return err
}
if err := collection.Fields.AddMarshaledJSONAt(15, []byte(`{
"autogeneratePattern": "",
"help": "",
"hidden": false,
"id": "text4045880084",
"max": 0,
"min": 0,
"name": "ca",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": false,
"system": false,
"type": "text"
}`)); err != nil {
return err
}
if err := app.Save(collection); err != nil {
return err
}
@ -221,7 +242,12 @@ func init() {
for _, record := range records {
changed := false
if certX509, err := xcert.ParseCertificateFromPEM(record.GetString("certificate")); err == nil {
if record.GetString("certificate") != "" {
certX509, err := xcert.ParseCertificateFromPEM(record.GetString("certificate"))
if err != nil {
continue
}
record.Set("subjectName", certX509.Subject.CommonName)
record.Set("issuerName", certX509.Issuer.CommonName)
@ -241,6 +267,35 @@ func init() {
changed = true
}
if record.GetString("acmeAcctUrl") != "" {
acmeAcctUrl := record.GetString("acmeAcctUrl")
acmeAcctRecord, err := app.FindFirstRecordByFilter("acme_accounts", "acmeAcctUrl={:acmeAcctUrl}", dbx.Params{"acmeAcctUrl": acmeAcctUrl})
if err != nil {
mapping := map[string]string{
"https://acme-v02.api.letsencrypt.org/": "letsencrypt",
"https://acme-staging-v02.api.letsencrypt.org/": "letsencryptstaging",
"https://acme-api.actalis.com/": "actalisssl",
"https://acme.digicert.com/": "digicert",
"https://emea.acme.atlas.globalsign.com/": "globalsignatlas",
"https://dv.acme-v02.api.pki.goog/": "googletrustservices",
"https://acme.litessl.com/acme/v2/": "litessl",
"https://acme.ssl.com/": "sslcom",
"https://acme.sectigo.com/": "sectigo",
"https://acme.zerossl.com/": "zerossl",
}
for url, ca := range mapping {
if strings.HasPrefix(acmeAcctUrl, url) {
record.Set("ca", ca)
changed = true
break
}
}
} else {
record.Set("ca", acmeAcctRecord.GetString("ca"))
changed = true
}
}
if changed {
if err := app.Save(record); err != nil {
return err