kubernetes/kops · critical
validating PKCS7 signer SAN: %w
Error message
validating PKCS7 signer SAN: %w
What it means
This wraps a failure from validateAzureMetadataSignerSAN, which checks that the PKCS7 signer certificate's Subject Alternative Name corresponds to the Azure metadata endpoint (e.g. the certificate covering 'management.azure.com' / IMDS). Even a cryptographically valid signature is rejected here if the signer cert is not the expected Azure metadata certificate, guarding against a validly-signed but untrusted document.
Source
Thrown at upup/pkg/fi/cloudup/azure/attest.go:262
p7, err := pkcs7.Parse(sigBytes)
if err != nil {
return nil, nil, fmt.Errorf("parsing PKCS7 signature: %w", err)
}
klog.V(8).Infof("Parsed PKCS7 structure with %d embedded certificate(s)", len(p7.Certificates))
// Verify the PKCS7 signature against the embedded leaf certificate.
if err := p7.Verify(); err != nil {
return nil, nil, fmt.Errorf("verifying PKCS7 signature: %w", err)
}
klog.V(4).Infof("PKCS7 self-signature verified")
signer := p7.GetOnlySigner()
if signer == nil {
return nil, nil, fmt.Errorf("PKCS7 signer certificate not found")
}
klog.V(8).Infof("PKCS7 signer certificate: subject=%q issuer=%q SANs=%v", signer.Subject, signer.Issuer, signer.DNSNames)
if err := validateAzureMetadataSignerSAN(signer); err != nil {
return nil, nil, fmt.Errorf("validating PKCS7 signer SAN: %w", err)
}
klog.V(4).Infof("PKCS7 signer SAN validated as Azure metadata endpoint")
return p7, signer, nil
}
// nonceForBody derives the IMDS attestation nonce from the request body; the shared
// azuremetadata implementation keeps the authenticator and verifier sides identical.
func nonceForBody(body []byte) string {
return azuremetadata.NonceForBody(body)
}
// parseAndValidateAttestedDocumentContent unmarshals the signed attestation payload and validates
// its nonce and freshness timestamps.
func parseAndValidateAttestedDocumentContent(content []byte, body []byte) (*attestedData, error) {
var data attestedData
if err := json.Unmarshal(content, &data); err != nil {
return nil, fmt.Errorf("unmarshalling attested data: %w", err)View on GitHub (pinned to 4c8573c808)
Solutions
- Enable klog V(8) to log the signer's subject, issuer, and DNSNames and compare against the SAN allowlist in validateAzureMetadataSignerSAN
- Update the expected SAN allowlist if Microsoft rotated the IMDS signing certificate to new hostnames (check Azure IMDS docs for the current certificate)
- Ensure the code is validating the IMDS/attestation document signer, not a different Azure service's certificate; use the correct root/fetcher pairing
- If this occurs unexpectedly in production, treat as a potential security signal and verify the attested document was fetched from 169.254.169.254 inside the VM
Example fix
// before
// allowlist stale after Azure cert rotation
if !contains(allowedSANs, signer.DNSNames...) {
return fmt.Errorf("unexpected SAN")
}
// after
allowedSANs := []string{"metadata.azure.com", "management.azure.com"} // refreshed per current Azure IMDS signing cert
for _, dns := range signer.DNSNames {
if slices.Contains(allowedSANs, strings.ToLower(dns)) {
return nil
}
}
return fmt.Errorf("signer SAN %v not Azure metadata endpoint", signer.DNSNames) Defensive patterns
Strategy: validation
Validate before calling
func validateAzureMetadataSignerSAN(signer *x509.Certificate) error {
expected := "management.azure.com"
for _, dns := range signer.DNSNames {
if strings.EqualFold(dns, expected) {
return nil
}
}
return fmt.Errorf("signer SAN %v does not include %q", signer.DNSNames, expected)
} Type guard
func hasAzureMetadataSAN(cert *x509.Certificate) bool {
for _, dns := range cert.DNSNames {
if strings.EqualFold(dns, "management.azure.com") {
return true
}
}
return false
} Try / catch
if err := validateAzureMetadataSignerSAN(signer); err != nil {
klog.V(4).Infof("rejecting signer: subject=%q issuer=%q SANs=%v", signer.Subject, signer.Issuer, signer.DNSNames)
return nil, nil, fmt.Errorf("validating PKCS7 signer SAN: %w", err)
} Prevention
- Log signer SANs at V(8) so SAN mismatches are immediately diagnosable
- Track Azure IMDS signing certificate rotations and refresh the SAN allowlist on upgrade
- Keep the SAN validator strict — never fall back to Subject CN when SANs are missing
- Treat SAN failures on real IMDS documents as a potential security incident, not just a config bug
When it happens
Trigger: validateAzureMetadataSignerSAN(signer) inspects signer.DNSNames (logged at klog.V(8) just before the call); it errors when the signer certificate has no DNS SANs, has SANs other than the expected Azure metadata hostnames, or omits SANs entirely in favor of a subject CN.
Common situations: Azure rotating the IMDS signing certificate to one with different SANs while the local allowlist is outdated; using the wrong certificate in test fixtures (a generic code-signing cert without the expected SAN); a genuine security event where the document was signed by a different Azure service's certificate.
Related errors
- verifying PKCS7 signature: %w
- attested vmId %q does not match %s (API vmId %q)
- decoding PKCS7 signature: %w
- parsing PKCS7 signature: %w
- PKCS7 signer certificate not found
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/5a49c9f92e7955f9.
Report an issue: GitHub.