Back to blog
Best PracticesCloud SecurityCompute & ContainersGCPIdentity & Access

OS Login Not Enabled at Project Level (GCP)

Learn why GCP OS Login should be enabled at the project level, the risks of metadata SSH keys, and how to enforce it with gcloud, Terraform, and org policy.

TL;DR

OS Login ties SSH access on your Compute Engine VMs to IAM identities instead of static, manually managed SSH keys. When it is not enabled at the project level, you fall back to metadata-based keys that are hard to audit and easy to leave behind. Enable it by setting the enable-oslogin=TRUE metadata key on the project.

SSH key management is one of those problems that quietly grows worse over time. A VM gets a key added during a 2 a.m. incident, an engineer leaves the company but their public key lingers in instance metadata, and six months later nobody can say with confidence who can log into what. OS Login exists to make that whole category of problems go away by routing SSH access through Google Cloud IAM.

This check flags GCP projects where OS Login is not enabled at the project level. Below we cover what that means, why it is worth fixing, and how to roll it out without locking yourself out of your own machines.


What this check detects

The check looks at your project's common instance metadata for the enable-oslogin key. If the key is missing, set to FALSE, or otherwise not enabled, the check fails.

When OS Login is off, Compute Engine authenticates SSH sessions using public keys stored in instance or project metadata. Anyone with permission to edit that metadata can add a key and gain access, and those keys are not tied to a Google identity, so they do not appear in your IAM policy and do not get revoked when someone's access is removed.

With OS Login enabled, SSH access is instead governed by two IAM roles:

  • roles/compute.osLogin for standard access
  • roles/compute.osAdminLogin for sudo access

Note: OS Login maps a Google account or service account to a POSIX user on the VM. The user's SSH keys are stored against their identity, not against individual machines, so granting or removing access happens in one place rather than across every instance.


Why it matters

Metadata SSH keys are a common path for privilege creep and lingering access. A few concrete scenarios:

  • Orphaned keys after offboarding. An engineer leaves, their IAM access is revoked, but their SSH public key is still sitting in project metadata. They, or anyone who copied that private key, can still log in.
  • No central audit trail. Without OS Login, there is no clean answer to "who can SSH into this VM?" You have to scan metadata across every instance and reconcile keys by hand.
  • Lateral movement. If an attacker gains compute.instances.setMetadata permission, they can inject their own SSH key and get a shell, bypassing your IAM controls entirely.
  • Weak two-factor coverage. Metadata keys cannot enforce two-factor authentication. OS Login can, through the enable-oslogin-2fa setting.

For teams under SOC 2, ISO 27001, or similar frameworks, OS Login also gives you a much cleaner answer to access-review questions. Auditors want to see access controlled centrally and tied to identities, which is exactly what OS Login provides.

Warning: Enabling OS Login changes how SSH authentication works for affected VMs. Existing metadata-based keys stop working on those instances. Plan the rollout so engineers and automation that rely on key-based access are migrated first, or you risk locking people out.


How to fix it

The fix is to set enable-oslogin=TRUE in the project's common metadata. This applies to all instances in the project unless an individual instance overrides it.

Option 1: gcloud CLI

gcloud compute project-info add-metadata \
  --project=YOUR_PROJECT_ID \
  --metadata enable-oslogin=TRUE

To verify the change took effect:

gcloud compute project-info describe \
  --project=YOUR_PROJECT_ID \
  --format="value(commonInstanceMetadata.items)"

Option 2: Google Cloud Console

  1. Go to Compute EngineSettingsMetadata.
  2. Select the Metadata tab.
  3. Click Edit, then Add item.
  4. Set the key to enable-oslogin and the value to TRUE.
  5. Click Save.

Option 3: Terraform

resource "google_compute_project_metadata_item" "oslogin" {
  project = "YOUR_PROJECT_ID"
  key     = "enable-oslogin"
  value   = "TRUE"
}

Grant the right IAM roles

Once OS Login is on, users need an IAM role to actually log in. Grant standard access:

gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
  --member="user:[email protected]" \
  --role="roles/compute.osLogin"

For users who need sudo on the VMs:

gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
  --member="user:[email protected]" \
  --role="roles/compute.osAdminLogin"

Danger: Do not enable OS Login project-wide before granting roles/compute.osLogin to the people who need access, including any break-glass account. If you flip the metadata switch first and nobody has the role, you can lock out everyone, including yourself, from SSH access to running VMs.

Connecting after the switch

With OS Login enabled, the standard gcloud SSH command handles key provisioning for you:

gcloud compute ssh INSTANCE_NAME --zone=ZONE --project=YOUR_PROJECT_ID

For external SSH clients, upload your public key to your OS Login profile:

gcloud compute os-login ssh-keys add \
  --key-file=$HOME/.ssh/id_ed25519.pub

Tip: Service accounts can use OS Login too. Grant the service account the same roles/compute.osLogin role and have your automation authenticate through it, rather than embedding a static SSH key in your CI pipeline.


How to prevent it from happening again

Setting the metadata once is not enough if a new project gets created next quarter without it. Bake the requirement into how projects are provisioned and audited.

Enforce with Organization Policy

GCP has a built-in constraint that requires OS Login across an org, folder, or project. Apply it at the org level so every project inherits it:

gcloud resource-manager org-policies enable-enforce \
  compute.requireOsLogin \
  --organization=YOUR_ORG_ID

With this constraint enforced, new projects get OS Login behavior by default and the metadata switch cannot be set back to a non-compliant state.

Note: compute.requireOsLogin is a boolean organization policy constraint. Enforcing it at a high level in your resource hierarchy is the most durable fix, since individual project owners cannot quietly disable OS Login afterward.

Catch it in Terraform with policy-as-code

If your infrastructure goes through Terraform, add a Conftest or OPA policy that fails the plan when the org policy or metadata is missing:

package main

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "google_compute_project_metadata_item"
  resource.change.after.key == "enable-oslogin"
  resource.change.after.value != "TRUE"
  msg := "OS Login must be enabled (enable-oslogin=TRUE) at the project level"
}

Monitor continuously

Organization policy and CI gates cover the resources you manage as code. For drift and for resources created outside that flow, run a continuous check. Lensix evaluates compute_osloginproject across your projects and alerts when OS Login is disabled, so a manually created project or a reverted setting does not slip past your reviews.


Best practices

  • Enable OS Login at the organization level rather than project by project. One policy covers everything, including projects that do not exist yet.
  • Turn on two-factor authentication for SSH by setting enable-oslogin-2fa=TRUE on sensitive projects.
  • Use IAM conditions to scope osLogin grants to specific instances or time windows instead of granting broad project-wide access.
  • Prefer service accounts over user keys for automation, and rotate them through Google-managed mechanisms rather than long-lived static keys.
  • Audit access through IAM, not metadata. Run regular access reviews against the osLogin and osAdminLogin bindings.
  • Block metadata SSH keys alongside OS Login. Once OS Login is on, you can also set block-project-ssh-keys=true on instances to stop anyone reintroducing metadata keys.

OS Login is one of the cheapest security wins available on GCP. There is no cost, the change is a single metadata value, and it converts a messy, per-machine key sprawl problem into a clean IAM-based access model that your auditors will thank you for. The main thing to get right is sequencing: grant the roles, confirm a break-glass path, then enforce.