mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-12 11:39:32 +00:00
3f619bcaac
Add three new issuer connectors completing commercial and open-source CA coverage. Entrust uses mTLS client certificate auth with sync/async issuance. GlobalSign Atlas uses mTLS + API key/secret dual auth with serial-based tracking. EJBCA supports dual auth (mTLS or OAuth2) for self-hosted Keyfactor CAs. Each connector implements the full issuer.Connector interface (9 methods), includes httptest-based unit tests (~14 each), and follows established patterns (injectable HTTP clients, RFC 5280 revocation reason mapping, CRL/OCSP delegated to CA). Also includes: issuer factory cases, env var seeding, config structs, domain types, seed data (3 rows, all disabled), OpenAPI enum updates, frontend issuer catalog entries with config fields, and full docs (connectors.md, architecture.md, features.md, README). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
120 lines
3.9 KiB
Go
120 lines
3.9 KiB
Go
package issuerfactory
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"github.com/shankar0123/certctl/internal/connector/issuer"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/acme"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/awsacmpca"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/digicert"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/ejbca"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/entrust"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/globalsign"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/googlecas"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/local"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/openssl"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/sectigo"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/stepca"
|
|
"github.com/shankar0123/certctl/internal/connector/issuer/vault"
|
|
)
|
|
|
|
// NewFromConfig instantiates an issuer connector from its type string and config JSON.
|
|
// The config JSON keys use snake_case matching the connector Config struct json tags.
|
|
// This replaces the manual wiring in cmd/server/main.go.
|
|
func NewFromConfig(issuerType string, configJSON json.RawMessage, logger *slog.Logger) (issuer.Connector, error) {
|
|
if len(configJSON) == 0 {
|
|
configJSON = []byte("{}")
|
|
}
|
|
|
|
switch issuerType {
|
|
case "local", "GenericCA":
|
|
var cfg local.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Local CA config: %w", err)
|
|
}
|
|
return local.New(&cfg, logger), nil
|
|
|
|
case "ACME":
|
|
var cfg acme.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid ACME config: %w", err)
|
|
}
|
|
return acme.New(&cfg, logger), nil
|
|
|
|
case "StepCA":
|
|
var cfg stepca.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid step-ca config: %w", err)
|
|
}
|
|
return stepca.New(&cfg, logger), nil
|
|
|
|
case "OpenSSL":
|
|
var cfg openssl.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid OpenSSL config: %w", err)
|
|
}
|
|
return openssl.New(&cfg, logger), nil
|
|
|
|
case "VaultPKI":
|
|
var cfg vault.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Vault PKI config: %w", err)
|
|
}
|
|
return vault.New(&cfg, logger), nil
|
|
|
|
case "DigiCert":
|
|
var cfg digicert.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid DigiCert config: %w", err)
|
|
}
|
|
return digicert.New(&cfg, logger), nil
|
|
|
|
case "Sectigo":
|
|
var cfg sectigo.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Sectigo config: %w", err)
|
|
}
|
|
return sectigo.New(&cfg, logger), nil
|
|
|
|
case "GoogleCAS":
|
|
var cfg googlecas.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Google CAS config: %w", err)
|
|
}
|
|
return googlecas.New(&cfg, logger), nil
|
|
|
|
case "AWSACMPCA":
|
|
var cfg awsacmpca.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid AWS ACM PCA config: %w", err)
|
|
}
|
|
return awsacmpca.New(&cfg, logger), nil
|
|
|
|
case "Entrust":
|
|
var cfg entrust.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid Entrust config: %w", err)
|
|
}
|
|
return entrust.New(&cfg, logger), nil
|
|
|
|
case "GlobalSign":
|
|
var cfg globalsign.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid GlobalSign config: %w", err)
|
|
}
|
|
return globalsign.New(&cfg, logger), nil
|
|
|
|
case "EJBCA":
|
|
var cfg ejbca.Config
|
|
if err := json.Unmarshal(configJSON, &cfg); err != nil {
|
|
return nil, fmt.Errorf("invalid EJBCA config: %w", err)
|
|
}
|
|
return ejbca.New(&cfg, logger), nil
|
|
|
|
default:
|
|
return nil, fmt.Errorf("unknown issuer type: %q", issuerType)
|
|
}
|
|
}
|