Skip to content

Hardening

Statement

ClaimGuard's production VM (claim-guard-app-1) is a Google Cloud Deep Learning VM (DLVM) image with a documented incremental-hardening plan against it. The host runs with up-to-date OS packages, on the least-privilege claim-guard-vm service account (swapped 2026-05-02), with Shielded VM Secure Boot enabled (also 2026-05-02), and is operated through IAP-SSH rather than direct sshd. The remaining host-level hardening step — OS Login — is queued for plan step A1.6, deferred because it requires dev-team coordination (re-keying laptops + osLogin grant management).

This control sits at partial specifically because OS Login is not yet enforced. Secure Boot and the SA swap, previously listed here as known gaps, landed 2026-05-02.

Implementation

Host configuration today

  • Image: Google Cloud Deep Learning VM image (Linux). Standard GCP-managed kernel; package updates land via the standard unattended-upgrades / apt flow.
  • Shielded VM:
  • vTPM: on.
  • Integrity monitoring: on.
  • Secure Boot: on (enabled 2026-05-02 in the A1.5 maintenance window combined with A1.1).
  • OS Login: off at the project metadata level (queued for A1.6); SSH today uses metadata-keyed access on top of IAP.
  • Service account: the VM runs under claim-guard-vm@train-cvit2.iam.gserviceaccount.com (least-privilege), swapped from the default Compute SA on 2026-05-02 (plan step A1.1 combined with A1.5). Per-secret secretAccessor bindings only; no project-level roles/editor. See Privileged access.

Process posture

  • pm2 as the process supervisor. Crash-restart, log rotation, and pm2 resurrect on boot via the pm2-roee.service systemd unit (wired 2026-05-02 — until then the dump existed but no boot-time trigger fired it, which surfaced when Tier D rebooted the VM).
  • Application boot depends on JWT_SECRET and other secrets; server refuses to start if they're unset. The values are sourced from local .env today (the Secret Manager fallback exists but the USE_SECRET_MANAGER gate is not flipped on in prod — see Secrets management).
  • No server-side admin daemons beyond what the application requires. No RabbitMQ, no Redis, no Elasticsearch on this VM.

Firewall and SSH

  • No public SSH endpoint. SSH is gated through GCP's IAP. See Privileged access for the IAM side, Network security for the firewall side.
  • No legacy world-open SSH rules. The duplicated allow-ssh / default-allow-ssh rules were deleted on 2026-04-28 (plan step A0.2).

Logging and monitoring

  • Cloud audit logs for every privileged action. 400-day immutable retention. See Audit logging (cloud).
  • Application logs via pm2 stdout / stderr capture, rotated locally. Not yet shipped to Cloud Logging — cross-listed on Application audit logging.
  • Integrity monitoring signals are visible in the GCP console but not yet wired into a paging channel — queued.

What hardening looks like in practice today

  • A1.1 + A1.5 ran together in a maintenance window 2026-05-02. Total observed downtime: ~6 minutes. Pre-window boot-disk snapshot (claim-guard-pre-secboot-2026-05-01) was taken as failsafe and remains in place during the soak period.
  • A1.6 (OS Login) is the remaining bundle item, deferred because it disables the existing metadata-keyed SSH path used by the dev team — needs each operator's laptop re-keyed + osLogin grants managed. Will be scheduled once the team is ready to absorb the change.

What's deliberately not in scope for this page

  • VM-level antivirus / EDR. Out of scope for a Linux GCP VM at this stage.
  • CIS-benchmark scanning. Not running today; revisit at SOC 2 Type II.
  • Container hardening. The application does not run in containers on this VM; tools/services are pm2-managed processes. Container hardening becomes a relevant control if a future architecture introduces them.

Status

partial — verified 2026-05-02.

What's in place:

  • DLVM image with current OS package state.
  • Shielded VM features (vTPM, integrity monitoring, Secure Boot) enabled. Secure Boot landed 2026-05-02 in the A1.5 window.
  • VM runs under least-privilege claim-guard-vm SA (swapped 2026-05-02 in the A1.1 window).
  • IAP-only SSH; no world-open SSH or RDP.
  • pm2 startup wired to systemd (pm2-roee.service) 2026-05-02 — future reboots auto-resurrect the 8 pm2 processes.
  • Documented, reproducible boot path; Secret Manager bootstrap in code (gate not yet flipped — see secrets-management page).
  • Cloud audit logging on every privileged action.

Known gaps

  • OS Login is off — plan step A1.6. Until enabled, SSH metadata-keyed access lives on top of IAP, and stale home directories for removed users persist on the VM. (The corresponding metadata ssh-keys entries for those removed users were cleaned up 2026-05-02; on-disk dirs remain.)
  • USE_SECRET_MANAGER gate is not flipped on in prod. The claim-guard-vm SA holds the per-secret accessor grants but the bootstrap's gate is unset, so secrets actually come from on-disk .env files. Cross-listed on Secrets management.
  • Integrity-monitoring signals are not wired into alerting.
  • No CIS-benchmark scan or routine OS-level vulnerability scan beyond the GCP-managed package update flow.

Roadmap

  • A1.6 (OS Login enable) — needs dev-team re-keying coordination. Closes the metadata-keyed SSH path + enables cleanup of stale home dirs.
  • Activate USE_SECRET_MANAGER=1 + remove secret values from .env files so the runtime data path actually exercises the pre-provisioned SA grants.
  • CIS-benchmark scan at SOC 2 Type II preparation time.
  • Integrity-monitoring alert pipeline wired into the eventual audit-log alerting infrastructure (cross-listed on Incident response).
  • Container hardening framework if and when the architecture introduces containers.