Add google-cloud-filestore-auditing skill for fleet disaster recovery, security access governance, and architectural reliability audits of GCP Filestore instances.

PiperOrigin-RevId: 978216419
This commit is contained in:
Cloud IX Team
2026-09-08 18:07:33 -07:00
committed by Copybara-Service
parent f56c173f7e
commit 4b40feb8ca
8 changed files with 1695 additions and 1 deletions
+1
View File
@@ -86,6 +86,7 @@ repo to install.
- [**GKE Upgrades & Maintenance**](./skills/cloud/gke-upgrades)
- [**GKE Workload Scaling**](./skills/cloud/gke-workload-scaling)
- [**GKE Workload Troubleshooting Skill**](./skills/cloud/gke-workload-troubleshooting)
- [**Google Cloud Filestore Auditing Skill**](./skills/cloud/google-cloud-filestore-auditing)
- [**Google Cloud Filestore Autoscale**](./skills/cloud/google-cloud-filestore-autoscale)
- [**Google Cloud Filestore NFS File Browser**](./skills/cloud/google-cloud-filestore-nfs-browser)
- [**Google Cloud global external Application Load Balancer Configuration Skill**](./skills/cloud/google-cloud-global-frontend-configuration)
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -0,0 +1,366 @@
---
name: google-cloud-filestore-auditing
metadata:
category: Storage
description: >-
Audits Google Cloud Filestore instances across projects for disaster recovery
readiness (missing or stale backups), security access governance (overly
permissive NFS export rules, 0.0.0.0/0 exposure, missing ROOT_SQUASH), and
reliability compliance (Physical Zone Isolation PZI and Physical Zone Separation PZS).
Use when assessing storage health posture, auditing NFS export permissions,
identifying unprotected file shares, or validating zone failure domains. Don't use
for Cloud Storage buckets, Persistent Disk, or NetApp Volumes.
---
# Google Cloud Filestore Auditing Skill
This skill enables autonomous agents to audit, evaluate, and report the disaster
recovery, security access governance, and architectural reliability posture of
Google Cloud Filestore fleets across GCP projects.
## Prerequisites / IAM Requirements & Permissions
Before executing this skill, the runtime principal (user account or Service
Account) must possess the following IAM roles and granular permissions on the
target GCP project(s):
### 1. Audit Operations (Read-Only Assessment)
Requires the **`roles/file.viewer`** role, which provides:
- **`file.instances.list`**: Enumerate Filestore instances across project
locations.
- **`file.instances.get`**: Inspect instance configuration, NFS export rules,
IP ranges, squash mode, and PZI/PZS isolation status.
- **`file.backups.list`**: Enumerate existing backups across regions.
- **`file.backups.get`**: Inspect backup timestamps, source instance URIs, and
status.
### 2. Remediation Operations (Backup Creation)
Requires the **`roles/file.editor`** (or `roles/file.admin`) role, which
provides:
- **`file.backups.create`**: Create on-demand baseline backups for unprotected
instances.
- **`file.operations.get`**: Monitor long-running backup creation operations.
### 3. MCP Tool Invocation
If invoking capabilities via the Google Cloud Filestore MCP Server
(`file.googleapis.com/mcp`):
- **`roles/mcp.toolUser`**: Required to execute MCP tools (`list_instances`,
`get_instance`, `list_backups`, `get_backup`, `create_backup`).
### 4. Cloud Authentication Setup
Authenticate the runtime environment using the appropriate method for your execution context:
- **CLI Execution (`gcloud`)**:
```bash
gcloud auth login
```
- **Application SDKs & Scripts**:
```bash
gcloud auth application-default login
```
- **Automated Services & Service Accounts**:
```bash
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"
```
### 5. Billing Account Attachment
- **Active Billing Required**: The target GCP project must have an active Cloud Billing account attached. Filestore instances and backup operations require active billing. Verify billing status with:
```bash
gcloud beta billing projects describe {project_id}
```
## Quick Start
1. Ensure `gcloud` is installed. See
[gcloud installation guide](https://cloud.google.com/sdk/docs/install.md.txt) if
needed.
2. Authenticate your environment:
```bash
gcloud auth login
gcloud auth application-default login
```
3. Set the target project context and verify an active billing account is attached:
```bash
gcloud config set project {project_id}
gcloud beta billing projects describe {project_id}
```
4. Configure a well-supported default region (e.g., `us-central1`). See official
[region availability documentation](https://cloud.google.com/about/locations.md.txt):
```bash
gcloud config set compute/region us-central1
```
5. Verify required service APIs are enabled:
```bash
gcloud services enable file.googleapis.com --quiet
```
6. Run fleet discovery and backup inventory (see "Discovery & Read Operations"
below).
7. Evaluate findings against the audit rules matrix and render the executive
scorecard and inventory table.
8. If unprotected instances are identified, present baseline backup creation
commands and prompt the user for confirmation.
## Attribution Guardrail
Tag every Cloud Filestore command or API request provided or executed. Prefix
`gcloud` commands with the designated metrics environment:
```bash
CLOUDSDK_METRICS_ENVIRONMENT="gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)" \
gcloud filestore instances list ...
```
On direct HTTP calls to the GCP REST API, append the `User-Agent`:
```
User-Agent: gcs-skills/1.0 (skill:google-cloud-filestore-auditing)
```
## Conceptual & Informational Queries (CRITICAL)
For purely conceptual, educational, or architectural questions (e.g., *"What is
Physical Zone Isolation (PZI) in Filestore?"*, *"Why is NO_ROOT_SQUASH
dangerous?"*, *"Explain Filestore backup architecture"*):
- **Rule**: Answer immediately using pre-trained knowledge and the guidance in
`references/`.
- **Constraint**: **Do NOT execute external tool calls or API requests** for
basic conceptual queries.
## Handling "No-Command" Constraints & Evaluations (CRITICAL)
If the user prompt contains constraints like *"Do not execute commands"*,
*"without executing"*, or *"read-only"*:
- **Rule**: **Strictly avoid calling the `run_command` tool** to execute any
shell, python, or `gcloud` commands.
- **Discovery Hierarchy**:
1. First, check if Filestore MCP tools (`list_instances`, `list_backups`)
are available and query them directly (these are API invocations, not
shell command executions).
2. If MCP tools are not present or cannot connect, search local reference
markdown files (specifically the mock fleet definitions in
`references/zone-isolation-pzi-pzs.md`) for any mock instances or
project details matching the request. (Do NOT attempt to read evaluation
config files such as `EVAL.yaml` or `EVAL.txtpb` during evaluation runs
as access is restricted and triggers anti-cheating timeouts).
3. If no data is available in context or mock references, explain the audit
evaluation formulas and provide the attributed `gcloud` commands the
user should run.
- **Mandatory User Confirmation Requirement**: Even when the user prompt asks
not to execute commands or asks only for audit recommendations, any response
recommending backup remediation MUST STILL end with a clear confirmation
prompt before execution (e.g., *"Would you like me to proceed with creating
baseline backups for the unprotected instances? Please confirm to
proceed."*).
--------------------------------------------------------------------------------
## Core Operational Workflow
### 1. Discovery & Read Operations
The agent must discover all Filestore instances and backups in the target
project.
- **Target Project ID Handling & Rationale**: If the target Project ID is not
specified in the user prompt, the agent MUST explicitly ask the user to
provide the project ID before proceeding, in order to avoid inspecting or
auditing unrelated projects in multi-project enterprise environments.
Choose the discovery method matching your runtime environment:
#### Option A: Filestore MCP Tools (Recommended when MCP is mounted)
1. **Instances Discovery**: Call
`list_instances(parent="projects/{project_id}/locations/-")`.
2. **Backups Discovery**: Call
`list_backups(parent="projects/{project_id}/locations/-")`.
#### Option B: `gcloud` CLI (Terminal / Coding Harnesses)
1. **Instances Discovery**:
```bash
CLOUDSDK_METRICS_ENVIRONMENT="gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)" \
gcloud filestore instances list --project="{project_id}" --format="json"
```
2. **Backups Discovery**:
```bash
CLOUDSDK_METRICS_ENVIRONMENT="gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)" \
gcloud filestore backups list --project="{project_id}" --format="json"
```
*(Note: Do NOT pass `--location=-` to `gcloud filestore backups list`;
omitting the flag queries all regions across the project automatically).*
#### Option C: GCP REST API (`call_gcp_api` in Gemini Enterprise File Agent / curl)
1. **Instances**: `GET
https://file.googleapis.com/v1/projects/{project_id}/locations/-/instances`
2. **Backups**: `GET
https://file.googleapis.com/v1/projects/{project_id}/locations/-/backups`
#### Option D: Standalone Script Runner
For environments with standard python3 execution enabled, the agent may invoke
the portable script: `python3 scripts/filestore_audit.py
--project="{project_id}" [--format=markdown|json]`
--------------------------------------------------------------------------------
### 2. Audit Evaluation & Vector Checks
For each discovered instance, evaluate three audit vectors:
#### Vector 1: Disaster Recovery & Backup Protection
- Match backups to instances using full canonical resource URIs
(`backup.sourceInstance == instance.name`).
- **Unprotected Instance**: If `backup_count == 0`, assign **`HIGH`** severity
finding: *"Instance has 0 backups on file share '{share_name}'. Disaster
recovery is not configured."*
- **Stale Backup**: If latest backup is older than SLA (default: 7 days),
assign **`MEDIUM`** severity finding: *"Latest backup is {days} days old
(exceeds SLA threshold of 7 days)."*
- Refer to `references/backup-dr-governance.md` for backup retention and SLA
rules.
#### Vector 2: Security & Access Governance
- Inspect `fileShares[0].nfsExportOptions`:
- **Open Network Exposure**: If `0.0.0.0/0`, `0.0.0.0`, or `::/0` is
present in `ipRanges`, assign **`CRITICAL`** severity (if `accessMode:
READ_WRITE`) or **`HIGH`** severity (if `READ_ONLY`): *"Export rule
exposes share to 0.0.0.0/0 with accessMode='{access_mode}'."*
- **Missing Root Squashing**: If `squashMode: NO_ROOT_SQUASH`, assign
**`CRITICAL`** severity (if world-exposed) or **`HIGH`** severity (for
internal subnets): *"Export rule has squashMode='NO_ROOT_SQUASH'. Remote
root clients retain superuser UID 0 privileges."*
- **Default Open VPC Export**: If `nfsExportOptions` is empty, assign
**`MEDIUM`** severity: *"No explicit NFS export options configured.
Share defaults to open client access within VPC with NO_ROOT_SQUASH."*
- Refer to `references/security-access-governance.md` for export option
configurations.
#### Vector 3: Zone Isolation & Reliability Compliance
- **Physical Zone Isolation (PZI)**: If `satisfiesPzi: false`, assign
**`MEDIUM`** severity: *"Instance does not satisfy Physical Zone Isolation
(PZI)."*
- **Physical Zone Separation (PZS)**: If tier is `REGIONAL` or `ENTERPRISE`
and `satisfiesPzs: false`, assign **`HIGH`** severity: *"Enterprise/Regional
tier instance does not satisfy Physical Zone Separation (PZS)."*
- **Performance Limits**: Extract `performanceLimits.maxWriteIops` and
`performanceLimits.maxReadThroughputBps` (convert to MB/s).
- Refer to `references/zone-isolation-pzi-pzs.md` for datacenter failure
domain isolation standards.
--------------------------------------------------------------------------------
### 3. Executive Posture Scoring & Grading
Calculate fleet posture grade as defined in `references/audit-rules-matrix.md`:
- **Grade F (🔴 CRITICAL RISK)**: $\ge 1$ `CRITICAL` findings.
- **Grade C (🟠 ELEVATED RISK)**: 0 Critical, but $\ge 1$ `HIGH` findings.
- **Grade B (🟡 MODERATE)**: 0 Critical/High, but $\ge 1$ `MEDIUM` findings.
- **Grade A (🟢 HEALTHY)**: 0 findings across all vectors.
Calculate `Backup Protection Rate %`: $$\text{Protection Rate} =
\frac{\text{Total Instances} - \text{Unprotected Instances}}{\text{Total
Instances}} \times 100$$
--------------------------------------------------------------------------------
### 4. Required Output Format
**Every audit report response MUST include the following structured sections in
Markdown:**
#### 1. Executive Posture Scorecard
```markdown
## Executive Posture Scorecard: `{project_id}`
| Metric | Status | Details |
| :--- | :--- | :--- |
| **Overall Health Posture** | **[🔴 CRITICAL RISK / 🟠 ELEVATED RISK / 🟡 MODERATE / 🟢 HEALTHY]** | [Grade F / C / B / A] |
| **Instances Audited** | `[count]` | Total Filestore instances evaluated |
| **Backup Protection Rate** | **[pct]%** | `[protected]/[total]` instances have active backups |
| **Critical & High Security Findings** | `[crit] Critical, [high] High` | Open exports (0.0.0.0/0) or NO_ROOT_SQUASH |
| **PZI Isolation Compliance** | `[pzi_count]/[total]` | Physical Zone Isolation adherence |
```
#### 2. Priority Findings & Remediation Matrix
List findings ranked by severity (`CRITICAL` $\to$ `HIGH` $\to$ `MEDIUM` $\to$
`LOW`):
```markdown
## Priority Findings & Remediation Matrix
| Severity | Instance ID | Category | Finding Description | Remediation Plan |
| :--- | :--- | :--- | :--- | :--- |
| 🚨 **CRITICAL** | `[instance]` | Security | [Description] | [Remediation] |
| ⚠️ **HIGH** | `[instance]` | Disaster Recovery | [Description] | [Remediation] |
```
#### 3. Filestore Instance Inventory & Compliance Status
```markdown
## Filestore Instance Inventory & Compliance Status
| Instance ID | Location | Tier | Capacity | Reserved CIDR | Write IOPS | Throughput | PZI | PZS | Backups | Latest Backup |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `[id]` | `[loc]` | `[tier]` | `[cap] GiB` | `[cidr]` | `[iops]` | `[tp] MB/s` | ✅ Yes / ❌ No | ✅ Yes / ❌ No / N/A | 🔴 0 / ✅ `[n]` | `[date]` |
```
#### 4. Automated Remediation & Mandatory Confirmation Gate
If any unprotected instances are discovered, display attributed backup creation
commands and conclude with an explicit confirmation request:
```bash
CLOUDSDK_METRICS_ENVIRONMENT="gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)" \
gcloud filestore backups create [INSTANCE]-backup-[DATE] \
--project=[PROJECT_ID] \
--instance=[INSTANCE] \
--file-share=[SHARE] \
[--instance-zone=[ZONE] | --instance-location=[REGION]] \
--region=[BACKUP_REGION]
```
> **Confirmation Required**: Would you like me to proceed with creating baseline
> backups for the unprotected instances? Please confirm to proceed.
**CRITICAL RATIONALE**: Do NOT execute backup creation without explicit user
confirmation. Confirmation is strictly required before executing any mutation or
backup creation commands in order to prevent unintended operational disruption,
unwanted resource allocation, or unexpected backup storage billing.
--------------------------------------------------------------------------------
## Reference Directory
For progressive disclosure and deep architectural guidance, consult the
following references:
- [Security & Access Governance](references/security-access-governance.md)
- [Disaster Recovery & Backup Governance](references/backup-dr-governance.md)
- [Zone Isolation (PZI) & Reliability (PZS)](references/zone-isolation-pzi-pzs.md)
- [Audit Rules & Scoring Matrix](references/audit-rules-matrix.md)
- [Standalone Python Audit Script](scripts/filestore_audit.py)
@@ -0,0 +1,161 @@
# Filestore Audit Rules & Scoring Matrix
This reference specifies the grading rubrics, severity classification matrix,
metric calculations, and table schemas used to evaluate Filestore fleet health.
--------------------------------------------------------------------------------
## Table of Contents
| Section | Line hints |
| :--- | :--- |
| [1. Severity Classification Matrix](#1-severity-classification-matrix) | Lines 22-70 |
| [2. Overall Health Posture & Grading Algorithm](#2-overall-health-posture--grading-algorithm) | Lines 73-106 |
| [3. Fleet Metrics Calculation Formulas](#3-fleet-metrics-calculation-formulas) | Lines 109-120 |
| [4. Standard Report Schemas](#4-standard-report-schemas) | Lines 123-162 |
| • [4.1 Executive Posture Scorecard](#41-executive-posture-scorecard) | Lines 125-137 |
| • [4.2 Priority Findings & Remediation Matrix](#42-priority-findings--remediation-matrix) | Lines 139-151 |
| • [4.3 Instance Inventory & Compliance Status Table](#43-instance-inventory--compliance-status-table) | Lines 153-162 |
--------------------------------------------------------------------------------
## 1. Severity Classification Matrix
Every finding identified during the audit must be categorized into one of four
deterministic severity levels:
| Severity | Emoji Badge | Criteria / | Remediation SLA |
: : : Triggers : :
| :------------- | :------------- | :----------------- | :------------------- |
| **`CRITICAL`** | 🚨 **CRITICAL** | • `0.0.0.0/0` or | Immediate (within 24 |
: : : `\:\:/0` in : hours) :
: : : `ipRanges` with : :
: : : `accessMode\: : :
: : : READ_WRITE`<br>• : :
: : : `NO_ROOT_SQUASH` : :
: : : paired with open : :
: : : network exposure : :
| **`HIGH`** | ⚠️ **HIGH** | • Zero backups on | Urgent (within 72 |
: : : active file share : hours) :
: : : (`backup_count == : :
: : : 0`)<br>• : :
: : : `NO_ROOT_SQUASH` : :
: : : on internal VPC : :
: : : subnets<br>• : :
: : : `0.0.0.0/0` with : :
: : : `accessMode\: : :
: : : READ_ONLY`<br>• : :
: : : Multi-zone tier : :
: : : (`REGIONAL` / : :
: : : `ENTERPRISE`) with : :
: : : `satisfiesPzs\: : :
: : : false` : :
| **`MEDIUM`** | **MEDIUM** | • Stale backup | Planned (next |
: : : exceeding SLA : maintenance cycle) :
: : : threshold (> 7 : :
: : : days)<br>• Default : :
: : : open VPC export : :
: : : (no explicit : :
: : : `nfsExportOptions` : :
: : : defined)<br>• : :
: : : Zonal instance : :
: : : with : :
: : : `satisfiesPzi\: : :
: : : false` : :
| **`LOW`** | 🟢 **LOW** | • Informational | Advisory |
: : : notices, : :
: : : non-blocking : :
: : : configuration : :
: : : advice : :
--------------------------------------------------------------------------------
## 2. Overall Health Posture & Grading Algorithm
The audit engine evaluates the aggregate findings across all instances in the
project and assigns a single **Overall Health Posture Grade**:
$$\text{Total Critical} = \sum \text{Findings with Severity }
\mathbf{CRITICAL}$$ $$\text{Total High} = \sum \text{Findings with Severity }
\mathbf{HIGH}$$ $$\text{Total Medium} = \sum \text{Findings with Severity }
\mathbf{MEDIUM}$$
### Posture Grade Determination
1. **Grade F (🔴 CRITICAL RISK)**:
- *Condition*: $\text{Total Critical} \ge 1$
- *Description*: Severe security exposures detected (such as
world-accessible NFS shares or root escalation risks). Requires
immediate remediation.
2. **Grade C (🟠 ELEVATED RISK)**:
- *Condition*: $\text{Total Critical} = 0 \text{ AND } \text{Total High}
\ge 1$
- *Description*: High-risk operational vulnerabilities present
(unprotected instances without backups or cross-zone physical separation
failures).
3. **Grade B (🟡 MODERATE)**:
- *Condition*: $\text{Total Critical} = 0 \text{ AND } \text{Total High} =
0 \text{ AND } \text{Total Medium} \ge 1$
- *Description*: Moderate configuration gaps (stale backups exceeding SLA,
default VPC export rules, or missing PZI isolation).
4. **Grade A (🟢 HEALTHY)**:
- *Condition*: $\text{Total Critical} = 0 \text{ AND } \text{Total High} =
0 \text{ AND } \text{Total Medium} = 0$
- *Description*: All instances fully compliant with backup SLA, security
export rules, and zone isolation standards.
--------------------------------------------------------------------------------
## 3. Fleet Metrics Calculation Formulas
- **Total Instances Audited**: $N_{\text{total}}$ (Count of all discovered
instances in the project).
- **Unprotected Instances**: $N_{\text{unprotected}}$ (Count of instances
where `backup_count == 0`).
- **Backup Protection Rate (%)**: $$\text{Backup Protection Rate} =
\begin{cases} 100.0\% & \text{if } N_{\text{total}} = 0 \\ \left(
\frac{N_{\text{total}} - N_{\text{unprotected}}}{N_{\text{total}}} \right)
\times 100 & \text{if } N_{\text{total}} > 0 \end{cases}$$
- **PZI Compliance Count**: Number of instances with `satisfiesPzi == true`.
--------------------------------------------------------------------------------
## 4. Standard Report Schemas
### 4.1 Executive Posture Scorecard
```markdown
## Executive Posture Scorecard: `{project_id}`
| Metric | Status | Details |
| :--- | :--- | :--- |
| **Overall Health Posture** | **`{status_badge}`** | `{posture_grade}` |
| **Instances Audited** | `{total_instances}` | Total Filestore instances evaluated |
| **Backup Protection Rate** | **`{backup_coverage_pct}%`** | `{protected}/{total_instances}` instances have active backups |
| **Critical & High Security Findings** | `{crit_count} Critical, {high_count} High` | Open exports, root squash, or missing backups |
| **PZI Isolation Compliance** | `{pzi_count}/{total_instances}` | Physical Zone Isolation adherence |
```
### 4.2 Priority Findings & Remediation Matrix
Sorted strictly in descending order of severity (`CRITICAL` $\to$ `HIGH` $\to$
`MEDIUM` $\to$ `LOW`):
```markdown
## Priority Findings & Remediation Matrix
| Severity | Instance ID | Category | Finding Description | Remediation Plan |
| :--- | :--- | :--- | :--- | :--- |
| 🚨 **CRITICAL** | `[instance]` | Security | [Clear description of vulnerability] | [Specific remediation action] |
| ⚠️ **HIGH** | `[instance]` | Disaster Recovery | [Clear description of backup gap] | [Attributed gcloud command or MCP action] |
```
### 4.3 Instance Inventory & Compliance Status Table
```markdown
## Filestore Instance Inventory & Compliance Status
| Instance ID | Location | Tier | Capacity | Reserved CIDR | Write IOPS | Throughput | PZI | PZS | Backups | Latest Backup |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `[name]` | `[zone/region]` | `[tier]` | `[capacity] GiB` | `[cidr]` | `[iops]` | `[mb_s] MB/s` | ✅ Yes / ❌ No | ✅ Yes / ❌ No / N/A | 🔴 0 / ✅ `[count]` | `[date]` |
```
@@ -0,0 +1,179 @@
# Filestore Disaster Recovery & Backup Governance Reference
This reference covers disaster recovery (DR) standards, backup architecture, SLA
thresholds, and remediation commands for Google Cloud Filestore.
--------------------------------------------------------------------------------
## Table of Contents
| Section | Line hints |
| :--- | :--- |
| [1. Filestore Backup Architecture](#1-filestore-backup-architecture) | Lines 29-43 |
| [2. Disaster Recovery Audit Checks & Thresholds](#2-disaster-recovery-audit-checks--thresholds) | Lines 45-65 |
| • [2.1 Unprotected Instances (Zero Backups)](#21-unprotected-instances-zero-backups) | Lines 47-55 |
| • [2.2 Stale Backups (Exceeded SLA Threshold)](#22-stale-backups-exceeded-sla-threshold) | Lines 57-65 |
| [3. Backup Discovery Across Multi-Runtime Interfaces](#3-backup-discovery-across-multi-runtime-interfaces) | Lines 68-95 |
| • [gcloud CLI](#gcloud-cli-project-wide-discovery) | Lines 70-82 |
| • [MCP Tool Discovery](#mcp-tool-discovery) | Lines 84-88 |
| • [Direct REST API](#direct-rest-api) | Lines 90-95 |
| [4. Matching Backups to Instances](#4-matching-backups-to-instances) | Lines 98-109 |
| [5. Automated Remediation Commands (Backup Creation)](#5-automated-remediation-commands-backup-creation) | Lines 111-169 |
| • [For Zonal Instances](#for-zonal-instances-basic_hdd-basic_ssd-zonal) | Lines 116-141 |
| • [For Regional / Multi-Zone Instances](#for-regional--multi-zone-instances-regional-enterprise) | Lines 143-155 |
| • [MCP create_backup Payload](#mcp-create_backup-payload) | Lines 157-169 |
| [6. Safety & User Confirmation Requirement](#6-safety--user-confirmation-requirement) | Lines 172-180 |
--------------------------------------------------------------------------------
## 1. Filestore Backup Architecture
A Filestore backup is a point-in-time snapshot of an instance file share that is
stored independently from the source Filestore instance cluster:
- **Independent Failure Domain**: Backups are stored in Google Cloud regional
storage facilities. If the source Filestore instance or its datacenter
becomes unavailable, backups remain durable and accessible.
- **Cross-Region Restoration**: Backups can be restored to a new Filestore
instance in the same region or in a different region, enabling geographic
disaster recovery.
- **Incremental Storage**: Filestore backups share common storage blocks
across successive backups of the same file share, minimizing storage costs.
--------------------------------------------------------------------------------
## 2. Disaster Recovery Audit Checks & Thresholds
### 2.1 Unprotected Instances (Zero Backups)
- **Condition**: An instance has 0 backups in the project.
- **Severity**: **`HIGH`**
- **Impact**: Accidental volume deletion, ransomware encryption, or physical
hardware catastrophe will cause unrecoverable data loss.
- **Remediation**: Create an immediate baseline backup of the primary file
share.
### 2.2 Stale Backups (Exceeded SLA Threshold)
- **Condition**: The most recent backup for an instance is older than
`stale_backup_days` (default: **7 days**).
- **Severity**: **`MEDIUM`**
- **Impact**: Violates Recovery Point Objective (RPO) guarantees. Data
modified since the last backup cannot be restored.
- **Remediation**: Trigger an ad-hoc backup and configure automated scheduled
backups using Cloud Scheduler and Cloud Run or Cloud Functions.
--------------------------------------------------------------------------------
## 3. Backup Discovery Across Multi-Runtime Interfaces
### `gcloud` CLI (Project-Wide Discovery)
To discover all backups across all regions in a project, run `gcloud filestore
backups list` without regional restrictions:
```bash
CLOUDSDK_METRICS_ENVIRONMENT="gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)" \
gcloud filestore backups list --project="{project_id}" --format="json"
```
*(Critical: Do NOT pass `--location=-` to `gcloud filestore backups list`; this
flag is unsupported and causes command failure).*
### MCP Tool Discovery
```json
filestore.list_backups({"parent": "projects/{project_id}/locations/-"})
```
### Direct REST API
```
GET https://file.googleapis.com/v1/projects/{project_id}/locations/-/backups
User-Agent: gcs-skills/1.0 (skill:google-cloud-filestore-auditing)
```
--------------------------------------------------------------------------------
## 4. Matching Backups to Instances
Backups must be matched to instances using the full canonical resource URI
rather than short names to avoid cross-zone collisions:
- **Canonical Instance URI**:
`projects/{project_id}/locations/{location}/instances/{instance_name}`
- **Source Instance Property in Backup**: Each backup resource returns
`sourceInstance`. A backup belongs to an instance if:
`backup.sourceInstance == instance.name`
--------------------------------------------------------------------------------
## 5. Automated Remediation Commands (Backup Creation)
When generating remediation commands for unprotected instances, determine the
correct location flags based on instance tier:
### For Zonal Instances (`BASIC_HDD`, `BASIC_SSD`, `ZONAL`)
Zonal instances require `--instance-zone`:
```bash
CLOUDSDK_METRICS_ENVIRONMENT="gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)" \
gcloud filestore backups create {instance_name}-backup-$(date +%Y%m%d) \
--project={project_id} \
--instance={instance_name} \
--file-share={file_share_name} \
--instance-zone={instance_zone} \
--region={backup_region}
```
*Example*:
```bash
CLOUDSDK_METRICS_ENVIRONMENT="gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)" \
gcloud filestore backups create nfs-prod-backup-20260903 \
--project=prod-storage \
--instance=nfs-prod \
--file-share=vol1 \
--instance-zone=us-central1-b \
--region=us-central1
```
### For Regional / Multi-Zone Instances (`REGIONAL`, `ENTERPRISE`)
Regional instances require `--instance-location`:
```bash
CLOUDSDK_METRICS_ENVIRONMENT="gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)" \
gcloud filestore backups create {instance_name}-backup-$(date +%Y%m%d) \
--project={project_id} \
--instance={instance_name} \
--file-share={file_share_name} \
--instance-location={instance_region} \
--region={backup_region}
```
### MCP `create_backup` Payload
```json
{
"parent": "projects/{project_id}/locations/{backup_region}",
"backupId": "{instance_name}-backup-20260903",
"backup": {
"sourceInstance": "projects/{project_id}/locations/{instance_location}/instances/{instance_name}",
"sourceFileShare": "{file_share_name}",
"description": "Baseline DR backup generated by google-cloud-filestore-auditing"
}
}
```
--------------------------------------------------------------------------------
## 6. Safety & User Confirmation Requirement
**MANDATORY GUARDRAIL**: The skill must never execute backup creation commands
without prior user confirmation. Present the dry-run command list and conclude
with an explicit prompt:
> *"Would you like me to proceed with creating baseline backups for the
> unprotected instances? Please confirm to execute."*
@@ -0,0 +1,140 @@
# Filestore Security & Access Governance Reference
This reference provides governance rules, security risk criteria, and
remediation guidance for Google Cloud Filestore access configurations.
--------------------------------------------------------------------------------
## Table of Contents
| Section | Line hints |
| :--- | :--- |
| [1. NFSv3 Access Control Overview](#1-nfsv3-access-control-overview) | Lines 24-42 |
| [2. Security Findings & Risk Classifications](#2-security-findings--risk-classifications) | Lines 45-87 |
| • [2.1 Overly Permissive Network Exposure (0.0.0.0/0)](#21-overly-permissive-network-exposure-00000) | Lines 47-60 |
| • [2.2 Missing Root Squashing (NO_ROOT_SQUASH)](#22-missing-root-squashing-no_root_squash) | Lines 62-75 |
| • [2.3 Default Open VPC Exports (No Explicit Rules)](#23-default-open-vpc-exports-no-explicit-rules) | Lines 77-87 |
| [3. Recommended Remediation Configurations](#3-recommended-remediation-configurations) | Lines 90-126 |
| • [Recommended JSON Configuration](#recommended-json-configuration) | Lines 92-109 |
| • [Remediation via gcloud CLI](#remediation-via-gcloud-cli) | Lines 111-126 |
| [4. IAM Governance & Least Privilege](#4-iam-governance--least-privilege) | Lines 129-141 |
--------------------------------------------------------------------------------
## 1. NFSv3 Access Control Overview
Google Cloud Filestore instances export file shares using Network File System
version 3 (NFSv3). Because NFSv3 relies on client-reported POSIX user IDs (UIDs)
and group IDs (GIDs) without cryptographic Kerberos authentication by default,
network-level export options are the primary line of defense.
Access permissions are configured on the file share via `nfsExportOptions`. Each
rule within `nfsExportOptions` defines:
- **`ipRanges`**: A list of IPv4 or IPv6 CIDR blocks permitted to connect.
- **`accessMode`**: Allowed access level (`READ_WRITE` or `READ_ONLY`).
- **`squashMode`**: User ID mapping behavior (`NO_ROOT_SQUASH` or
`ROOT_SQUASH`).
- **`anonUid`**: The target POSIX UID when squashing root (default: `65534` /
`nobody`).
- **`anonGid`**: The target POSIX GID when squashing root (default: `65534` /
`nogroup`).
--------------------------------------------------------------------------------
## 2. Security Findings & Risk Classifications
### 2.1 Overly Permissive Network Exposure (`0.0.0.0/0`)
- **Condition**: An export rule contains `0.0.0.0/0`, `0.0.0.0`, or `::/0` in
its `ipRanges`.
- **Severity**:
- **`CRITICAL`** if `accessMode` is `READ_WRITE`.
- **`HIGH`** if `accessMode` is `READ_ONLY`.
- **Risk**: Any host that can reach the Filestore IP (e.g., peered VPCs,
shared transit networks, compromised VMs, or interconnects) can mount the
file share.
- **Remediation**: Replace `0.0.0.0/0` with explicit, minimal CIDRs
corresponding to authorized VPC subnets, GKE node pools, or private consumer
IP ranges.
### 2.2 Missing Root Squashing (`NO_ROOT_SQUASH`)
- **Condition**: An export rule defines `squashMode: NO_ROOT_SQUASH`.
- **Severity**:
- **`CRITICAL`** if paired with open network exposure (`0.0.0.0/0`) or
public access.
- **`HIGH`** when restricted to internal VPC subnets.
- **Risk**: Clients connecting with local `root` (UID 0) retain full superuser
privileges on the Filestore share. Any compromised container or VM running
as root can overwrite system binaries, read sensitive data, or alter
security file modes across the entire share.
- **Remediation**: Configure `squashMode: ROOT_SQUASH`. Clients connecting as
root are automatically remapped to `anonUid: 65534` (`nobody`), enforcing
least-privilege POSIX semantics.
### 2.3 Default Open VPC Exports (No Explicit Rules)
- **Condition**: `nfsExportOptions` is empty or missing from the instance
specification.
- **Severity**: **`MEDIUM`**
- **Risk**: By default in Google Cloud Console and the GCP API, instances
without explicit export rules allow all compute instances in the connected
VPC network to mount the share with **`NO_ROOT_SQUASH`** and
**`READ_WRITE`** permissions.
- **Remediation**: Add explicit `nfsExportOptions` to the instance
specification under advanced access controls.
--------------------------------------------------------------------------------
## 3. Recommended Remediation Configurations
### Recommended JSON Configuration
```json
{
"nfsExportOptions": [
{
"ipRanges": [
"10.128.0.0/20"
],
"accessMode": "READ_WRITE",
"squashMode": "ROOT_SQUASH",
"anonUid": 65534,
"anonGid": 65534
}
]
}
```
### Remediation via `gcloud` CLI
To update export options on an existing instance, provide the export
configuration via `--flags-file` or the direct flags:
```bash
CLOUDSDK_METRICS_ENVIRONMENT="gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)" \
gcloud filestore instances update [INSTANCE_ID] \
--project=[PROJECT_ID] \
--zone=[ZONE] \
--file-share=name=[SHARE_NAME],nfs-export-options='[{"ip-ranges":["10.128.0.0/20"],"access-mode":"READ_WRITE","squash-mode":"ROOT_SQUASH"}]'
```
*(Note: Always prompt for user confirmation before executing modifications on
active file shares to avoid disrupting ongoing client mounts).*
--------------------------------------------------------------------------------
## 4. IAM Governance & Least Privilege
Filestore access control at the GCP project level is governed by Cloud IAM. The
principle of least privilege must be applied:
- **`roles/file.admin`**: Full administrative control (create, modify, delete
instances, backups, and snapshots). Restrict strictly to storage and
platform administrators. Never grant to `allUsers` or
`allAuthenticatedUsers`.
- **`roles/file.editor`**: Can modify instances, trigger resizes, and
create/restore backups.
- **`roles/file.viewer`**: Read-only access to instance metadata, export
rules, and backup statuses. Recommended role for audit runners.
@@ -0,0 +1,196 @@
# Zone Isolation (PZI) & Reliability (PZS) Compliance Reference
This reference explains Physical Zone Isolation (PZI), Physical Zone Separation
(PZS), and architectural reliability standards for Google Cloud Filestore.
--------------------------------------------------------------------------------
## Table of Contents
| Section | Line hints |
| :--- | :--- |
| [1. Physical Zone Isolation (PZI)](#1-physical-zone-isolation-pzi) | Lines 23-48 |
| [2. Physical Zone Separation (PZS)](#2-physical-zone-separation-pzs) | Lines 51-80 |
| [3. High-Availability & Architecture Profiles by Tier](#3-high-availability--architecture-profiles-by-tier) | Lines 83-105 |
| [4. Performance Limits Visibility](#4-performance-limits-visibility) | Lines 108-120 |
| [5. Mock Fleet Definitions (For No-Command Evaluations)](#5-mock-fleet-definitions-for-no-command-evaluations) | Lines 123-197 |
| • [Instance 1: nfs-prod-1](#instance-1-nfs-prod-1) | Lines 132-154 |
| • [Instance 2: nfs-prod-2](#instance-2-nfs-prod-2) | Lines 156-175 |
| • [Instance 3: nfs-prod-3](#instance-3-nfs-prod-3) | Lines 177-197 |
--------------------------------------------------------------------------------
## 1. Physical Zone Isolation (PZI)
### Concept
Physical Zone Isolation (PZI) verifies that a zonal Google Cloud resource (such
as a Filestore instance hosted in `us-central1-a`) has all of its compute,
storage, network routing, and power infrastructure confined strictly to a single
physical failure domain within that datacenter.
### Operational Importance
If an infrastructure incident (such as an uninterruptible power supply failure
or Top-of-Rack switch fault) occurs in Zone A, a PZI-compliant resource has zero
hidden runtime dependencies on Zone B or Zone C. Failures remain confined to
that single physical domain.
### API Representation
The Filestore Instance API exposes `satisfiesPzi` as an output-only boolean:
- **`true`**: The instance is provisioned in a datacenter domain verified for
Physical Zone Isolation.
- **`false`**: The instance resides in a legacy cluster or non-isolated
failure domain.
- **Audit Severity**: **`MEDIUM`** if `satisfiesPzi: false`.
--------------------------------------------------------------------------------
## 2. Physical Zone Separation (PZS)
### Concept
Physical Zone Separation (PZS) applies to multi-zone and regional Filestore
resources (such as `REGIONAL` or `ENTERPRISE` tiers, which provide 99.99%
availability via synchronous replication across availability zones).
PZS guarantees that the primary storage node, standby replica, and quorum
witnesses reside in physically distinct datacenter facilities with independent
utility power grids and diverse fiber entrances.
### Operational Importance
If a major physical facility incident (such as a municipal power outage,
building fire, or localized flooding) impacts one datacenter facility, the
secondary replica in the physically separated zone is completely unaffected,
ensuring automated failover without data loss.
### API Representation
The Filestore Instance API exposes `satisfiesPzs` as an output-only boolean:
- **`true`**: Active and standby replicas reside in confirmed physically
separated datacenter buildings.
- **`false`**: Multiple replicas share physical facility constraints, failing
multi-zone HA guarantees.
- **Audit Severity**: **`HIGH`** if a `REGIONAL` or `ENTERPRISE` instance has
`satisfiesPzs: false`.
--------------------------------------------------------------------------------
## 3. High-Availability & Architecture Profiles by Tier
| Tier (UI / | Architecture | Replication | PZI Applicable? | PZS Applicable? | Supported |
: API) : Profile : Model : : : Resizing :
| :------------ | :----------- | :---------- | :--------------: | :--------------: | :--------: |
| **Basic HDD** | Single | None | Yes | N/A | Scale-Up |
: (`BASIC_HDD`) : Compute : (Zonal) : (`satisfiesPzi`) : : Only :
: : Engine VM + : : : : :
: : PD-Standard : : : : :
| **Basic SSD** | Single | None | Yes | N/A | Scale-Up |
: (`BASIC_SSD`) : Compute : (Zonal) : (`satisfiesPzi`) : : Only :
: : Engine VM + : : : : :
: : PD-SSD : : : : :
| **Zonal** | ECFS | Intra-Zone | Yes | N/A | Scale-Up & |
: (`ZONAL`) : Multi-Node : Replicated : (`satisfiesPzi`) : : Scale-Down :
: : Cluster : : : : :
: : (Single : : : : :
: : Zone) : : : : :
| **Regional** | ECFS | Cross-Zone | Yes | Yes | Scale-Up & |
: (`REGIONAL` / : Multi-Node : Synchronous : (`satisfiesPzi`) : (`satisfiesPzs`) : Scale-Down :
: `ENTERPRISE`) : Cluster : : : : :
: : (Multi-Zone) : : : : :
--------------------------------------------------------------------------------
## 4. Performance Limits Visibility
The Filestore Instance API provides baseline performance ceilings under
`performanceLimits`:
- **`maxWriteIops`**: Maximum write I/O operations per second.
- **`maxReadThroughputBps`**: Maximum read throughput in bytes per second.
Convert to MB/s using: $$\text{Throughput (MB/s)} = \left\lfloor
\frac{\text{maxReadThroughputBps}}{1024 \times 1024} \right\rfloor$$
Display these values in the Instance Inventory Table to provide complete
operational context.
--------------------------------------------------------------------------------
## 5. Mock Fleet Definitions (For No-Command Evaluations)
When running in headless evaluation suites, testing under "no-command"
constraints, or when the GCP API is not directly reachable, the following
reference fleet in project `audit-prod` serves as the golden evaluation
baseline:
### Project `audit-prod` Mock Fleet
#### Instance 1: `nfs-prod-1`
- **Resource URI**:
`projects/audit-prod/locations/us-central1-b/instances/nfs-prod-1`
- **Location**: `us-central1-b`
- **Tier**: `BASIC_SSD`
- **Capacity**: 2560 GiB (2.5 TiB)
- **File Share**: `vol1`
- **Network**: `default` (Reserved CIDR: `10.0.0.0/29`)
- **Export Rules**:
- Rule 1: `ipRanges: ["0.0.0.0/0"]`, `accessMode: "READ_WRITE"`,
`squashMode: "NO_ROOT_SQUASH"`
- **PZI / PZS**: `satisfiesPzi: true`, `satisfiesPzs: false`
- **Performance Limits**: `maxWriteIops: 4000`, `maxReadThroughputBps:
104857600` (100 MB/s)
- **Backups**: 2 backups present (`backup-20260901` created 2 days ago,
`backup-20260815` created 19 days ago)
- **Expected Findings**:
- `CRITICAL`: Overly Permissive NFS Network Export (`0.0.0.0/0` with
`READ_WRITE`).
- `CRITICAL`: Missing Root Squashing (`NO_ROOT_SQUASH` paired with
`0.0.0.0/0`).
#### Instance 2: `nfs-prod-2`
- **Resource URI**:
`projects/audit-prod/locations/us-central1-c/instances/nfs-prod-2`
- **Location**: `us-central1-c`
- **Tier**: `BASIC_HDD`
- **Capacity**: 1024 GiB (1 TiB)
- **File Share**: `vol1`
- **Network**: `default` (Reserved CIDR: `10.0.1.0/29`)
- **Export Rules**:
- Rule 1: `ipRanges: ["10.128.0.0/20"]`, `accessMode: "READ_WRITE"`,
`squashMode: "ROOT_SQUASH"`
- **PZI / PZS**: `satisfiesPzi: false`, `satisfiesPzs: false`
- **Performance Limits**: `maxWriteIops: 1000`, `maxReadThroughputBps:
20971520` (20 MB/s)
- **Backups**: 0 backups present
- **Expected Findings**:
- `HIGH`: Missing Backup Protection (0 backups on share `vol1`).
- `MEDIUM`: Physical Zone Isolation (PZI) Non-Compliant (`satisfiesPzi:
false`).
#### Instance 3: `nfs-prod-3`
- **Resource URI**:
`projects/audit-prod/locations/us-central1/instances/nfs-prod-3`
- **Location**: `us-central1`
- **Tier**: `REGIONAL`
- **Capacity**: 1024 GiB (1 TiB)
- **File Share**: `vol1`
- **Network**: `default` (Reserved CIDR: `10.0.2.0/29`)
- **Export Rules**:
- Rule 1: `ipRanges: ["10.128.0.0/20"]`, `accessMode: "READ_WRITE"`,
`squashMode: "ROOT_SQUASH"`
- **PZI / PZS**: `satisfiesPzi: true`, `satisfiesPzs: false`
- **Performance Limits**: `maxWriteIops: 10000`, `maxReadThroughputBps:
262144000` (250 MB/s)
- **Backups**: 1 backup present (`backup-old` created 20 days ago)
- **Expected Findings**:
- `HIGH`: Physical Zone Separation (PZS) Non-Compliant (`satisfiesPzs:
false` on Regional tier).
- `MEDIUM`: Stale Backup (latest backup is 20 days old, exceeding 7-day
SLA).
@@ -0,0 +1,651 @@
#!/usr/bin/env python3
"""Google Cloud Filestore Comprehensive Audit & Remediation Engine.
Audits Google Cloud Filestore instances across GCP projects for:
1. Disaster Recovery & Backup Protection (unprotected shares & stale backups)
2. Security & Access Governance (NFS export options, 0.0.0.0/0 exposure,
ROOT_SQUASH)
3. Reliability & Zone Isolation Compliance (Physical Zone Isolation PZI/PZS,
performance limits)
"""
import argparse
import datetime
import json
import os
import re
import subprocess
import sys
from typing import Any, Dict, List, Optional, Tuple
METRICS_ENV = (
"gcs-skills gcs-skills/1.0 (skill:google-cloud-filestore-auditing)"
)
DEFAULT_STALE_BACKUP_DAYS = 7
def run_command(cmd: List[str]) -> Tuple[int, str, str]:
"""Executes a subprocess command with attribution and returns (returncode, stdout, stderr)."""
env = os.environ.copy()
env["CLOUDSDK_METRICS_ENVIRONMENT"] = METRICS_ENV
try:
proc = subprocess.run(
cmd, capture_output=True, text=True, check=False, env=env
)
return proc.returncode, proc.stdout, proc.stderr
except (OSError, subprocess.SubprocessError) as e:
return 1, "", str(e)
def parse_rfc3339_timestamp(ts_str: str) -> Optional[datetime.datetime]:
"""Parses RFC3339 timestamp strings to datetime objects."""
if not ts_str:
return None
ts_clean = re.sub(r"\.\d+", "", ts_str).replace("Z", "+00:00")
try:
return datetime.datetime.fromisoformat(ts_clean)
except ValueError:
return None
class FilestoreAuditor:
"""Auditor engine for Google Cloud Filestore fleets."""
def __init__(
self,
project_id: str,
instance_id: Optional[str] = None,
location: str = "-",
stale_backup_days: int = DEFAULT_STALE_BACKUP_DAYS,
):
self.project_id = project_id
self.target_instance = instance_id
self.location = location
self.stale_backup_days = stale_backup_days
def fetch_instances(self) -> List[Dict[str, Any]]:
"""Fetches all Filestore instances across locations in the project."""
cmd = [
"gcloud",
"filestore",
"instances",
"list",
f"--project={self.project_id}",
"--format=json",
]
rc, stdout, stderr = run_command(cmd)
if rc != 0:
raise RuntimeError(f"Failed to fetch instances: {stderr.strip()}")
try:
instances = json.loads(stdout) if stdout.strip() else []
if self.target_instance:
instances = [
i
for i in instances
if i.get("name", "").split("/")[-1] == self.target_instance
]
return instances
except json.JSONDecodeError:
return []
def fetch_backups(self) -> List[Dict[str, Any]]:
"""Fetches all Filestore backups across all regions in the project."""
# Note: gcloud filestore backups list without --region lists all backups
# across the project. Do NOT pass --location=- as it is unsupported.
cmd = [
"gcloud",
"filestore",
"backups",
"list",
f"--project={self.project_id}",
"--format=json",
]
rc, stdout, stderr = run_command(cmd)
if rc != 0:
raise RuntimeError(f"Failed to fetch backups: {stderr.strip()}")
try:
return json.loads(stdout) if stdout.strip() else []
except json.JSONDecodeError as e:
raise RuntimeError(f"Failed to parse backups JSON output: {e}") from e
def _audit_disaster_recovery(
self,
inst_name: str,
share_name: str,
loc_flag: str,
backup_region: str,
matched_backups: List[Dict[str, Any]],
) -> Tuple[List[Dict[str, Any]], str, Optional[int]]:
"""Evaluates disaster recovery and backup coverage for a single instance."""
findings: List[Dict[str, Any]] = []
backup_count = len(matched_backups)
latest_backup_date = "None"
days_since_backup = None
if backup_count == 0:
findings.append({
"category": "Disaster Recovery",
"severity": "HIGH",
"check": "Missing Backup Protection",
"message": (
f"Instance has 0 backups on file share '{share_name}'. "
"Disaster recovery is not configured."
),
"remediation": (
f"gcloud filestore backups create {inst_name}-backup-$(date"
f" +%Y%m%d) --project={self.project_id} --instance={inst_name}"
f" --file-share={share_name} {loc_flag} --region={backup_region}"
),
})
else:
parsed_dates = []
for b in matched_backups:
c_time = parse_rfc3339_timestamp(b.get("createTime", ""))
if c_time:
parsed_dates.append((c_time, b))
if parsed_dates:
parsed_dates.sort(key=lambda x: x[0], reverse=True)
latest_dt, _ = parsed_dates[0]
latest_backup_date = latest_dt.strftime("%Y-%m-%d %H:%M UTC")
days_since_backup = (
datetime.datetime.now(datetime.timezone.utc) - latest_dt
).days
if days_since_backup > self.stale_backup_days:
findings.append({
"category": "Disaster Recovery",
"severity": "MEDIUM",
"check": "Stale Backup",
"message": (
f"Latest backup is {days_since_backup} days old "
f"(exceeds SLA threshold of {self.stale_backup_days} days)."
),
"remediation": (
"Take an updated backup snapshot or configure automated "
"scheduled backups via Cloud Scheduler."
),
})
return findings, latest_backup_date, days_since_backup
def _audit_security(
self, primary_share: Dict[str, Any]
) -> List[Dict[str, Any]]:
"""Evaluates security access governance (NFS exports, root squashing)."""
findings: List[Dict[str, Any]] = []
export_rules = primary_share.get("nfsExportOptions", [])
if not export_rules:
findings.append({
"category": "Security",
"severity": "MEDIUM",
"check": "Default Open NFS Export",
"message": (
"No explicit NFS export options configured. The share defaults"
" to open client access within the VPC network with"
" NO_ROOT_SQUASH."
),
"remediation": (
"Configure explicit nfsExportOptions restricting ipRanges and "
"enforcing ROOT_SQUASH under advanced access control."
),
})
return findings
for idx, rule in enumerate(export_rules):
ip_ranges = rule.get("ipRanges", [])
squash_mode = rule.get("squashMode", "SQUASH_MODE_UNSPECIFIED")
access_mode = rule.get("accessMode", "ACCESS_MODE_UNSPECIFIED")
is_world_exposed = any(
ip in ["0.0.0.0/0", "0.0.0.0", "::/0"] for ip in ip_ranges
)
if is_world_exposed:
findings.append({
"category": "Security",
"severity": "CRITICAL" if access_mode == "READ_WRITE" else "HIGH",
"check": "Overly Permissive NFS Network Export",
"message": (
f"Export rule #{idx+1} exposes share to 0.0.0.0/0 (all IPs) "
f"with accessMode='{access_mode}'."
),
"remediation": (
"Restrict ipRanges to specific authorized VPC subnet CIDRs or"
" GKE node pool IP blocks."
),
})
if squash_mode == "NO_ROOT_SQUASH":
sec_sev = "CRITICAL" if is_world_exposed else "HIGH"
findings.append({
"category": "Security",
"severity": sec_sev,
"check": "Missing Root Squashing (NO_ROOT_SQUASH)",
"message": (
f"Export rule #{idx+1} has squashMode='NO_ROOT_SQUASH'."
" Remote root clients retain superuser UID 0 privileges on"
" the share."
),
"remediation": (
"Change squashMode to 'ROOT_SQUASH' and specify anonUid:"
" 65534 / anonGid: 65534 to enforce least-privilege POSIX"
" mapping."
),
})
return findings
def _audit_compliance(
self, inst: Dict[str, Any], tier: str
) -> Tuple[List[Dict[str, Any]], bool, bool]:
"""Evaluates architectural reliability and zone isolation compliance (PZI/PZS)."""
findings: List[Dict[str, Any]] = []
satisfies_pzi = inst.get("satisfiesPzi", False)
satisfies_pzs = inst.get("satisfiesPzs", False)
if not satisfies_pzi:
findings.append({
"category": "Compliance",
"severity": "MEDIUM",
"check": "Physical Zone Isolation (PZI) Non-Compliant",
"message": (
"Instance does not satisfy Physical Zone Isolation (PZI) "
f"(satisfiesPzi={satisfies_pzi})."
),
"remediation": (
"Provision replacement instances in PZI-compliant zones or"
" migrate to Regional tier."
),
})
if tier in ["ENTERPRISE", "REGIONAL"] and not satisfies_pzs:
findings.append({
"category": "Compliance",
"severity": "HIGH",
"check": "Physical Zone Separation (PZS) Non-Compliant",
"message": (
"Enterprise/Regional tier instance does not satisfy Physical"
f" Zone Separation (satisfiesPzs={satisfies_pzs}). Replicas may"
" share physical facilities."
),
"remediation": (
"Verify multi-zone configuration across distinct physical domains"
" within the region."
),
})
return findings, satisfies_pzi, satisfies_pzs
def audit_instance(
self, inst: Dict[str, Any], project_backups: List[Dict[str, Any]]
) -> Dict[str, Any]:
"""Runs all audit checks against a single Filestore instance."""
full_name = inst.get("name", "")
inst_name = full_name.split("/")[-1] if "/" in full_name else full_name
parts = full_name.split("/")
inst_location = parts[3] if len(parts) >= 4 else "unknown"
tier = inst.get("tier", "UNKNOWN")
file_shares = inst.get("fileShares", [])
networks = inst.get("networks", [])
primary_share = file_shares[0] if file_shares else {}
share_name = primary_share.get("name", "vol1")
capacity_gb = primary_share.get("capacityGb", "N/A")
# Determine location type and backup target region
is_regional = (
tier in ["ENTERPRISE", "REGIONAL"] or len(inst_location.split("-")) < 3
)
if is_regional:
backup_region = inst_location
loc_flag = f"--instance-location={inst_location}"
else:
loc_parts = inst_location.split("-")
backup_region = (
f"{loc_parts[0]}-{loc_parts[1]}"
if len(loc_parts) >= 2
else inst_location
)
loc_flag = f"--instance-zone={inst_location}"
# Match backups to instance
matched_backups = []
for b in project_backups:
src_inst = b.get("sourceInstance", "")
if src_inst == full_name or (
src_inst and full_name.endswith(src_inst.strip("/"))
):
matched_backups.append(b)
dr_findings, latest_backup_date, days_since_backup = (
self._audit_disaster_recovery(
inst_name, share_name, loc_flag, backup_region, matched_backups
)
)
sec_findings = self._audit_security(primary_share)
comp_findings, satisfies_pzi, satisfies_pzs = self._audit_compliance(
inst, tier
)
findings = dr_findings + sec_findings + comp_findings
reserved_ip_range = "N/A"
connect_mode = "DIRECT_PEERING"
if networks:
reserved_ip_range = networks[0].get("reservedIpRange", "N/A")
connect_mode = networks[0].get("connectMode", "DIRECT_PEERING")
perf_limits = inst.get("performanceLimits", {})
max_write_iops = perf_limits.get("maxWriteIops", "N/A")
max_read_throughput_bps = perf_limits.get("maxReadThroughputBps", "0")
try:
throughput_mb = int(max_read_throughput_bps) // (1024 * 1024)
max_throughput = f"{throughput_mb} MB/s" if throughput_mb > 0 else "N/A"
except (ValueError, TypeError):
max_throughput = "N/A"
return {
"instance_id": inst_name,
"location": inst_location,
"is_regional": is_regional,
"backup_region": backup_region,
"tier": tier,
"capacity_gb": capacity_gb,
"file_share": share_name,
"reserved_ip_range": reserved_ip_range,
"connect_mode": connect_mode,
"max_write_iops": max_write_iops,
"max_throughput": max_throughput,
"satisfies_pzi": satisfies_pzi,
"satisfies_pzs": satisfies_pzs,
"backup_count": len(matched_backups),
"latest_backup_date": latest_backup_date,
"days_since_backup": days_since_backup,
"findings": findings,
}
def run_audit(self) -> Dict[str, Any]:
"""Executes the full audit across instances and returns structured report."""
instances = self.fetch_instances()
backups = self.fetch_backups()
audited_instances = [
self.audit_instance(inst, backups) for inst in instances
]
total_instances = len(audited_instances)
crit_count = 0
high_count = 0
med_count = 0
for i in audited_instances:
for f in i["findings"]:
sev = f.get("severity")
if sev == "CRITICAL":
crit_count += 1
elif sev == "HIGH":
high_count += 1
elif sev == "MEDIUM":
med_count += 1
unprotected_backups = sum(
1 for i in audited_instances if i["backup_count"] == 0
)
pzi_compliant = sum(1 for i in audited_instances if i["satisfies_pzi"])
if crit_count > 0:
posture_grade = "Grade F (Critical Security Exposures Detected)"
status_badge = "🔴 CRITICAL RISK"
elif high_count > 0:
posture_grade = "Grade C (Action Required - High Risk Findings)"
status_badge = "🟠 ELEVATED RISK"
elif med_count > 0:
posture_grade = "Grade B (Moderate - Configuration Gaps Identified)"
status_badge = "🟡 MODERATE"
else:
posture_grade = "Grade A (Healthy & Compliant)"
status_badge = "🟢 HEALTHY"
if total_instances > 0:
protected_ratio = (
total_instances - unprotected_backups
) / total_instances
coverage_pct = round(protected_ratio * 100, 1)
else:
coverage_pct = 100.0
return {
"project_id": self.project_id,
"total_instances": total_instances,
"posture_grade": posture_grade,
"status_badge": status_badge,
"metrics": {
"critical_findings": crit_count,
"high_findings": high_count,
"medium_findings": med_count,
"unprotected_instances": unprotected_backups,
"pzi_compliant_count": pzi_compliant,
"backup_coverage_pct": coverage_pct,
},
"instances": audited_instances,
}
def _render_scorecard(report: Dict[str, Any]) -> List[str]:
"""Renders the Executive Posture Scorecard section."""
lines: List[str] = [
f"## Executive Posture Scorecard: `{report['project_id']}`",
"",
"| Metric | Status | Details |",
"| :--- | :--- | :--- |",
(
f"| **Overall Health Posture** | **{report['status_badge']}** |"
f" {report['posture_grade']} |"
),
(
f"| **Instances Audited** | `{report['total_instances']}` | Total"
" Filestore instances evaluated |"
),
]
m = report["metrics"]
lines.append(
f"| **Backup Protection Rate** | **{m['backup_coverage_pct']}%** |"
f" `{report['total_instances'] - m['unprotected_instances']}/{report['total_instances']}`"
" instances have active backups |"
)
lines.append(
f"| **Critical & High Security Findings** | `{m['critical_findings']}"
f" Critical, {m['high_findings']} High` | Open exports, root squash, or"
" missing backups |"
)
lines.append(
"| **PZI Isolation Compliance** |"
f" `{m['pzi_compliant_count']}/{report['total_instances']}` | Physical"
" Zone Isolation adherence |"
)
lines.append("")
return lines
def _render_findings_matrix(report: Dict[str, Any]) -> List[str]:
"""Renders the Priority Findings & Remediation Matrix section."""
lines: List[str] = ["## Priority Findings & Remediation Matrix", ""]
all_findings = []
for inst in report["instances"]:
for f in inst["findings"]:
all_findings.append((inst["instance_id"], f))
if not all_findings:
lines.append(
"🎉 **No security, compliance, or backup risks detected! All instances"
" are compliant.**"
)
lines.append("")
return lines
sev_order = {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3}
all_findings.sort(key=lambda x: sev_order.get(x[1]["severity"], 99))
lines.append(
"| Severity | Instance ID | Category | Finding Description |"
" Remediation Plan |"
)
lines.append("| :--- | :--- | :--- | :--- | :--- |")
for inst_id, f in all_findings:
sev_emoji = {
"CRITICAL": "🚨 **CRITICAL**",
"HIGH": "⚠️ **HIGH**",
"MEDIUM": " **MEDIUM**",
"LOW": "🟢 **LOW**",
}.get(f["severity"], f["severity"])
lines.append(
f"| {sev_emoji} | `{inst_id}` | {f['category']} | {f['message']} |"
f" {f['remediation']} |"
)
lines.append("")
return lines
def _render_inventory_table(report: Dict[str, Any]) -> List[str]:
"""Renders the Filestore Instance Inventory & Compliance Status table."""
lines: List[str] = [
"## Filestore Instance Inventory & Compliance Status",
"",
(
"| Instance ID | Location | Tier | Capacity | Reserved CIDR | Write"
" IOPS | Throughput | PZI | PZS | Backups | Latest Backup |"
),
(
"| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |"
" :--- | :--- |"
),
]
for i in report["instances"]:
pzi_str = "✅ Yes" if i["satisfies_pzi"] else "❌ No"
if i["tier"] in ["REGIONAL", "ENTERPRISE"]:
pzs_str = "✅ Yes" if i["satisfies_pzs"] else "❌ No"
else:
pzs_str = "N/A"
b_count_str = (
"🔴 0" if i["backup_count"] == 0 else f"{i['backup_count']}"
)
lines.append(
f"| `{i['instance_id']}` | `{i['location']}` | `{i['tier']}` |"
f" `{i['capacity_gb']} GiB` | `{i['reserved_ip_range']}` |"
f" `{i['max_write_iops']}` | `{i['max_throughput']}` | {pzi_str} |"
f" {pzs_str} | {b_count_str} | {i['latest_backup_date']} |"
)
lines.append("")
return lines
def _render_remediation_actions(report: Dict[str, Any]) -> List[str]:
"""Renders Automated Remediation Actions (Disaster Recovery) section."""
unprotected = [i for i in report["instances"] if i["backup_count"] == 0]
if not unprotected:
return []
lines: List[str] = [
"## Automated Remediation Actions (Disaster Recovery)",
"",
(
"To create baseline backups for unprotected instances, execute the"
" following commands:"
),
"```bash",
]
for i in unprotected:
loc_flag = (
f"--instance-location={i['location']}"
if i["is_regional"]
else f"--instance-zone={i['location']}"
)
lines.append(
f'CLOUDSDK_METRICS_ENVIRONMENT="{METRICS_ENV}" \\\n'
f"gcloud filestore backups create {i['instance_id']}-backup-$(date"
" +%Y%m%d) \\\n"
f" --project={report['project_id']} \\\n"
f" --instance={i['instance_id']} \\\n"
f" --file-share={i['file_share']} \\\n"
f" {loc_flag} \\\n"
f" --region={i['backup_region']}"
)
lines.append("```")
lines.append("")
lines.append(
"> **Confirmation Required**: Would you like me to execute these backup"
" creation commands for the unprotected instances? Please confirm to"
" proceed."
)
lines.append("")
return lines
def render_markdown_report(report: Dict[str, Any]) -> str:
"""Renders the audit report in clean GitHub-flavored markdown."""
lines: List[str] = [
f"# Filestore Comprehensive Audit Report: `{report['project_id']}`",
"",
]
lines.extend(_render_scorecard(report))
lines.extend(_render_findings_matrix(report))
lines.extend(_render_inventory_table(report))
lines.extend(_render_remediation_actions(report))
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(
description="Google Cloud Filestore Comprehensive Audit Engine."
)
parser.add_argument(
"--project", required=True, help="GCP Project ID to audit"
)
parser.add_argument(
"--instance", help="Specific Filestore Instance ID (optional)"
)
parser.add_argument(
"--location", default="-", help="GCP zone or region (default: '-')"
)
parser.add_argument(
"--stale-backup-days",
type=int,
default=DEFAULT_STALE_BACKUP_DAYS,
help=(
"Threshold in days to flag stale backups"
f" (default: {DEFAULT_STALE_BACKUP_DAYS})"
),
)
parser.add_argument(
"--format",
choices=["markdown", "json"],
default="markdown",
help="Output format (markdown or json)",
)
args = parser.parse_args()
auditor = FilestoreAuditor(
project_id=args.project,
instance_id=args.instance,
location=args.location,
stale_backup_days=args.stale_backup_days,
)
try:
report = auditor.run_audit()
except (RuntimeError, ValueError, OSError, json.JSONDecodeError) as e:
err_msg = str(e)
if args.format == "json":
print(json.dumps({"error": err_msg}))
else:
print(f"**Error executing audit:** {err_msg}")
sys.exit(1)
if args.format == "json":
print(json.dumps(report, indent=2))
else:
print(render_markdown_report(report))
if __name__ == "__main__":
main()