kubernetes/kops · error
PKCS7 signer certificate not found
Error message
PKCS7 signer certificate not found
What it means
After a successful signature verification, parseAndValidatePKCS7Signer calls p7.GetOnlySigner() to extract the single signer certificate. If the PKCS#7 message has zero or multiple signer certificates, GetOnlySigner returns nil and this error is raised. A valid Azure attested document has exactly one signer.
Source
Thrown at upup/pkg/fi/cloudup/azure/attest.go:258
return nil, nil, fmt.Errorf("decoding PKCS7 signature: %w", err)
}
klog.V(4).Infof("Decoded PKCS7 signature (%d bytes)", len(sigBytes))
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.View on GitHub (pinned to 4c8573c808)
Solutions
- Regenerate test fixtures with exactly one signer (openssl cms -sign -signer leaf -inkey key -in data -outform DER)
- Inspect len(p7.Certificates) and the SignerInfos count; klog.V(8) logs the embedded certificate count to help diagnose
- Ensure no proxy or middleware re-signs or augments the IMDS response; fetch directly from 169.254.169.254
- If a legitimate multi-cert structure is expected upstream, adjust the validator to pick the leaf matching the expected SAN instead of requiring GetOnlySigner
Example fix
// before
signer := p7.GetOnlySigner()
if signer == nil {
return nil, nil, fmt.Errorf("PKCS7 signer certificate not found")
}
// after
signer := p7.GetOnlySigner()
if signer == nil {
klog.V(4).Infof("PKCS7 has %d certs, %d signer infos", len(p7.Certificates), len(p7.GetSignerInfos()))
return nil, nil, fmt.Errorf("PKCS7 signer certificate not found")
} Defensive patterns
Strategy: type-guard
Validate before calling
if p7 == nil || len(p7.Certificates) == 0 {
return fmt.Errorf("PKCS7 message contains no certificates")
} Type guard
func hasSingleSigner(p7 *pkcs7.PKCS7) bool {
return p7 != nil && p7.GetOnlySigner() != nil
} Try / catch
signer := p7.GetOnlySigner()
if signer == nil {
klog.V(4).Infof("PKCS7 certs=%d (expected exactly one resolvable signer)", len(p7.Certificates))
return nil, nil, fmt.Errorf("PKCS7 signer certificate not found")
} Prevention
- Generate test PKCS7 blobs with a single signer via `openssl cms -sign` (one -signer flag)
- Never let intermediaries re-sign or augment IMDS responses
- Check the embedded certificate count (klog V(8)) when debugging fixtures
- Assume exactly one signer is an invariant of Azure attested documents and validate fixtures against it
When it happens
Trigger: p7.GetOnlySigner() returns nil because p7.Certificates is empty or contains more than one certificate while the SignerInfos do not resolve to exactly one signer, immediately after p7.Verify() succeeded.
Common situations: Hand-crafted or tool-generated (openssl cms) test blobs with countersignatures or multiple signers; PKCS#7 structures produced by an intermediary/proxy that adds extra certificates; malformed fixtures that pass parse but not the single-signer assumption.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- decoding PKCS7 signature: %w
- parsing PKCS7 signature: %w
- verifying PKCS7 signature: %w
- validating PKCS7 signer SAN: %w
- attested document expired at %s
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/f32d6bd333aa4d50.
Report an issue: GitHub.