Skip to content

Privileged Access

Statement

Privileged access to ClaimGuard production infrastructure — the GCP project, the production VM, and the data services attached to them — is limited to the founder set, gated through Google's Identity-Aware Proxy (IAP) for shell access, and recorded in an immutable 400-day-retained audit log for every privileged action. Former collaborators have been fully removed from project-level IAM. Right- sizing of active developers' broad project roles is explicitly deferred to avoid disrupting sibling research workloads on the shared GCP project; that work is queued.

Implementation

Project-level owner set

The two principals holding roles/owner on train-cvit2 are:

  • roee@dtectvision.ai
  • dor@dtectvision.ai

This is the post-cleanup state, verified 2026-04-29:

$ gcloud projects get-iam-policy train-cvit2 \
    --flatten='bindings[].members' \
    --filter='bindings.role:roles/owner' \
    --format='value(bindings.members)'
user:dor@dtectvision.ai
user:roee@dtectvision.ai

Three former-collaborator accounts had owner or storage.admin grants before plan step A1.4-step1 and are now fully removed:

Removed Bindings dropped
balashevych.sergey@gmail.com roles/owner, roles/storage.admin
adammokiy@mail.tau.ac.il roles/owner, roles/storage.admin, roles/compute.osAdminLogin
bennohay@gmail.com 8 bindings including roles/aiplatform.admin, roles/artifactregistry.admin, roles/compute.admin, roles/iam.serviceAccountUser, roles/storage.admin

The most security-relevant removal was roles/compute.osAdminLogin on adammokiy@mail.tau.ac.il — that role granted sudo-SSH into every VM in the project. Full per-binding command record lives in docs/security/HARDENING-LOG.md (entry: A1.4-step1).

Administrative SSH

Administrative SSH to claim-guard-app-1 is gated through GCP's Identity-Aware Proxy. There is no public SSH endpoint, no jump host, and no shared bastion VM. The only TCP/22 firewall rule on the VPC is scoped to Google's IAP source range (35.235.240.0/20).

To reach the VM, an operator must:

  1. Hold a GCP IAM role granting roles/iap.tunnelResourceAccessor on the VM resource.
  2. Use gcloud compute ssh ... --tunnel-through-iap.

This means no separate VM credentials (passwords, SSH keys, etc.) are required — IAP authenticates the operator via their Google identity. Removing a person's GCP access removes their VM access in a single action, not two.

The legacy world-open SSH rules (allow-ssh, default-allow-ssh) were deleted on 2026-04-28 (plan step A0.2). See Network security for the firewall side of the same control.

Service account

The application's runtime service account, claim-guard-vm@train-cvit2.iam.gserviceaccount.com, is least-privilege:

  • Project-level: roles/logging.logWriter, roles/monitoring.metricWriter.
  • Per secret (roles/secretmanager.secretAccessor): three claim-guard-* secrets only.
  • No project-Editor. No project-level secret accessor. No GCS bindings (until c2pa migrates from its static JSON key — see Secrets management).

The VM runs under this SA as of 2026-05-02. Plan step A1.1 was executed in a maintenance window combined with A1.5 (Secure Boot enable). Verification:

$ gcloud compute instances describe claim-guard-app-1 \
    --zone=europe-west1-b --project=train-cvit2 \
    --format='value(serviceAccounts[0].email,
                    shieldedInstanceConfig.enableSecureBoot)'
claim-guard-vm@train-cvit2.iam.gserviceaccount.com    True

A boot-disk snapshot (claim-guard-pre-secboot-2026-05-01) was taken before the swap as a failsafe and remains in place during the soak period. Smoke tests passed (Node /health → 200 with DB connection + Secret Manager fetches working under the new SA; 8 pm2 processes online; zero secretmanager/permission denied patterns in 200 lines of post-restart logs).

Audit trail

Every privileged action — IAM mutations, VM lifecycle events, firewall rule changes, service account key operations, secret access — is recorded in the project's _Required Cloud Logging bucket with 400-day immutable retention (locked: true). See Audit logging for the audit-log control.

Multi-factor authentication

All members of the owner set use Google Workspace accounts with mandatory MFA enforced at the Workspace policy level. Sign-in to the Google Cloud Console and gcloud CLI both require MFA via the Workspace identity. Personal @gmail.com collaborator accounts are no longer present in the project after A1.4-step1 with one exception (see "Known gaps").

Workstation hygiene

GCP credentials on operator laptops are stored via gcloud auth login (short-lived ID tokens, refreshable). Long-lived JSON service account keys for human use are not provisioned. The one static JSON key present in the production environment is for a non-human Python workload (google-lens-image-processor-creds.json used by the c2pa tool) and is queued for migration to ADC.

Status

partial — verified 2026-05-02.

What's in place:

  • Owner set is the founder pair; former collaborators fully removed. Verified 2026-04-30 via gcloud projects get-iam-policy train-cvit2 --filter='bindings.role:roles/owner' → only dor@dtectvision.ai and roee@dtectvision.ai.
  • Administrative SSH is gated through IAP; no public SSH path exists.
  • Least-privilege application service account provisioned and in use. The VM was swapped from the default compute SA → claim-guard-vm on 2026-05-02 (combined A1.1 + A1.5 maintenance window). Per-secret roles/secretmanager.secretAccessor confirmed on all three claim-guard-* secrets (claim-guard-jwt-secret, claim-guard-database-url, claim-guard-google-api-key). Spot-check of gs://claim-guard returned no binding for the SA — consistent with "no GCS bindings yet" above. The gs://claim-guard-audit-logs audit-export bucket was added 2026-05-01 with a sink-writer Object Creator binding; see Audit logging.
  • Shielded VM Secure Boot is on (enableSecureBoot=True) alongside the SA swap, plan step A1.5.
  • Every privileged action audit-logged for 400 days, immutable.
  • MFA on all owner accounts via Google Workspace.

Known gaps

  • Org-level admin is gated to a single seat outside the founder pair. roee@dtectvision.ai holds project-roles/owner on train-cvit2 but has no org-level role on the parent organization 857403431877 (verified 2026-05-02 when gcloud scc manage services list --organization=857403431877 returned PERMISSION_DENIED for securitycentermanagement.securityCenterServices.list). The chain of trust runs through whoever holds Workspace super-admin on dtectvision.ai. Documenting the org-admin owner and adding a second seat is a SOC 2 control-design item.
  • Active developers retain broad project roles. idonithid@gmail.com, dev_audio@dtectvision.ai, yalin@dtectvision.ai, orel@dtectvision.ai, ilan@dtectvision.ai hold project-level roles (e.g., roles/storage.admin, roles/compute.admin, roles/artifactregistry.admin) inherited from prior workflows. Right-sizing was deferred per founder request to avoid disrupting in-flight ML work on sibling research workloads in the shared GCP project. See Cloud provider for why the multi-tenant project makes this a delicate cleanup.
  • One personal @gmail.com developer account remains. idonithid@gmail.com is an active critical ML engineer; issuance of a @dtectvision.ai Workspace identity and re-binding of his roles to the new identity is a planned follow-up.
  • OS Login is not yet enforced. enable-oslogin is not set on the project. SSH still uses metadata-keyed access on top of IAP. Enabling OS Login is plan step A1.6, deferred from the 2026-05-02 window because it requires dev-team coordination (re-keying their laptops + osLogin grant management).
  • pm2 startup-on-reboot was missing until 2026-05-02. The pm2 daemon now has a systemd unit (pm2-roee.service) that runs pm2 resurrect at boot; a fresh dump was saved post-Tier-D. Future reboots will auto-restore the 8 pm2 processes; the previous 47h-uptime baseline had hidden the gap.
  • No just-in-time elevation. Owner-level access is granted, not requested. JIT elevation (e.g., a "request access for 30 minutes" flow) is a roadmap item.
  • Stale home directories for removed users (/home/adammokiy, /home/bennohay, /home/Sergey, etc.) still exist on the VM. They no longer have IAM access (and therefore can't log in), but the dirs persist with whatever data was left. Cleanup is deferred to A1.6 (OS Login enable) when the metadata-key model is retired. (The corresponding project-level ssh-keys metadata entries for these users were removed 2026-05-02 — see the HARDENING-LOG entry "Stale SSH metadata keys for removed users — cleaned up".)
  • Several roee-username metadata keys carry comment fields naming other people's Windows machines (COMFYUI-RDP\roee@comfyui-rdp, DESKTOP-42HMUQN\Orel_Shalem, PILAN\ilans@pilan, DTECT1\dtect_dev1@dtect1). Two interpretations: (a) Roee generated them on shared/RDP machines, or (b) other operators have SSH access AS the production roee user — which would mean shared- account access without sudo. Pending operator review.
  • Leftover "test condition" IAM binding on iap.tunnelResourceAccessor for ilan@dtectvision.ai. A second binding for the same role + member exists with title "thinkpad-only", description "test condition", and an instance-scoped expression (resource.name == "projects/700371397073/iap_tunnel/zones/us-central1-a/instances/thinkpad-n2-std8"). This binding is redundant — ilan already has the unconditional binding for the same role, which grants access to all instances including the named thinkpad VM. The conditional binding should be removed (test artifact left in production IAM). Surfaced 2026-05-02.

Roadmap

  • A1.6 — enable OS Login on claim-guard-app-1 (last item of the A1.1 / A1.5 / A1.6 bundle; the first two landed 2026-05-02). Needs dev-team coordination for re-keying.
  • Org-admin owner documentation + second seat — confirm the Workspace super-admin owner of dtectvision.ai, document the delegation chain, and grant roles/resourcemanager.organizationAdmin to a second principal so the org-level control plane has a second seat (currently a single point of failure).
  • A1.4-step3 — right-size active developers' broad project roles, contingent on the dedicated-project move (A1.4-step4) so per-workload role granularity is actually meaningful.
  • A1.4-step4 — move ClaimGuard to a dedicated GCP project. Proper SOC 2 isolation fix.
  • JIT access — evaluate Google Workspace's privileged-access manager or third-party tooling for time-bounded role grants.
  • Periodic access review — quarterly review of project IAM and Workspace group memberships, with sign-off recorded.