loadCertResourceAnyIssuer loads and returns the certificate resource from any of the configured issuers. If multiple are found (e.g. if there are 3 issuers configured, and all 3 have a resource matching certNamesKey), then the newest (latest NotBefore date) resource will be chosen.
(ctx context.Context, certNamesKey string)
| 175 | // configured, and all 3 have a resource matching certNamesKey), then the newest |
| 176 | // (latest NotBefore date) resource will be chosen. |
| 177 | func (cfg *Config) loadCertResourceAnyIssuer(ctx context.Context, certNamesKey string) (CertificateResource, error) { |
| 178 | // we can save some extra decoding steps if there's only one issuer, since |
| 179 | // we don't need to compare potentially multiple available resources to |
| 180 | // select the best one, when there's only one choice anyway |
| 181 | if len(cfg.Issuers) == 1 { |
| 182 | return cfg.loadCertResource(ctx, cfg.Issuers[0], certNamesKey) |
| 183 | } |
| 184 | |
| 185 | type decodedCertResource struct { |
| 186 | CertificateResource |
| 187 | issuer Issuer |
| 188 | decoded *x509.Certificate |
| 189 | } |
| 190 | var certResources []decodedCertResource |
| 191 | var lastErr error |
| 192 | |
| 193 | // load and decode all certificate resources found with the |
| 194 | // configured issuers so we can sort by newest |
| 195 | for _, issuer := range cfg.Issuers { |
| 196 | certRes, err := cfg.loadCertResource(ctx, issuer, certNamesKey) |
| 197 | if err != nil { |
| 198 | if errors.Is(err, fs.ErrNotExist) { |
| 199 | // not a problem, but we need to remember the error |
| 200 | // in case we end up not finding any cert resources |
| 201 | // since we'll need an error to return in that case |
| 202 | lastErr = err |
| 203 | continue |
| 204 | } |
| 205 | return CertificateResource{}, err |
| 206 | } |
| 207 | certs, err := parseCertsFromPEMBundle(certRes.CertificatePEM) |
| 208 | if err != nil { |
| 209 | return CertificateResource{}, err |
| 210 | } |
| 211 | certResources = append(certResources, decodedCertResource{ |
| 212 | CertificateResource: certRes, |
| 213 | issuer: issuer, |
| 214 | decoded: certs[0], |
| 215 | }) |
| 216 | } |
| 217 | if len(certResources) == 0 { |
| 218 | if lastErr == nil { |
| 219 | lastErr = fmt.Errorf("no certificate resources found") // just in case; e.g. no Issuers configured |
| 220 | } |
| 221 | return CertificateResource{}, lastErr |
| 222 | } |
| 223 | |
| 224 | // sort by date so the most recently issued comes first |
| 225 | sort.Slice(certResources, func(i, j int) bool { |
| 226 | return certResources[j].decoded.NotBefore.Before(certResources[i].decoded.NotBefore) |
| 227 | }) |
| 228 | |
| 229 | cfg.Logger.Debug("loading managed certificate", |
| 230 | zap.String("domain", certNamesKey), |
| 231 | zap.Time("expiration", expiresAt(certResources[0].decoded)), |
| 232 | zap.String("issuer_key", certResources[0].issuer.IssuerKey()), |
| 233 | zap.Any("storage", cfg.Storage), |
| 234 | ) |
no test coverage detected