feat(M46): Windows Certificate Store + Java Keystore target connectors, shared certutil package

Extract shared certutil helpers (CreatePFX, ParsePrivateKey, ComputeThumbprint,
GenerateRandomPassword, ParseCertificatePEM) from IIS connector for reuse.
Add WinCertStore connector (PowerShell Import-PfxCertificate, dual local/WinRM
mode, configurable store/location, expired cert cleanup) and JavaKeystore
connector (PEM→PKCS#12→keytool pipeline, JKS/PKCS12 support, shell injection
prevention, path traversal protection). 53 new tests, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shankar0123
2026-04-05 19:14:32 -04:00
parent dfa4dbbcbd
commit 7d6ef44e21
15 changed files with 2048 additions and 116 deletions
+20
View File
@@ -33,6 +33,8 @@ import (
pf "github.com/shankar0123/certctl/internal/connector/target/postfix"
sshconn "github.com/shankar0123/certctl/internal/connector/target/ssh"
"github.com/shankar0123/certctl/internal/connector/target/f5"
jks "github.com/shankar0123/certctl/internal/connector/target/javakeystore"
wcs "github.com/shankar0123/certctl/internal/connector/target/wincertstore"
"github.com/shankar0123/certctl/internal/connector/target/haproxy"
"github.com/shankar0123/certctl/internal/connector/target/iis"
"github.com/shankar0123/certctl/internal/connector/target/nginx"
@@ -657,6 +659,24 @@ func (a *Agent) createTargetConnector(targetType string, configJSON json.RawMess
}
return sshconn.New(&cfg, a.logger)
case "WinCertStore":
var cfg wcs.Config
if len(configJSON) > 0 {
if err := json.Unmarshal(configJSON, &cfg); err != nil {
return nil, fmt.Errorf("invalid WinCertStore config: %w", err)
}
}
return wcs.New(&cfg, a.logger)
case "JavaKeystore":
var cfg jks.Config
if len(configJSON) > 0 {
if err := json.Unmarshal(configJSON, &cfg); err != nil {
return nil, fmt.Errorf("invalid JavaKeystore config: %w", err)
}
}
return jks.New(&cfg, a.logger), nil
default:
return nil, fmt.Errorf("unsupported target type: %s", targetType)
}