hashicorp/packer · error

load KMS public key %q: %w

Error message

load KMS public key %q: %w

What it means

After the SignerVerifier is constructed, newKMSSigner calls signerVerifier.PublicKey() to retrieve the public half of the KMS key so it can build a local verifier. This error wraps any failure of that call — typically an API error fetching the key material from the cloud KMS (permissions, deleted key, network) or a failure of the provider to parse/expose the key. It is thrown because attestation verification requires the public key locally even though signing happens remotely.

Source

Thrown at internal/attestation/sign_kms.go:48

}

func newKMSSigner(ctx context.Context, cfg BackendConfig) (Signer, error) {
	if cfg.SignerRef == "" {
		return nil, fmt.Errorf("signing_mode %q requires signer or key", SigningModeKMS)
	}

	signerVerifier, err := newKMSSignerVerifier(ctx, cfg.SignerRef)
	if err != nil {
		var notFound *sigstorekms.ProviderNotFoundError
		if errors.As(err, &notFound) {
			return nil, fmt.Errorf("initialize KMS signer %q: %w%s", cfg.SignerRef, err, kmsProviderBuildHint(cfg.SignerRef))
		}
		return nil, fmt.Errorf("initialize KMS signer %q: %w", cfg.SignerRef, err)
	}

	publicKey, err := signerVerifier.PublicKey()
	if err != nil {
		return nil, fmt.Errorf("load KMS public key %q: %w", cfg.SignerRef, err)
	}

	verifier, err := newSigstoreVerifierFromPublicKey(publicKey)
	if err != nil {
		return nil, fmt.Errorf("create KMS verifier %q: %w", cfg.SignerRef, err)
	}

	return &kmsSigner{
		signerVerifier: signerVerifier,
		verifier:       verifier,
		keyID:          verifier.KeyID(),
	}, nil
}

func (s *kmsSigner) Sign(_ context.Context, payloadType string, payload []byte) (Signature, error) {
	encoded := PreAuthEncode(payloadType, payload)
	signature, err := s.signerVerifier.SignMessage(bytes.NewReader(encoded))
	if err != nil {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Grant the caller GetPublicKey permission on the KMS key (e.g. aws kms get-public-key works with the same credentials).
  2. Confirm the key exists, is enabled, and is an asymmetric key suitable for signing (check its state in the KMS console).
  3. Retry the run if the wrapped error indicates a transient API/network failure.
  4. Verify the key ID/alias still resolves after rotation; update the config if the alias changed.

Example fix

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["kms:Sign", "kms:GetPublicKey"],
    "Resource": "arn:aws:kms:us-east-1:123456789012:key/abcd-1234"
  }]
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight permission check before signing
out, err := kmsClient.GetPublicKey(&kms.GetPublicKeyInput{KeyId: aws.String(keyID)})
if err != nil {
	return fmt.Errorf("caller lacks GetPublicKey on key or key disabled/deleted: %w", err)
}
if *out.KeyState != "Enabled" { return fmt.Errorf("key state %s", *out.KeyState) }

Try / catch

signer, err := attestation.NewSigner(ctx, cfg)
if err != nil && strings.Contains(err.Error(), "load KMS public key") {
	// typically kms:GetPublicKey permission or key state issue
	if isTransient(err) { return retryInit(ctx, cfg) }
	return fmt.Errorf("grant GetPublicKey on the KMS key and ensure it is enabled/asymmetric: %w", err)
}

Prevention

When it happens

Trigger: signing_mode "kms" where the KMS provider initializes fine but SignerVerifier.PublicKey() returns an error: caller lacks GetPublicKey permission on the key, the key is scheduled for deletion/disabled, or the KMS API call fails transiently.

Common situations: IAM policy grants kms:Sign but not kms:GetPublicKey (or the equivalent on GCP/Azure/Vault); asymmetric key rotated or disabled after signer init; the key is symmetric-only in a provider that cannot export a public key this way; intermittent cloud API/network failure at startup.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/bd56b0079d8c2590. Report an issue: GitHub.