{"record":{"id":"c6d6df7d1180eaed","repo":"kubernetes/kops","slug":"empty-attested-document-signature","errorCode":null,"errorMessage":"empty attested document signature","messagePattern":"empty attested document signature","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/azure/azuremetadata/authenticator.go","lineNumber":67,"sourceCode":"\n\t// Query IMDS for the VM's resource ID.\n\tmetadata, err := QueryComputeInstanceMetadata(ctx)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"querying instance metadata: %w\", err)\n\t}\n\tif metadata.ResourceID == \"\" {\n\t\treturn \"\", fmt.Errorf(\"missing resource ID\")\n\t}\n\tklog.V(4).Infof(\"Azure authenticator obtained resource ID %q\", metadata.ResourceID)\n\n\t// Query IMDS for a PKCS7-signed attested document containing the nonce.\n\tnonce := NonceForBody(body)\n\tdoc, err := queryIMDSAttestedDocument(ctx, nonce)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"querying attested document: %w\", err)\n\t}\n\tif doc.Signature == \"\" {\n\t\treturn \"\", fmt.Errorf(\"empty attested document signature\")\n\t}\n\tklog.V(2).Infof(\"Azure authenticator obtained attested document for %q\", metadata.ResourceID)\n\n\t// Token format: \"x-azure-id <resourceID> <base64-pkcs7-signature>\"\n\treturn AzureAuthenticationTokenPrefix + metadata.ResourceID + \" \" + doc.Signature, nil\n}\n","sourceCodeStart":49,"sourceCodeEnd":74,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/azure/azuremetadata/authenticator.go#L49-L74","documentation":"The attested document endpoint returned HTTP 200 and valid JSON, but the signature field was empty. The authenticator requires a non-empty PKCS7 signature to construct the \"x-azure-id <resourceID> <signature>\" bootstrap token, so it rejects the response as unusable.","triggerScenarios":"queryIMDSAttestedDocument returns an attestedDocument struct whose signature field is an empty string — the JSON lacked the \"signature\" key or it was empty/null.","commonSituations":"Intercepting software returning 200 with crafted JSON; Azure IMDS behavior/shape change for the api-version in use; VM in a degraded state where signing service returns empty payloads; accidental hit of a spoofed 169.254.169.254 responder.","solutions":["Inspect the raw IMDS attested response with curl to see whether a signature field is returned normally","Verify api-version currency and re-test; pin/upgrade to a supported version","Rule out spoofing: check routes/iptables for anything answering on 169.254.169.254","If the VM is degraded (run 'az vm rerun' / redeploy) to restore the IMDS signing service"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-flight: fetch the attested document and assert a non-empty signature\nresp, err := http.Get(\"http://169.254.169.254/metadata/attested/document?api-version=2025-04-07&nonce=test\")\n// (set Metadata:true header in production code)\nvar doc struct{ Signature string `json:\"signature\"` }\njson.NewDecoder(resp.Body).Decode(&doc)\nif doc.Signature == \"\" { return errors.New(\"IMDS returned empty attestation signature\") }","typeGuard":"func hasValidSignature(d *struct{ Signature string }) bool {\n    return d != nil && strings.TrimSpace(d.Signature) != \"\"\n}","tryCatchPattern":"// Treat empty-signature as unrecoverable config/env issue: fail fast with diagnostics\nif err != nil {\n    return fmt.Errorf(\"bootstrap aborted (attestation): %w\", err)\n}","preventionTips":["Verify a signature comes back from the attested endpoint on every new image/region","Audit routes and iptables for anything impersonating 169.254.169.254","Redeploy VMs whose IMDS behaves abnormally instead of retrying indefinitely"],"tags":["azure","imds","attestation","signature"],"backgroundTag":"empty-attestation-signature","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}