mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-12 11:39:32 +00:00
feat(m27): certificate export (PEM/PKCS#12) and S/MIME EKU support
Add certificate export in PEM (JSON or file download) and PKCS#12 formats. Private keys are never included — they stay on agents. Add EKU-aware issuance threading profile EKUs (serverAuth, clientAuth, codeSigning, emailProtection, timeStamping) through the full issuance pipeline. Fix agent CSR SAN splitting for email addresses, adaptive KeyUsage flags for S/MIME vs TLS, and a pre-existing generateID collision bug in deployment job creation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ type AgentService struct {
|
||||
certRepo repository.CertificateRepository
|
||||
jobRepo repository.JobRepository
|
||||
targetRepo repository.TargetRepository
|
||||
profileRepo repository.CertificateProfileRepository
|
||||
auditService *AuditService
|
||||
issuerRegistry map[string]IssuerConnector
|
||||
renewalService *RenewalService
|
||||
@@ -45,6 +46,11 @@ func NewAgentService(
|
||||
}
|
||||
}
|
||||
|
||||
// SetProfileRepo sets the profile repository for EKU resolution during CSR signing.
|
||||
func (s *AgentService) SetProfileRepo(repo repository.CertificateProfileRepository) {
|
||||
s.profileRepo = repo
|
||||
}
|
||||
|
||||
// Register creates a new agent and returns its API key (only once).
|
||||
func (s *AgentService) Register(ctx context.Context, name string, hostname string) (*domain.Agent, string, error) {
|
||||
if name == "" || hostname == "" {
|
||||
@@ -159,7 +165,14 @@ func (s *AgentService) SubmitCSR(ctx context.Context, agentID string, certID str
|
||||
// Fallback: direct issuer signing (no AwaitingCSR job — ad-hoc CSR submission)
|
||||
connector, ok := s.issuerRegistry[cert.IssuerID]
|
||||
if ok {
|
||||
result, err := connector.IssueCertificate(ctx, cert.CommonName, cert.SANs, string(csrPEM))
|
||||
// Resolve EKUs from the certificate profile if available
|
||||
var ekus []string
|
||||
if cert.CertificateProfileID != "" && s.profileRepo != nil {
|
||||
if profile, profileErr := s.profileRepo.Get(ctx, cert.CertificateProfileID); profileErr == nil && profile != nil {
|
||||
ekus = profile.AllowedEKUs
|
||||
}
|
||||
}
|
||||
result, err := connector.IssueCertificate(ctx, cert.CommonName, cert.SANs, string(csrPEM), ekus)
|
||||
if err != nil {
|
||||
return fmt.Errorf("issuer signing failed: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user