kubernetes/kops · error
instance doesn't have a signing key in ShieldedVmIdentity
Error message
instance doesn't have a signing key in ShieldedVmIdentity
What it means
The Shielded VM identity response contained no SigningKey. GCE returns the identity structure but without a signing key when the instance is not genuinely shielded or the identity is incomplete, so the verifier cannot obtain the TPM public key to check the token signature.
Source
Thrown at upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go:217
result := &bootstrap.VerifyResult{
NodeName: instance.Name,
InstanceGroupName: instanceGroupName,
CAPIMachine: capiMachine,
CertificateNames: sans,
ChallengeEndpoint: challengeEndpoint,
}
return result, nil
}
func (v *tpmVerifier) getTPMSigningKey(ctx context.Context, data *gcetpm.AuthTokenData) (*rsa.PublicKey, error) {
response, err := v.computeClient.Instances.GetShieldedInstanceIdentity(data.GCPProjectID, data.Zone, data.Instance).Context(ctx).Do()
if err != nil {
return nil, fmt.Errorf("failed to get shield instance identity: %w", err)
}
if response.SigningKey == nil {
return nil, fmt.Errorf("instance doesn't have a signing key in ShieldedVmIdentity")
}
block, _ := pem.Decode([]byte(response.SigningKey.EkPub))
if block == nil {
return nil, fmt.Errorf("failed parsing PEM block from EkPub %q", response.SigningKey.EkPub)
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed parsing EK public key: %w", err)
}
rsaPub, ok := pub.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("EK public key is %T, expected *rsa.PublickKey", pub)
}
return rsaPub, nil
}
// GetInstanceCertificateAlternateNames returns the instance hostname and addresses that should go into certificates.View on GitHub (pinned to 4c8573c808)
Solutions
- Enable Shielded VM (vTPM) on the instance or its instance template/MIG
- Wait briefly and retry if the instance was just created
- Recreate the node from a shielded-VM-enabled image/template
- Verify with gcloud compute instances describe --format='*(shieldedInstanceConfig)' that shielded options are on
Example fix
// before shieldedInstanceConfig: enableVtpm: false // after shieldedInstanceConfig: enableVtpm: true enableIntegrityMonitoring: true
Defensive patterns
Strategy: validation
Validate before calling
resp, err := computeClient.Instances.GetShieldedInstanceIdentity(proj, zone, name).Context(ctx).Do()
if err != nil { return err }
if resp.SigningKey == nil || resp.SigningKey.EkPub == "" {
return errors.New("instance has no Shielded VM signing key; enable vTPM or wait for identity publication")
} Prevention
- Ensure shieldedInstanceConfig.enableVtpm: true in instance templates
- Allow a short delay after VM creation before requesting its identity
- Use kops defaults which enable shielded VM on GCE
- Recreate nodes whose identity comes back empty
When it happens
Trigger: GetShieldedInstanceIdentity succeeds but response.SigningKey == nil — e.g. instance created with shielded VM options disabled, or GCE hasn't populated the identity yet for a brand-new VM.
Common situations: Node template missing vTPM/shielded settings; very recently created instance queried before identity publication; custom images without shielded VM support.
Related errors
- failed to get shield instance identity: %w
- failed to get GCE RSA attestation key from TPM: %w
- failed to marshal token data: %w
- failed to marshal token: %w
- decoding authorization token: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/83aea3dc12b1204b.
Report an issue: GitHub.