kubernetes/kops · error
fetching intermediate certificate from %s: %w
Error message
fetching intermediate certificate from %s: %w
What it means
fetchCertificate performs an HTTP GET to download a DER-encoded intermediate certificate from an AIA URL. If the HTTP client's Get call itself fails (connection refused, DNS failure, TLS handshake error, timeout), the error is wrapped with the URL for context via %w so callers can errors.Is/As the underlying net error.
Source
Thrown at upup/pkg/fi/cloudup/azure/attest.go:432
}
if issuer == nil {
if hop == 0 {
return nil, fmt.Errorf("no fetched intermediate certificates matched signer issuer %q", signer.Issuer)
}
// Fetched, but nothing matched current's issuer; stop with what we have.
break
}
current = issuer
}
return pool, nil
}
// fetchCertificate fetches and parses a DER-encoded certificate from the given URL.
func fetchCertificate(client *http.Client, url string) (*x509.Certificate, error) {
resp, err := client.Get(url)
if err != nil {
return nil, fmt.Errorf("fetching intermediate certificate from %s: %w", url, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("fetching intermediate certificate from %s: status %d", url, resp.StatusCode)
}
// Cap the body read to reject pathologically large responses. Read one extra byte so we can
// distinguish "at the limit" from "exceeded limit".
body, err := io.ReadAll(io.LimitReader(resp.Body, intermediateCertMaxResponseBytes+1))
if err != nil {
return nil, fmt.Errorf("reading intermediate certificate from %s: %w", url, err)
}
if len(body) > intermediateCertMaxResponseBytes {
return nil, fmt.Errorf("intermediate certificate from %s exceeds %d bytes", url, intermediateCertMaxResponseBytes)
}
cert, err := x509.ParseCertificate(body)View on GitHub (pinned to 4c8573c808)
Solutions
- Verify outbound HTTPS connectivity from the node to the AIA URL (curl the URL from the host)
- Open firewall/security-group egress rules to the Microsoft CA endpoints
- Fix DNS resolution on the node (check /etc/resolv.conf, VPC DNS)
- Add retry logic for transient network errors and rely on the negative cache to avoid hot-looping
Example fix
// before
resp, err := client.Get(url) // no retry; one network blip fails the chain build
if err != nil { return nil, err }
// after
var cert *x509.Certificate
err := retry.OnError(backoff, isNetworkError, func() error {
var e error
cert, e = fetchCertificate(client, url)
return e
}) Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight connectivity check before chain building
resp, err := http.Head(issuerURL)
if err != nil {
return nil, fmt.Errorf("AIA host unreachable: %w", err)
}
resp.Body.Close() Try / catch
var netErr net.Error
pool, err := fetchIntermediateCerts(client, signer)
if err != nil && errors.As(err, &netErr) {
// transient network error: retry with backoff
pool, err = retryWithBackoff(func() (*x509.CertPool, error) {
return fetchIntermediateCerts(client, signer)
})
} Prevention
- Allow outbound 443 to Microsoft CA/AIA endpoints in security groups and firewalls
- Ensure working DNS on nodes
- Set explicit HTTP client timeouts and retry transient failures
When it happens
Trigger: fetchCertificate invoked by fetchIntermediateCertsFromBaseURL (or directly in tests) when the transport-level request to the AIA URL fails — unreachable host, DNS resolution failure, network timeout, or TLS errors.
Common situations: Cluster egress blocked to Microsoft CA endpoints; private networks without internet access; DNS misconfiguration; firewall/security-group rules blocking outbound 443.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- reading intermediate certificate from %s: %w
- intermediate certificate fetch recently failed for signer is
- fetching intermediate certificate from %s: status %d
- intermediate certificate from %s exceeds %d bytes
- parsing intermediate certificate from %s: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/b4a2b088f6052448.
Report an issue: GitHub.