@@ -75,10 +75,11 @@ type CA struct {
7575 // and module provisioning.
7676 ID string `json:"-"`
7777
78- storage certmagic.Storage
79- root , inter * x509.Certificate
80- interKey any // TODO: should we just store these as crypto.Signer?
81- mu * sync.RWMutex
78+ storage certmagic.Storage
79+ root * x509.Certificate
80+ interChain []* x509.Certificate
81+ interKey crypto.Signer
82+ mu * sync.RWMutex
8283
8384 rootCertPath string // mainly used for logging purposes if trusting
8485 log * zap.Logger
@@ -127,36 +128,40 @@ func (ca *CA) Provision(ctx caddy.Context, id string, log *zap.Logger) error {
127128 }
128129
129130 // load the certs and key that will be used for signing
130- var rootCert , interCert * x509.Certificate
131+ var rootCert * x509.Certificate
132+ var rootCertChain , interCertChain []* x509.Certificate
131133 var rootKey , interKey crypto.Signer
132134 var err error
133135 if ca .Root != nil {
134136 if ca .Root .Format == "" || ca .Root .Format == "pem_file" {
135137 ca .rootCertPath = ca .Root .Certificate
136138 }
137- rootCert , rootKey , err = ca .Root .Load ()
139+ rootCertChain , rootKey , err = ca .Root .Load ()
140+ rootCert = rootCertChain [0 ]
138141 } else {
139142 ca .rootCertPath = "storage:" + ca .storageKeyRootCert ()
140143 rootCert , rootKey , err = ca .loadOrGenRoot ()
141144 }
142145 if err != nil {
143146 return err
144147 }
145- actualRootLifetime := time .Until (rootCert .NotAfter )
146- if time .Duration (ca .IntermediateLifetime ) >= actualRootLifetime {
147- return fmt .Errorf ("intermediate certificate lifetime must be less than actual root certificate lifetime (%s)" , actualRootLifetime )
148- }
148+
149149 if ca .Intermediate != nil {
150- interCert , interKey , err = ca .Intermediate .Load ()
150+ interCertChain , interKey , err = ca .Intermediate .Load ()
151151 } else {
152- interCert , interKey , err = ca .loadOrGenIntermediate (rootCert , rootKey )
152+ actualRootLifetime := time .Until (rootCert .NotAfter )
153+ if time .Duration (ca .IntermediateLifetime ) >= actualRootLifetime {
154+ return fmt .Errorf ("intermediate certificate lifetime must be less than actual root certificate lifetime (%s)" , actualRootLifetime )
155+ }
156+
157+ interCertChain , interKey , err = ca .loadOrGenIntermediate (rootCert , rootKey )
153158 }
154159 if err != nil {
155160 return err
156161 }
157162
158163 ca .mu .Lock ()
159- ca .root , ca .inter , ca .interKey = rootCert , interCert , interKey
164+ ca .root , ca .interChain , ca .interKey = rootCert , interCertChain , interKey
160165 ca .mu .Unlock ()
161166
162167 return nil
@@ -172,21 +177,21 @@ func (ca CA) RootCertificate() *x509.Certificate {
172177// RootKey returns the CA's root private key. Since the root key is
173178// not cached in memory long-term, it needs to be loaded from storage,
174179// which could yield an error.
175- func (ca CA ) RootKey () (any , error ) {
180+ func (ca CA ) RootKey () (crypto. Signer , error ) {
176181 _ , rootKey , err := ca .loadOrGenRoot ()
177182 return rootKey , err
178183}
179184
180- // IntermediateCertificate returns the CA's intermediate
181- // certificate (public key) .
182- func (ca CA ) IntermediateCertificate () * x509.Certificate {
185+ // IntermediateCertificateChain returns the CA's intermediate
186+ // certificate chain .
187+ func (ca CA ) IntermediateCertificateChain () [] * x509.Certificate {
183188 ca .mu .RLock ()
184189 defer ca .mu .RUnlock ()
185- return ca .inter
190+ return ca .interChain
186191}
187192
188193// IntermediateKey returns the CA's intermediate private key.
189- func (ca CA ) IntermediateKey () any {
194+ func (ca CA ) IntermediateKey () crypto. Signer {
190195 ca .mu .RLock ()
191196 defer ca .mu .RUnlock ()
192197 return ca .interKey
@@ -207,26 +212,27 @@ func (ca *CA) NewAuthority(authorityConfig AuthorityConfig) (*authority.Authorit
207212 // cert/key directly, since it's unlikely to expire
208213 // while Caddy is running (long lifetime)
209214 var issuerCert * x509.Certificate
210- var issuerKey any
215+ var issuerKey crypto. Signer
211216 issuerCert = rootCert
212217 var err error
213218 issuerKey , err = ca .RootKey ()
214219 if err != nil {
215220 return nil , fmt .Errorf ("loading signing key: %v" , err )
216221 }
217- signerOption = authority .WithX509Signer (issuerCert , issuerKey .(crypto. Signer ) )
222+ signerOption = authority .WithX509Signer (issuerCert , issuerKey )
218223 } else {
219224 // if we're signing with intermediate, we need to make
220225 // sure it's always fresh, because the intermediate may
221226 // renew while Caddy is running (medium lifetime)
222227 signerOption = authority .WithX509SignerFunc (func () ([]* x509.Certificate , crypto.Signer , error ) {
223- issuerCert := ca .IntermediateCertificate ()
224- issuerKey := ca .IntermediateKey ().(crypto.Signer )
228+ issuerChain := ca .IntermediateCertificateChain ()
229+ issuerCert := issuerChain [0 ]
230+ issuerKey := ca .IntermediateKey ()
225231 ca .log .Debug ("using intermediate signer" ,
226232 zap .String ("serial" , issuerCert .SerialNumber .String ()),
227233 zap .String ("not_before" , issuerCert .NotBefore .String ()),
228234 zap .String ("not_after" , issuerCert .NotAfter .String ()))
229- return [] * x509. Certificate { issuerCert } , issuerKey , nil
235+ return issuerChain , issuerKey , nil
230236 })
231237 }
232238
@@ -252,7 +258,11 @@ func (ca *CA) NewAuthority(authorityConfig AuthorityConfig) (*authority.Authorit
252258
253259func (ca CA ) loadOrGenRoot () (rootCert * x509.Certificate , rootKey crypto.Signer , err error ) {
254260 if ca .Root != nil {
255- return ca .Root .Load ()
261+ rootChain , rootSigner , err := ca .Root .Load ()
262+ if err != nil {
263+ return nil , nil , err
264+ }
265+ return rootChain [0 ], rootSigner , nil
256266 }
257267 rootCertPEM , err := ca .storage .Load (ca .ctx , ca .storageKeyRootCert ())
258268 if err != nil {
@@ -268,7 +278,7 @@ func (ca CA) loadOrGenRoot() (rootCert *x509.Certificate, rootKey crypto.Signer,
268278 }
269279
270280 if rootCert == nil {
271- rootCert , err = pemDecodeSingleCert (rootCertPEM )
281+ rootCert , err = pemDecodeCertificate (rootCertPEM )
272282 if err != nil {
273283 return nil , nil , fmt .Errorf ("parsing root certificate PEM: %v" , err )
274284 }
@@ -314,7 +324,8 @@ func (ca CA) genRoot() (rootCert *x509.Certificate, rootKey crypto.Signer, err e
314324 return rootCert , rootKey , nil
315325}
316326
317- func (ca CA ) loadOrGenIntermediate (rootCert * x509.Certificate , rootKey crypto.Signer ) (interCert * x509.Certificate , interKey crypto.Signer , err error ) {
327+ func (ca CA ) loadOrGenIntermediate (rootCert * x509.Certificate , rootKey crypto.Signer ) (interCertChain []* x509.Certificate , interKey crypto.Signer , err error ) {
328+ var interCert * x509.Certificate
318329 interCertPEM , err := ca .storage .Load (ca .ctx , ca .storageKeyIntermediateCert ())
319330 if err != nil {
320331 if ! errors .Is (err , fs .ErrNotExist ) {
@@ -326,10 +337,12 @@ func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Si
326337 if err != nil {
327338 return nil , nil , fmt .Errorf ("generating new intermediate cert: %v" , err )
328339 }
340+
341+ interCertChain = append (interCertChain , interCert )
329342 }
330343
331- if interCert == nil {
332- interCert , err = pemDecodeSingleCert (interCertPEM )
344+ if len ( interCertChain ) == 0 {
345+ interCertChain , err = pemDecodeCertificateChain (interCertPEM )
333346 if err != nil {
334347 return nil , nil , fmt .Errorf ("decoding intermediate certificate PEM: %v" , err )
335348 }
@@ -346,7 +359,7 @@ func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey crypto.Si
346359 }
347360 }
348361
349- return interCert , interKey , nil
362+ return interCertChain , interKey , nil
350363}
351364
352365func (ca CA ) genIntermediate (rootCert * x509.Certificate , rootKey crypto.Signer ) (interCert * x509.Certificate , interKey crypto.Signer , err error ) {
0 commit comments