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

  1. Enable klog V(8) to log the signer's subject, issuer, and DNSNames and compare against the SAN allowlist in validateAzureMetadataSignerSAN
  2. Update the expected SAN allowlist if Microsoft rotated the IMDS signing certificate to new hostnames (check Azure IMDS docs for the current certificate)
  3. Ensure the code is validating the IMDS/attestation document signer, not a different Azure service's certificate; use the correct root/fetcher pairing
  4. 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

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


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/5a49c9f92e7955f9. Report an issue: GitHub.