From 0bdb9749f70ffe68198d9b36a3a19f5ffb8ae968 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Mon, 9 Feb 2026 09:27:11 +0100 Subject: [PATCH 1/5] do not fail loading expired CAs Signed-off-by: Jose I. Paris --- app/controlplane/configs/config.devel.yaml | 5 +- app/controlplane/pkg/ca/ca.go | 4 +- app/controlplane/pkg/ca/fileca/fileca.go | 58 ++++++++++++++++++++-- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/app/controlplane/configs/config.devel.yaml b/app/controlplane/configs/config.devel.yaml index dc546e062..b032a94be 100644 --- a/app/controlplane/configs/config.devel.yaml +++ b/app/controlplane/configs/config.devel.yaml @@ -28,7 +28,10 @@ certificate_authorities: cert_path: ${FILE_CA_CERT_PATH:../../devel/devkeys/ca.pub} key_path: ${FILE_CA_KEY_PATH:../../devel/devkeys/ca.pem} key_pass: chainloop - + - file_ca: + cert_path: ${FILE_CA_CERT_PATH:../../tmp/expired.crt} + key_path: ${FILE_CA_KEY_PATH:../../tmp/expired.key} + key_pass: NUJ6iTzxRMOrn7 # - ejbca_ca: # server_url: "https://localhost/ejbca" # key_path: "../../devel/devkeys/superadmin.key" diff --git a/app/controlplane/pkg/ca/ca.go b/app/controlplane/pkg/ca/ca.go index 93f81c94f..b6f3e51ec 100644 --- a/app/controlplane/pkg/ca/ca.go +++ b/app/controlplane/pkg/ca/ca.go @@ -53,8 +53,8 @@ func NewCertificateAuthoritiesFromConfig(configCAs []*conf.CA, logger *log.Helpe var authority CertificateAuthority if configCA.GetFileCa() != nil { fileCa := configCA.GetFileCa() - logger.Log(log.LevelInfo, "msg", "Keyless: File CA configured") - authority, err = fileca.New(fileCa.GetCertPath(), fileCa.GetKeyPath(), fileCa.GetKeyPass(), false) + logger.Log(log.LevelInfo, "msg", fmt.Sprintf("Keyless: File CA configured (issuer = %v)", configCA.Issuer)) + authority, err = fileca.New(fileCa.GetCertPath(), fileCa.GetKeyPath(), fileCa.GetKeyPass(), configCA.Issuer) } if configCA.GetEjbcaCa() != nil { diff --git a/app/controlplane/pkg/ca/fileca/fileca.go b/app/controlplane/pkg/ca/fileca/fileca.go index a79cf6483..843496465 100644 --- a/app/controlplane/pkg/ca/fileca/fileca.go +++ b/app/controlplane/pkg/ca/fileca/fileca.go @@ -16,13 +16,20 @@ package fileca import ( + "bytes" "context" + "crypto" "crypto/x509" + "errors" "fmt" + "os" + "path/filepath" fulcioca "github.com/sigstore/fulcio/pkg/ca" - fulciofileca "github.com/sigstore/fulcio/pkg/ca/fileca" + "github.com/sigstore/fulcio/pkg/ca/baseca" "github.com/sigstore/fulcio/pkg/identity" + "github.com/sigstore/sigstore/pkg/cryptoutils" + "go.step.sm/crypto/pemutil" ) const CAName = "fileCA" @@ -31,16 +38,57 @@ type FileCA struct { ca fulcioca.CertificateAuthority } -func New(certPath, keyPath, keyPass string, watch bool) (*FileCA, error) { - wrappedCa, err := fulciofileca.NewFileCA(certPath, keyPath, keyPass, watch) +func New(certPath, keyPath, keyPass string, signer bool) (*FileCA, error) { + var err error + baseCA := &baseca.BaseCA{} + baseCA.SignerWithChain, err = loadKeyPair(certPath, keyPath, keyPass) if err != nil { - return nil, fmt.Errorf("failed to create file CA: %w", err) + return nil, err } + + if signer { + // if the CA is a signer, verify the chain + chain, signer := baseCA.GetSignerWithChain() + if err := fulcioca.VerifyCertChain(chain, signer); err != nil { + return nil, err + } + } + return &FileCA{ - ca: wrappedCa, + ca: baseCA, }, nil } +func loadKeyPair(certPath, keyPath, keyPass string) (*fulcioca.SignerCerts, error) { + var ( + certs []*x509.Certificate + err error + key crypto.Signer + ) + + data, err := os.ReadFile(filepath.Clean(certPath)) + if err != nil { + return nil, err + } + certs, err = cryptoutils.LoadCertificatesFromPEM(bytes.NewReader(data)) + if err != nil { + return nil, err + } + + opaqueKey, err := pemutil.Read(keyPath, pemutil.WithPassword([]byte(keyPass))) + if err != nil { + return nil, err + } + + var ok bool + key, ok = opaqueKey.(crypto.Signer) + if !ok { + return nil, errors.New(`fileca: loaded private key can't be used to sign`) + } + + return &fulcioca.SignerCerts{Certs: certs, Signer: key}, nil +} + func (f FileCA) CreateCertificateFromCSR(ctx context.Context, principal identity.Principal, csr *x509.CertificateRequest) (*fulcioca.CodeSigningCertificate, error) { return f.ca.CreateCertificate(ctx, principal, csr.PublicKey) } From 09cab29074449038994fe38b06b19b134e9c642e Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Mon, 9 Feb 2026 15:33:22 +0100 Subject: [PATCH 2/5] undo change Signed-off-by: Jose I. Paris --- app/controlplane/configs/config.devel.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/controlplane/configs/config.devel.yaml b/app/controlplane/configs/config.devel.yaml index b032a94be..09f1fa445 100644 --- a/app/controlplane/configs/config.devel.yaml +++ b/app/controlplane/configs/config.devel.yaml @@ -28,10 +28,6 @@ certificate_authorities: cert_path: ${FILE_CA_CERT_PATH:../../devel/devkeys/ca.pub} key_path: ${FILE_CA_KEY_PATH:../../devel/devkeys/ca.pem} key_pass: chainloop - - file_ca: - cert_path: ${FILE_CA_CERT_PATH:../../tmp/expired.crt} - key_path: ${FILE_CA_KEY_PATH:../../tmp/expired.key} - key_pass: NUJ6iTzxRMOrn7 # - ejbca_ca: # server_url: "https://localhost/ejbca" # key_path: "../../devel/devkeys/superadmin.key" From d948dac46bac7fdc59f8e8721b098cc0dd5fdcc9 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Mon, 9 Feb 2026 15:35:05 +0100 Subject: [PATCH 3/5] undo change Signed-off-by: Jose I. Paris --- app/controlplane/configs/config.devel.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controlplane/configs/config.devel.yaml b/app/controlplane/configs/config.devel.yaml index 09f1fa445..dc546e062 100644 --- a/app/controlplane/configs/config.devel.yaml +++ b/app/controlplane/configs/config.devel.yaml @@ -28,6 +28,7 @@ certificate_authorities: cert_path: ${FILE_CA_CERT_PATH:../../devel/devkeys/ca.pub} key_path: ${FILE_CA_KEY_PATH:../../devel/devkeys/ca.pem} key_pass: chainloop + # - ejbca_ca: # server_url: "https://localhost/ejbca" # key_path: "../../devel/devkeys/superadmin.key" From 5aeb1b234a28b4acaa89f5c91d67344581b03686 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Thu, 12 Feb 2026 18:21:45 +0100 Subject: [PATCH 4/5] comment Signed-off-by: Jose I. Paris --- app/controlplane/pkg/ca/ca.go | 1 + app/controlplane/pkg/ca/fileca/fileca.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controlplane/pkg/ca/ca.go b/app/controlplane/pkg/ca/ca.go index b6f3e51ec..fab1775db 100644 --- a/app/controlplane/pkg/ca/ca.go +++ b/app/controlplane/pkg/ca/ca.go @@ -54,6 +54,7 @@ func NewCertificateAuthoritiesFromConfig(configCAs []*conf.CA, logger *log.Helpe if configCA.GetFileCa() != nil { fileCa := configCA.GetFileCa() logger.Log(log.LevelInfo, "msg", fmt.Sprintf("Keyless: File CA configured (issuer = %v)", configCA.Issuer)) + // load the CA and verify it if it's configured as an issuer CA authority, err = fileca.New(fileCa.GetCertPath(), fileCa.GetKeyPath(), fileCa.GetKeyPass(), configCA.Issuer) } diff --git a/app/controlplane/pkg/ca/fileca/fileca.go b/app/controlplane/pkg/ca/fileca/fileca.go index 843496465..3a996627b 100644 --- a/app/controlplane/pkg/ca/fileca/fileca.go +++ b/app/controlplane/pkg/ca/fileca/fileca.go @@ -38,7 +38,7 @@ type FileCA struct { ca fulcioca.CertificateAuthority } -func New(certPath, keyPath, keyPass string, signer bool) (*FileCA, error) { +func New(certPath, keyPath, keyPass string, verify bool) (*FileCA, error) { var err error baseCA := &baseca.BaseCA{} baseCA.SignerWithChain, err = loadKeyPair(certPath, keyPath, keyPass) @@ -46,7 +46,7 @@ func New(certPath, keyPath, keyPass string, signer bool) (*FileCA, error) { return nil, err } - if signer { + if verify { // if the CA is a signer, verify the chain chain, signer := baseCA.GetSignerWithChain() if err := fulcioca.VerifyCertChain(chain, signer); err != nil { From 08f9f94a9d7748a749be379037005a099c2d77f1 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Fri, 13 Feb 2026 11:28:34 +0100 Subject: [PATCH 5/5] go mod tidy Signed-off-by: Jose I. Paris --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 78b164a28..fa7b8c58f 100644 --- a/go.mod +++ b/go.mod @@ -99,6 +99,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 github.com/zricethezav/gitleaks/v8 v8.30.0 gitlab.com/gitlab-org/security-products/analyzers/report/v5 v5.3.0 + go.step.sm/crypto v0.75.0 google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b google.golang.org/genproto/googleapis/bytestream v0.0.0-20251222181119-0a764e51fe1b ) @@ -302,7 +303,6 @@ require ( go.opentelemetry.io/otel/sdk v1.39.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.39.0 // indirect go.opentelemetry.io/proto/otlp v1.7.1 // indirect - go.step.sm/crypto v0.75.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect