Back to blog
Best PracticesCloud SecurityCompute & ContainersGCPOperations & Compliance

VM vTPM Not Enabled: Securing GCP Compute Engine Boot Integrity

Learn why a missing vTPM on GCP Compute Engine VMs weakens boot integrity, and how to enable Shielded VM with CLI, Terraform, and Org Policy guardrails.

TL;DR

This check flags Compute Engine VMs running without a virtual Trusted Platform Module (vTPM), part of GCP's Shielded VM protections. Without it, you lose hardware-backed boot integrity verification and cryptographic key isolation. Fix it by enabling --shielded-vtpm on the instance.

Shielded VM is one of those GCP features that quietly does a lot of work to protect your instances from boot-level tampering, and most teams never notice it until an auditor or a security tool points out that it is missing. The VM vTPM Not Enabled check looks for Compute Engine VMs that are running without a virtual Trusted Platform Module, which is a core component of the Shielded VM stack.

This post walks through what the vTPM actually does, why a missing one is worth fixing, and how to remediate it without breaking your fleet.


What this check detects

The compute_novtpm check inspects each Compute Engine instance and reports any VM where the Shielded VM virtual TPM is disabled. In the instance configuration, this maps to the shieldedInstanceConfig.enableVtpm field being set to false (or absent on older instances created before Shielded VM defaults changed).

A vTPM is a virtualized, hardware-rooted Trusted Platform Module backed by Google's infrastructure. It provides two things that matter for security:

  • Measured boot: the vTPM records cryptographic measurements of the boot sequence (UEFI firmware, bootloader, kernel) so that any tampering produces a different measurement.
  • Key and secret isolation: applications can generate and store keys inside the vTPM so they never live in plain memory, and operations like sealing data to a known-good boot state become possible.

Note: Shielded VM has three independent toggles: Secure Boot, vTPM, and Integrity Monitoring. The vTPM is a prerequisite for Integrity Monitoring, because the integrity checks rely on the boot measurements that only the vTPM records. Disabling vTPM silently disables your ability to do measured boot verification.


Why it matters

The threat Shielded VM defends against is not a noisy network attacker. It is a quieter, more dangerous category: malware that survives reboots and reinstalls by burrowing into the boot path. Rootkits and bootkits load before the operating system, which means they can hide from the OS and from most agent-based security tooling running inside the VM.

Here is the practical chain of consequences when vTPM is off:

  • No boot integrity baseline. Without measured boot, there is no cryptographic record of what loaded during startup. If an attacker swaps a malicious kernel module or tampers with the bootloader, nothing flags the change.
  • Integrity Monitoring is effectively useless. Even if you enabled Integrity Monitoring, it has no vTPM measurements to compare against, so the early-boot and late-boot integrity validation cannot run.
  • Weaker key custody. Workloads that could anchor keys in a vTPM instead keep them in process memory, where a memory-scraping exploit or a compromised process can read them.
  • Compliance gaps. The CIS Google Cloud Foundations Benchmark recommends Shielded VM features on production instances. A missing vTPM shows up directly in benchmark scans and audit reports.

Warning: Boot-level compromise is hard to detect after the fact and harder to clean up. By the time you suspect a bootkit, you usually cannot trust the OS you are looking at, which means rebuild and forensics rather than a simple patch. Enabling vTPM up front is far cheaper than the incident it prevents.


How to fix it

The vTPM setting can only be changed while the instance is stopped. The fix is straightforward, but it requires a brief reboot, so plan accordingly.

1. Confirm the current state

gcloud compute instances describe INSTANCE_NAME \
  --zone ZONE \
  --format="value(shieldedInstanceConfig.enableVtpm)"

If this returns False or is empty, the vTPM is not enabled.

2. Stop the instance

Danger: Stopping an instance interrupts everything running on it. Drain traffic, fail over, or schedule a maintenance window before running this on production. Instances behind a managed instance group or load balancer should be rolled one at a time.

gcloud compute instances stop INSTANCE_NAME --zone ZONE

3. Enable the vTPM

gcloud compute instances update INSTANCE_NAME \
  --zone ZONE \
  --shielded-vtpm

While you are here, it is worth turning on the related protections too, since they work as a set:

gcloud compute instances update INSTANCE_NAME \
  --zone ZONE \
  --shielded-vtpm \
  --shielded-integrity-monitoring \
  --shielded-secure-boot

Warning: Secure Boot can prevent instances from booting if they rely on unsigned kernel modules (common with certain GPU drivers or custom kernels). The vTPM and Integrity Monitoring flags are safe for almost all images, but test Secure Boot on a non-production instance first.

4. Start the instance and verify

gcloud compute instances start INSTANCE_NAME --zone ZONE

gcloud compute instances describe INSTANCE_NAME \
  --zone ZONE \
  --format="value(shieldedInstanceConfig.enableVtpm)"

A return value of True confirms the fix.

Note: The boot image must support UEFI for Shielded VM to work. Most Google-provided images (Debian, Ubuntu, RHEL, Windows Server) include Shielded VM support out of the box. Custom images need to be created with the --guest-os-features=UEFI_COMPATIBLE flag. If your image lacks this feature, the update will fail.


Fixing it with infrastructure as code

If your instances are managed with Terraform, bake the setting into the definition so it never drifts:

resource "google_compute_instance" "app" {
  name         = "app-server"
  machine_type = "e2-standard-2"
  zone         = "us-central1-a"

  boot_disk {
    initialize_params {
      image = "projects/debian-cloud/global/images/family/debian-12"
    }
  }

  shielded_instance_config {
    enable_vtpm                 = true
    enable_integrity_monitoring = true
    enable_secure_boot          = false # enable after validating boot compatibility
  }

  network_interface {
    network = "default"
  }
}

For instance templates feeding a managed instance group, the same shielded_instance_config block applies. Update the template, then perform a rolling replace so the change propagates.

Tip: Make a Shielded VM block part of your golden instance template or module defaults. If every team consumes a shared module "compute_instance" that sets enable_vtpm = true, individual engineers never have to remember it, and the check stops firing for new resources entirely.


How to prevent it from happening again

Remediating one VM is easy. Keeping vTPM enabled across a growing fleet is the real work. Use a layered approach.

Enforce at the organization level with Org Policy

GCP provides a built-in constraint that requires Shielded VM on all new instances:

gcloud resource-manager org-policies enable-enforce \
  compute.requireShieldedVm \
  --organization ORGANIZATION_ID

With this constraint active, any attempt to create a VM without Shielded VM (which includes the vTPM) is rejected at the API level. This is the strongest guardrail because it cannot be bypassed by a misconfigured Terraform file or a console click.

Warning: Turning on requireShieldedVm only affects new instances. Existing non-compliant VMs keep running. Pair the org policy with a sweep of current instances so you do not leave older workloads exposed.

Gate it in CI/CD with policy as code

Catch misconfigurations before they reach GCP by scanning Terraform plans. A Conftest/OPA Rego rule does the job:

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "google_compute_instance"
  not resource.change.after.shielded_instance_config[_].enable_vtpm
  msg := sprintf("Instance %v must have vTPM enabled", [resource.address])
}

Wire this into your pipeline so a pull request that adds an unshielded instance fails before merge.

Detect drift continuously

Org policy and CI cover new resources, but settings can still drift through manual changes or imported infrastructure. Continuous scanning with Lensix surfaces any VM where the vTPM has been turned off, so the gap between "we enabled it once" and "it is still enabled" never grows unnoticed.


Best practices

  • Treat the three Shielded VM features as a unit. vTPM alone gives you measured boot, but Integrity Monitoring is what turns those measurements into alerts. Enable both, and add Secure Boot once you have confirmed boot compatibility.
  • Standardize on UEFI-compatible images. Build custom images with UEFI_COMPATIBLE from the start so Shielded VM is always an option, never a blocker.
  • Apply protections at the template, not the instance. Configuring Shielded VM per instance invites drift. Set it once in your shared module or instance template.
  • Combine prevention and detection. Org Policy stops new violations, CI gates catch them in code review, and continuous scanning catches drift. No single layer is enough on its own.
  • Document the Secure Boot exceptions. Some legitimate workloads cannot use Secure Boot. When you grant an exception, record why, so the next reviewer does not assume it is a mistake.

The vTPM is cheap to enable and costs nothing extra to run, yet it closes one of the few attack surfaces that survive a reboot. For most fleets, the right end state is simple: Shielded VM on everywhere, enforced by policy, and verified continuously.