# GCP VM OS Login Not Enabled

> OS Login ties SSH access to IAM roles instead of hand-managed metadata keys. ZopNight rule RC-1202 flags instances lacking their own enable-oslogin=TRUE metadata item. Because the discoverer never reads project-level commonInstanceMetadata, a fleet enforced at project scope can false-fire: verify project metadata before remediating any flagged VM.

Source: https://zop.dev/integrations/gcp/recommendations/gcp-vm-os-login-not-enabled
Updated: 2026-08-19

---

## Metadata SSH keys versus IAM-governed SSH

Without OS Login, SSH access to a Compute Engine VM is a pile of public keys pasted into instance or project metadata. Keys accumulate, nobody remembers whose they are, and offboarding an engineer means grepping metadata across every project they ever touched. OS Login replaces that with IAM: access is granted through `roles/compute.osLogin` or `roles/compute.osAdminLogin`, revoked the moment the IAM binding goes, and logged like any other IAM-mediated action. Enabling it is one metadata item, `enable-oslogin=TRUE`, set on the instance or, better, on the project.

## Read this before acting on a finding

Rule RC-1202 can only infer, not prove, non-compliance, and the inference has a documented false-positive mode. GCP resolves `enable-oslogin` with project-level inheritance: a project's commonInstanceMetadata value applies to every instance that does not set its own override, which is Google's recommended enforcement pattern. The discoverer reads only each instance's own metadata items and never fetches the project's, so a VM correctly governed by project-wide enforcement is still stamped `oslogin_enabled=false` and will be flagged. No signal available to the rule can distinguish that case; the fix is discoverer-side. Check the project first:

```bash
gcloud compute project-info describe --project my-project \
  --format='value(commonInstanceMetadata.items)' | tr ',' '\n' | grep -i oslogin
```

If the project already enforces OS Login, the finding is noise for that VM. Close it and move on.

## How the gate is built

The rule fires when an instance that the discoverer definitely enriched (it anchors on the always-stamped `purchase_type` key) lacks `oslogin_enabled=true`. The anchor prevents false fires on resources that were never enriched at all, and an earlier revision that read a tag the discoverer never writes was dead on real data. The current gate reads the authoritative metadata sink.

## Rolling it out for real

Set enforcement at the project level rather than per instance, grant users the two OS Login roles as needed, then delete the legacy SSH keys from metadata. Leaving them in place preserves exactly the access sprawl you were removing. Expect friction on VMs with service-account-based tooling that assumed metadata keys; test on one instance per workload family before flipping the project.
