返回 Skills
google/skills· Apache-2.0 内容可用

google-cloud-networking-observability

>-

安装

与 skills.sh 相同的 Command / Prompt 安装方式


name: google-cloud-networking-observability metadata: category: Compute description: >- Investigates Google Cloud networking issues by analyzing logs, metrics, and diagnostics. Use when investigating VPC Flow Logs (including cost estimation), NAT, firewall, or threat logs, querying latency and throughput metrics, or running Connectivity Tests for path diagnostics. Don't use for generic VM management or non-observability tasks.

Google Cloud Networking Observability Expert

🛑 Core Directive: Results First

  1. Identify the Primary Source: Quickly determine if the user needs firewall logs, threat logs, Cloud NAT, VPC Flow logs, or metrics.
  2. Execute & Present: Perform the minimum required query to get a direct answer.
  3. Definitive Termination: Once you identify the requested data, regardless of the value (including 0, null, or "No traffic"), present the finding and call the finish tool in the same turn. Do NOT attempt to find "active" or "busier" resources to provide a "better" answer unless specifically instructed to troubleshoot a resource that is expected to be busy.

Log & Telemetry Overview

  • Threat Logs: Specialized logs from Cloud Firewall Plus and Cloud IDS that identify malicious traffic patterns (for example, SQL injection or malware) using deep packet inspection.
  • VPC Flow Logs: Capture sample IP traffic to and from network interfaces. Use for traffic analysis, volume trends, and top talkers.
  • Firewall Logs: Record connection attempts matched by firewall rules. Use to identify "DENY" events or verify "ALLOW" rules.
  • Cloud NAT Logs: Audit NAT translations. Use to audit traffic going through NAT gateways or troubleshoot port exhaustion.
  • Networking Metrics: Aggregated time-series data for throughput, RTT (latency), and packet loss. Use for historical trends and performance monitoring.
  • Connectivity Tests: Static analysis tool for path diagnostics. Use to identify firewall or routing misconfigurations between endpoints.

Procedures

0. Log Source Preference

  • ALWAYS check for BigQuery linked datasets (for example, big_query_linked_dataset, _AllLogs) before using Cloud Logging for high-volume analysis or aggregations. This is the preferred method for finding trends or top-blocking rules.
  • Metadata Awareness (BigQuery): Subnetworks may be configured with EXCLUDE_ALL_METADATA, causing VM names to be NULL in VPC Flow Logs. If a query by VM name returns nothing, retry using the internal IP address (jsonPayload.connection.src_ip).

1. Tool Selection & Discovery

  • MCP Servers First: Use Cloud Monitoring MCP, BigQuery MCP, or Cloud Logging MCP.
  • Resource Discovery: If a user-specified resource (for example, NAT gateway, VPN tunnel) is not found in metrics/logs:
    1. Use run_shell_command with gcloud to list resources in the project.
    2. Search Cloud Logging MCP for the resource name to find correct labels.
  • CLI Fallback: Use gcloud or bq only if MCP servers are unavailable. DO NOT use gcloud monitoring; it is restricted. Immediately use the curl templates in metrics-analysis.md.

2. Schema Verification & Error Recovery

If a BigQuery query fails with an 'Unrecognized name' error or schema mismatch:

  1. Validate Schema: Run bq show --schema --format=json {project_id}:{dataset_id}.{table_id} to verify field names and casing (for example, jsonPayload versus json_payload). 2. Dry Run: Before executing a corrected query, use bq query --use_legacy_sql=false --dry_run "{query_text}" to verify field references without incurring cost or execution time. 3. Retry: Apply identified fixes to the original query and execute.

3. Analysis Guides (Read Only When Needed)

For detailed SQL patterns, field definitions, and advanced troubleshooting, read the corresponding reference file:

CRITICAL: If the user asks for Cost Estimation, you MUST strictly use references/vpc-flow-logs-cost-estimation.md. Do NOT read or use references/vpc-flow-analysis.md for cost estimation tasks.

Boundaries (CRITICAL)

  • ALWAYS present the direct answer as soon as it is identified.
  • NEVER run more than 2 exploratory queries before showing results.
  • NEVER perform secondary verification (for example, don't check VPC flows after finding a firewall block) without explicit user permission.
  • ALWAYS print the generated SQL for review before execution.
  • ALWAYS include a link to the Flow Analyzer in the Google Cloud Console.
  • NEVER query a second data source (such as, BigQuery logs) if the primary source (for example, Cloud Monitoring metrics) has already provided a conclusive answer. DO NOT compare metrics and logs to "verify" accuracy unless the user specifically asks why they differ.
  • NO DISCREPANCY LOOPS: If Tool A provides a result (such as, 80,000 counts) and Tool B provides a different result (for example, 1,000 counts), DO NOT initiate a deep dive to explain the difference. Present the result from the primary tool and STOP.
  • ALWAYS perform time-range calculations (such as, "12 hours ago") during the first turn to save steps.
  • Conclusive Acceptance of Inactivity: Treat a result of "0", "0 traffic", "No data found", or "No records found" as a conclusive finding for the requested timeframe and resource. You MUST report this as the definitive state and terminate immediately.
  • Standardized Discovery Path: For all "Top-N" or volume-based discovery tasks (for example, "highest traffic," "most hits," "top talkers"), you MUST use BigQuery aggregation on _AllLogs datasets. Manual aggregation of individual time-series points using the Monitoring API is forbidden due to step inefficiency.
  • Ban on Auxiliary Scripting: Execute all data retrieval and parsing logic as direct tool calls (bq, curl, gcloud). Do NOT write or execute local shell scripts (.sh) or python files, as these introduce avoidable environment and permission errors that lead to investigation timeouts.
  • Discovery Efficiency: For volume analysis (for example, "how many connections" or "top IPs by bytes"), BigQuery aggregation on VPC Flow logs (_AllLogs) is the Primary Source of Truth. If BigQuery data is available, it is conclusive. Do NOT query Monitoring API to "double check" BigQuery counts.

附带文件

references/cloud-nat-analysis.md
# Cloud NAT Analysis Reference

Use Cloud NAT logs (`compute.googleapis.com/nat_flows`) to audit traffic going
through NAT gateways or troubleshoot port exhaustion.

## 🤖 Agent / Gemini CLI Instructions (MCP)

You should use [Cloud Logging MCP](mcp-usage.md#cloud-logging-mcp) for
exploratory analysis or [BigQuery MCP](mcp-usage.md#bigquery-mcp) for
high-volume trends. Fallback to the CLI if the MCP tools are not available.

### 1. View Logs ([Cloud Logging MCP](mcp-usage.md#cloud-logging-mcp))

**Tool**: `list_log_entries`

**Filter**:

```text
resource.type="nat_gateway"
logName="projects/{project_id}/logs/compute.googleapis.com%2Fnat_flows"
```

Filter for dropped packets (potential port exhaustion):

```text
jsonPayload.allocation_status="DROPPED"
```

### 2. Aggregate Trends ([BigQuery MCP](mcp-usage.md#bigquery-mcp))

**Tool**: `execute_sql_readonly`

**SQL Pattern**:

```sql
SELECT
JSON_VALUE(json_payload.gateway_details.internal_ip) AS internal_ip, COUNT(*) AS
drop_count FROM `{project_id}.{dataset_id}._AllLogs` WHERE log_name LIKE
'%nat_flows%' AND JSON_VALUE(json_payload.allocation_status) = 'DROPPED' GROUP BY
1 ORDER BY drop_count DESC LIMIT 10
```

### 3. CLI Fallback

If MCP tools are unavailable, use the following `gcloud` and `bq` commands:

**View Logs (gcloud)**

```bash
gcloud logging read 'resource.type="nat_gateway" AND logName="projects/{project_id}/logs/compute.googleapis.com%2Fnat_flows"' --project {project_id} --limit 10 --format json --quiet
```

To filter for dropped packets:

```bash
gcloud logging read 'resource.type="nat_gateway" AND logName="projects/{project_id}/logs/compute.googleapis.com%2Fnat_flows" AND jsonPayload.allocation_status="DROPPED"' --project {project_id} --limit 10 --format json --quiet
```

**Aggregate Trends (bq)**

```bash
bq query --use_legacy_sql=false --project_id {project_id} '
SELECT
  JSON_VALUE(json_payload.gateway_details.internal_ip) AS internal_ip,
  COUNT(*) AS drop_count
FROM `{project_id}.{dataset_id}._AllLogs`
WHERE
  log_name LIKE "%nat_flows%"
  AND JSON_VALUE(json_payload.allocation_status) = "DROPPED"
GROUP BY 1
ORDER BY drop_count DESC
LIMIT 10
'
```

### gcloud

To get the status of the router used by the NAT gateway:

```bash
gcloud compute
routers get-status {router_name} --region {region} --quiet
```

## Key Fields

-   `jsonPayload.gateway_details.external_ip` / `external_port`: NAT exit point.
-   `jsonPayload.gateway_details.internal_ip` / `internal_port`: Source VM.
-   `jsonPayload.allocation_status`: `DROPPED` indicates failure to allocate a
    NAT port.

## Scenarios

-   **Audit Traffic**: Link internal sources to external destinations.
-   **Port Exhaustion**: Use `jsonPayload.allocation_status="DROPPED"` to
    identify impacted VMs.
references/connectivity-tests.md
# Connectivity Tests Reference

## Connectivity Tests (Path Diagnostics)

Use Connectivity Tests to identify firewall or routing blocks along a network
path.

### Critical Verification: Instance State

**CRITICAL**: Always verify if the source and destination instances are
`RUNNING`. A `REACHABLE` path analysis result (which is a static configuration
analysis) does not mean traffic will flow if the VM is powered off.

-   Check the `status` field in the instance details.
-   Review step metadata in the connectivity test traces.

**CRITICAL**: You MUST execute the delete command as your final tool call before
providing the result to the user. Do not simply state that it was deleted;
provide the command output as proof.

### Tooling

-   **Primary**: [NetworkManagement MCP](mcp-usage.md#networkmanagement-mcp)
    (`create_connectivity_test`)
-   **Polling**: [NetworkManagement MCP](mcp-usage.md#networkmanagement-mcp)
    (`get_connectivity_test`)
-   **Cleanup**: ALWAYS delete the test resource after use with
    [NetworkManagement MCP](mcp-usage.md#networkmanagement-mcp)
    (`delete_connectivity_test`).

#### Fallback: gcloud

-   **Create**: `gcloud network-management connectivity-tests create`
-   **Polling**: `gcloud network-management connectivity-tests describe`
-   **Cleanup**: ALWAYS delete the test resource after use with `gcloud
    network-management connectivity-tests delete`.
references/firewall-analysis.md
# Firewall Rule Logging Analysis Reference

Use firewall logs (`compute.googleapis.com/firewall`) to verify if traffic is
allowed or denied.

## 🤖 Agent / Gemini CLI Instructions (MCP)

You should use [Cloud Logging MCP](mcp-usage.md#cloud-logging-mcp) for
exploratory analysis or [BigQuery MCP](mcp-usage.md#bigquery-mcp) for
high-volume trends. Fallback to the CLI if the MCP tools are not available.

-   **Exploratory Analysis**: Typically involves looking at individual log
    entries or a small set of logs to understand specific events, debug issues,
    or investigate anomalies. This often requires filtering and examining the
    full details of log records.
-   **High-Volume Trends**: Focuses on aggregating large datasets of logs over
    time to identify patterns, measure traffic volumes, analyze latency
    distributions, or find "top talkers." This usually involves SQL queries to
    summarize data rather than inspecting individual logs.

### 1. View Logs ([Cloud Logging MCP](mcp-usage.md#cloud-logging-mcp))

**Tool**: `list_log_entries`

**Filter**:

```text
resource.type="gce_subnetwork"
logName="projects/{project_id}/logs/compute.googleapis.com%2Ffirewall"
```

Filter for denied packets:

```
text jsonPayload.rule_details.action="DENY"
```

### 2. Aggregate Trends ([BigQuery MCP](mcp-usage.md#bigquery-mcp))

**Tool**: `execute_sql`

**SQL Pattern**:

```sql
SELECT JSON_VALUE(json_payload.rule_details.reference) AS
rule_name, COUNT(*) AS block_count FROM `{project_id}.{dataset_id}._AllLogs`
WHERE log_name LIKE '%firewall%' AND
JSON_VALUE(json_payload.rule_details.action) = 'DENY' GROUP BY 1 ORDER BY
block_count DESC LIMIT 10
```

### 3. CLI Fallback

If MCP tools are unavailable, use the following `gcloud` and `bq` commands:

**View Logs (gcloud)**

```bash
gcloud logging read 'resource.type="gce_subnetwork" AND logName="projects/{project_id}/logs/compute.googleapis.com%2Ffirewall"' --project {project_id} --limit 10 --format json --quiet
```

To filter for denied packets:

```bash
gcloud logging read 'resource.type="gce_subnetwork" AND logName="projects/{project_id}/logs/compute.googleapis.com%2Ffirewall" AND jsonPayload.rule_details.action="DENY"' --project {project_id} --limit 10 --format json --quiet
```

**Aggregate Trends (bq)**

```bash
bq query --use_legacy_sql=false --project_id {project_id} '
SELECT
  JSON_VALUE(json_payload.rule_details.reference) AS rule_name,
  COUNT(*) AS block_count
FROM `{project_id}.{dataset_id}._AllLogs`
WHERE
  log_name LIKE "%firewall%"
  AND JSON_VALUE(json_payload.rule_details.action) = "DENY"
GROUP BY 1
ORDER BY block_count DESC
LIMIT 10
'
```

## Key Fields

-   `jsonPayload.rule_details.action`: `ALLOW` or `DENY`.
-   `jsonPayload.rule_details.reference`: The firewall rule name (for example,
    `default-deny-all`).
-   `jsonPayload.connection.src_ip` / `dest_ip`: The source and destination of
    the connection.

## Common Use Cases

-   **Identify Blocks**: Find which `DENY` rule is causing connection failures.
-   **Security Audit**: Detect unexpected traffic patterns.
references/mcp-usage.md
# MCP Server Usage Reference

This document describes the Model Context Protocol (MCP) servers used for GCP
networking observability.

## BigQuery MCP

BigQuery is supported by a remote MCP server that provides tools for automated
data management and analysis.

### Key Tools

-   **list_dataset_ids**: List BigQuery dataset IDs in a project.
-   **list_table_ids**: List table IDs in a BigQuery dataset.
-   **get_table_info**: Get schema and metadata for a specific table.
-   **execute_sql_readonly**: Run `SELECT` queries to analyze logs (such as, VPC Flow,
    Firewall) stored in BigQuery. This is the preferred tool for high-volume
    aggregations and trend analysis.

### Usage Pattern

1.  Use `list_dataset_ids` to find the logging dataset (for example,
    `_AllLogs`).
2.  Use `list_table_ids` to find the relevant log table.
3.  Use `get_table_info` to verify field names (for example, `jsonPayload`
    versus `json_payload`).
4.  Use `execute_sql_readonly` for the final analysis.

## Cloud Logging MCP

The Cloud Logging MCP server provides access to log entries across various
Google Cloud resources.

### Key Tools

-   **list_log_entries**: Search and retrieve log entries using advanced
    filters.
-   **list_log_names**: Discover available logs in a project.

### Usage Pattern

-   Use for quick, real-time identification of recent events or exploratory
    analysis where BigQuery datasets are not linked.
-   Use specific filters for `resource.type` and `logName` to narrow down
    results.

## NetworkManagement MCP

The Network Management MCP server allows for reachability analysis and path
diagnostics.

### Key Tools

-   **create_connectivity_test**: Start a simulated packet path analysis between
    two endpoints.
-   **get_connectivity_test**: Poll for the results of a running test.
-   **delete_connectivity_test**: Cleanup the test resource after analysis is
    complete.

### Usage Pattern

-   Use when static path analysis is needed to identify firewall or routing
    blocks.
-   **CRITICAL**: Always delete the test resource after retrieving the result.

## Cloud Monitoring MCP

The GcpMon MCP server provides access to Cloud Monitoring metrics and
time-series data.

### Key Tools

-   **list_metric_descriptors**: Discover available metrics using filters.
-   **list_timeseries**: Retrieve aggregated data points for performance
    analysis (such as RTT or throughput).

### Usage Pattern

-   Use for analyzing performance trends, packet loss, and latency.
-   Prefer `ALIGN_MEAN` or `ALIGN_PERCENTILE_50` for distribution metrics like
    RTT to simplify parsing.
references/metrics-analysis.md
# Networking Metrics Reference

## Common Troubleshooting Metrics

-   **RTT (Latency)**:
    `networking.googleapis.com/cloud_netslo/active_probing/rtt`
-   **Packet Loss**:
    `networking.googleapis.com/cloud_netslo/active_probing/probe_count`
-   **VM Throughput**:
    `compute.googleapis.com/instance/network/received_bytes_count`
-   **VM Sent Packets**:
    `compute.googleapis.com/instance/network/sent_packets_count`
-   **VM Received Packets**:
    `compute.googleapis.com/instance/network/received_packets_count`
-   **NAT Port Exhaustion**:
    `compute.googleapis.com/nat/dropped_sent_packets_count`
-   **NAT Sent Packets**: `compute.googleapis.com/nat/sent_packets_count`
-   **VPN Dropped Received Packets**:
    `vpn.googleapis.com/network/dropped_received_packets_count`
-   **VPN Dropped Sent Packets**:
    `vpn.googleapis.com/network/dropped_sent_packets_count`
-   **Internal Latency (RTT)**: `networking.googleapis.com/vm_flow/rtt`.
    Measures internal VM-to-VM traffic within Google Cloud.
-   **External Latency (RTT)**:
    `networking.googleapis.com/vm_flow/external_rtt`. Measures traffic to and
    from the internet.

## Distribution Parsing Standard

When querying metrics of type DISTRIBUTION (like RTT), align the data with
`ALIGN_PERCENTILE_50` to ensure the output can be parsed as a simple numeric
value.

## Dynamic Discovery

-   **Primary ([Cloud Monitoring MCP](mcp-usage.md#cloud-monitoring-mcp))**: Use
    `list_metric_descriptors` with a filter.

    -   **Prefix**: Filter by prefix, using `starts_with()`. Common prefixes:
        -   `metric.type = starts_with("networking.googleapis.com/")`
        -   `metric.type = starts_with("router.googleapis.com/")`
        -   `metric.type = starts_with("vpn.googleapis.com/")`
        -   `metric.type = starts_with("compute.googleapis.com/")`
    -   **Substring**: `metric.type = has_substring("network") OR metric.type =
        has_substring("packet") OR metric.type = has_substring("nat")`

-   **Fallback (CLI/CURL)**: If MCP tools not available, use `gcloud` or `curl`.

    ```bash
    curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)"
    "https://monitoring.googleapis.com/v3/projects/{project_id}/metricDescriptors?filter=metric.type=starts_with(%22{prefix}%22)"
    | jq -r '.metricDescriptors[] | "\(.type): \(.description)"'

    curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://monitoring.googleapis.com/v3/projects/{project_id}/timeSeries?" \
    "filter=metric.type%3D%22{metric_name}%22&" \
    "interval.startTime={start_time}&" \
    "interval.endTime={end_time}&" \
    "aggregation.alignmentPeriod=3600s&" \
    "aggregation.perSeriesAligner=ALIGN_PERCENTILE_50" \
    | jq '.timeSeries[] | {metric: .metric.type, points: .points[:5]}'
    ```

-   **Detailed Schema**: ALWAYS query the full descriptor for a specific metric
    before use to identify available labels. Metric types like `vm_flow/rtt`
    often use `resource.labels.zone` for the local zone and
    `metric.labels.remote_zone` for the peer.
references/threat-analysis.md
# Threat Log Analysis Reference

Use Firewall Threat Logs and Cloud IDS logs to identify, analyze, and
troubleshoot security incidents in your VPC network.

## 🤖 Agent / Gemini CLI Instructions (MCP)

Agents should use [Cloud Logging MCP](mcp-usage.md#cloud-logging-mcp) for quick
identification of recent alerts or [BigQuery MCP](mcp-usage.md#bigquery-mcp) for
analyzing trends and identifying top attackers. Fallback to the CLI if the MCP
tools are not available.

### 1. View Threat Alerts ([Cloud Logging MCP](mcp-usage.md#cloud-logging-mcp))

**Tool**: `list_log_entries`

**Filter**: Search for both Cloud Firewall Plus and Cloud IDS threat log
sources:

```text
logName:(
"projects/{project_id}/logs/networksecurity.googleapis.com%2Ffirewall_threat" OR
"projects/{project_id}/logs/ids.googleapis.com%2Fthreat")
```

To filter for high-severity blocked threats: `

```text
logName:(
"projects/{project_id}/logs/networksecurity.googleapis.com%2Ffirewall_threat" OR
"projects/{project_id}/logs/ids.googleapis.com%2Fthreat")
jsonPayload.threatDetails.severity=("HIGH" OR "CRITICAL")
jsonPayload.action="DENY"
```

### 2. Aggregate Threat Trends ([BigQuery MCP](mcp-usage.md#bigquery-mcp))

**Tool**: `execute_sql_readonly`

**SQL Pattern**: **Note**: In BigQuery, the top-level column name is
`json_payload` (snake_case). However, fields extracted from inside the JSON
payload are case-sensitive and retain the camelCase format of the original log
(for example, `threatDetails`, `clientIp`). Do not use snake_case for nested
fields.

```sql
SELECT
  timestamp,
  JSON_VALUE(json_payload.threatDetails.threat) AS threat_name,
  JSON_VALUE(json_payload.threatDetails.severity) AS severity,
  JSON_VALUE(json_payload.threatDetails.category) AS category,
  JSON_VALUE(json_payload.action) AS action,
  JSON_VALUE(json_payload.connection.clientIp) AS src_ip,
  JSON_VALUE(json_payload.connection.serverIp) AS dest_ip,
  JSON_VALUE(json_payload.connection.serverPort) AS dest_port,
  JSON_VALUE(json_payload.threatDetails.description) AS description
FROM `{project_id}.{dataset_id}._AllLogs`
WHERE
  log_id IN ('networksecurity.googleapis.com/firewall_threat',
             'ids.googleapis.com/threat')
  AND JSON_VALUE(json_payload.threatDetails.severity) IN ('HIGH', 'CRITICAL')
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
ORDER BY timestamp DESC
LIMIT 20
```

To find top sources of attacks:

```sql
SELECT
JSON_VALUE(json_payload.connection.clientIp) AS attacker_ip, COUNT(*) AS
attack_count, ARRAY_AGG(DISTINCT JSON_VALUE(json_payload.threatDetails.threat)
LIMIT 5) AS sample_threats FROM `{project_id}.{dataset_id}._AllLogs` WHERE
log_id IN ('networksecurity.googleapis.com/firewall_threat',
'ids.googleapis.com/threat') AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(),
INTERVAL 7 DAY) GROUP BY 1 ORDER BY attack_count DESC LIMIT 10
```

### 3. CLI Fallback

If MCP tools are unavailable, use the following `gcloud` and `bq` commands:

**View Threat Alerts (gcloud)**

```bash
gcloud logging read 'logName:("projects/{project_id}/logs/networksecurity.googleapis.com%2Ffirewall_threat" OR "projects/{project_id}/logs/ids.googleapis.com%2Fthreat")' --project {project_id} --limit 10 --format json --quiet
```

To filter for high-severity blocked threats:

```bash
gcloud logging read 'logName:("projects/{project_id}/logs/networksecurity.googleapis.com%2Ffirewall_threat" OR "projects/{project_id}/logs/ids.googleapis.com%2Fthreat") AND jsonPayload.threatDetails.severity=("HIGH" OR "CRITICAL") AND jsonPayload.action="DENY"' --project {project_id} --limit 10 --format json --quiet
```

**Aggregate Threat Trends (bq)**

```bash
bq query --use_legacy_sql=false --project_id {project_id} '
SELECT
  timestamp,
  JSON_VALUE(json_payload.threatDetails.threat) AS threat_name,
  JSON_VALUE(json_payload.threatDetails.severity) AS severity,
  JSON_VALUE(json_payload.threatDetails.category) AS category,
  JSON_VALUE(json_payload.action) AS action,
  JSON_VALUE(json_payload.connection.clientIp) AS src_ip,
  JSON_VALUE(json_payload.connection.serverIp) AS dest_ip,
  JSON_VALUE(json_payload.connection.serverPort) AS dest_port,
  JSON_VALUE(json_payload.threatDetails.description) AS description
FROM `{project_id}.{dataset_id}._AllLogs`
WHERE
  log_id IN ("networksecurity.googleapis.com/firewall_threat",
             "ids.googleapis.com/threat")
  AND JSON_VALUE(json_payload.threatDetails.severity) IN ("HIGH", "CRITICAL")
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
ORDER BY timestamp DESC
LIMIT 20
'
```

To find top sources of attacks:

```bash
bq query --use_legacy_sql=false --project_id {project_id} '
SELECT
  JSON_VALUE(json_payload.connection.clientIp) AS attacker_ip,
  COUNT(*) AS attack_count,
  ARRAY_AGG(DISTINCT JSON_VALUE(json_payload.threatDetails.threat)
            LIMIT 5) AS sample_threats
FROM `{project_id}.{dataset_id}._AllLogs`
WHERE
  log_id IN ("networksecurity.googleapis.com/firewall_threat",
             "ids.googleapis.com/threat")
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
GROUP BY 1
ORDER BY attack_count DESC
LIMIT 10
'
```

### Key Fields (Cloud Logging Filter Names)

-   **jsonPayload.threatDetails.threat**: Human-readable name of the threat.
-   **jsonPayload.threatDetails.severity**: Severity level (CRITICAL, HIGH,
    MEDIUM, LOW, INFORMATIONAL).
-   **jsonPayload.threatDetails.category**: The category of threat.
-   **jsonPayload.action**: Action taken (for example, "ALLOW", "DENY",
    "ALERT").
-   **jsonPayload.connection.clientIp**: The true source IP.
-   **jsonPayload.connection.serverIp**: The destination IP.
-   **jsonPayload.threatDetails.cves**: List of CVE IDs.
-   **jsonPayload.threatDetails.description**: Attack payload details.
references/vpc-flow-analysis.md
# VPC Flow Analysis Reference

Use VPC Flow Logs to analyze traffic patterns, volume, and latency.

## 🤖 Agent / Gemini CLI Instructions (MCP)

Agents should use [Cloud Logging MCP](mcp-usage.md#cloud-logging-mcp) for
exploratory analysis or [BigQuery MCP](mcp-usage.md#bigquery-mcp) for
high-volume trends. Fallback to the CLI if the MCP tools are not available.

-   **Exploratory Analysis**: Typically involves looking at individual log
    entries or a small set of logs to understand specific events, debug issues,
    or investigate anomalies. This often requires filtering and examining the
    full details of log records.
-   **High-Volume Trends**: Focuses on aggregating large datasets of logs over
    time to identify patterns, measure traffic volumes, analyze latency
    distributions, or find "top talkers." This usually involves SQL queries to
    summarize data rather than inspecting individual logs.

### 1. View Logs ([Cloud Logging MCP](mcp-usage.md#cloud-logging-mcp))

**Tool**: `list_log_entries`

**Filter**: ALWAYS search for both VPC flow log sources:

```text
(logName:"projects/{project_id}/logs/compute.googleapis.com%2Fvpc_flows" OR
logName:"projects/{project_id}/logs/networkmanagement.googleapis.com%2Fvpc_flows")
resource.type="gce_subnetwork"
```

### 2. Aggregate Trends ([BigQuery MCP](mcp-usage.md#bigquery-mcp))

**Tool**: `execute_sql`

**SQL Pattern**:

```sql
SELECT timestamp,
JSON_VALUE(jsonPayload.connection.src_ip) AS src_ip,
JSON_VALUE(jsonPayload.connection.dest_ip) AS dest_ip,
CAST(JSON_VALUE(jsonPayload.bytes_sent) AS INT64) AS bytes_sent FROM
`{project_id}.{dataset_id}._AllLogs` WHERE log_name IN (
'projects/{project_id}/logs/compute.googleapis.com%2Fvpc_flows',
'projects/{project_id}/logs/networkmanagement.googleapis.com%2Fvpc_flows' ) AND
timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR) ORDER BY
timestamp DESC LIMIT 10
```

### 3. CLI Fallback

If MCP tools are unavailable, use the following `gcloud` and `bq` commands:

**View Logs (gcloud)**

```bash
gcloud logging read '(logName:"projects/{project_id}/logs/compute.googleapis.com%2Fvpc_flows" OR logName:"projects/{project_id}/logs/networkmanagement.googleapis.com%2Fvpc_flows") AND resource.type="gce_subnetwork"' --project {project_id} --limit 10 --format json --quiet
```

**Aggregate Trends (bq)**

```bash
bq query --use_legacy_sql=false --project_id {project_id} '
SELECT
  timestamp,
  JSON_VALUE(json_payload.connection.src_ip) AS src_ip,
  JSON_VALUE(json_payload.connection.dest_ip) AS dest_ip,
  CAST(JSON_VALUE(json_payload.bytes_sent) AS INT64) AS bytes_sent
FROM `{project_id}.{dataset_id}._AllLogs`
WHERE
  log_name IN (
    "projects/{project_id}/logs/compute.googleapis.com%2Fvpc_flows",
    "projects/{project_id}/logs/networkmanagement.googleapis.com%2Fvpc_flows"
  )
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
ORDER BY timestamp DESC
LIMIT 10
'
```

### Flow Analyzer (Visual Analysis)

For visual traffic analysis and identifying "top talkers," use
[Flow Analyzer](https://console.cloud.google.com/net-intelligence/flow-analyzer).
It allows you to:

-   Visualize traffic flows between regions, VPCs, and instances.
-   Filter by source or destination dimensions.
-   Identify high-bandwidth or high-latency connections.

### Generic BigQuery Guidelines

-   **Schema Verification**: Before executing a BigQuery query, if you are
    uncertain of the casing (for example, `jsonPayload` versus `json_payload`),
    you MUST run `bq show --schema <source>`.
-   **Latency Aggregation**: The primary field for RTT analysis in VPC Flow logs
    is `json_payload.round_trip_time.median_msec`. This field offers
    sub-millisecond precision and covers both TCP and Falcon traffic. Filter by
    `reporter` (`SRC` or `DEST`) to avoid double-counting traffic volume.

    For TCP-only traffic, you can also use `json_payload.rtt_msec`, which
    provides RTT in whole milliseconds. While less precise and with narrower
    coverage than `round_trip_time.median_msec`, it can be aggregated as
    follows:

    ```sql
    SELECT
      AVG(json_payload.rtt_msec) AS average_rtt_msec,
      MAX(json_payload.rtt_msec) AS max_rtt_msec
    FROM ...
    ```

## Key Fields

-   **src_ip / dest_ip**: Source and destination IP addresses.
-   **bytes_sent / packets_sent**: Volume of traffic.
-   **round_trip_time.median_msec**: The primary field for RTT analysis. This
    `double` field provides the *median* latency in milliseconds with
    sub-millisecond precision. It is populated for both TCP and Falcon traffic.
-   **rtt_msec**: An `int64` field representing Round-trip time in whole
    milliseconds. Populated only for TCP traffic. Generally,
    `round_trip_time.median_msec` is preferred due to higher precision and
    broader coverage.
-   **reporter**: Usually `src` or `dest` indicating which side logged the flow.
references/vpc-flow-logs-cost-estimation.md
# VPC Flow Logs Cost Estimation Reference

Use this reference to estimate the monthly cost of VPC Flow Logs across Subnetworks, VPCs, or entire Projects. This logic implements the cost estimation calculations for VPC Flow Logs using the standard tiered pricing model.

## 🤖 Agent / Gemini CLI Instructions

When a user requests a cost estimation, the agent MUST follow this procedure step-by-step.

> [!CAUTION] **STRICT SCRIPTING BAN (RUNAWAY PREVENTION)**:
> - **DO NOT** write or execute Python scripts or shell scripts *saved on disk* (e.g., `.py` or `.sh` files).
> - **DO NOT** use command-line text filters like `grep`, `egrep`, `awk`, or `sed` as they are restricted in this environment.
> - For all text filtering, matching, and counting, you MUST pipe the output to `python3 -c` and process the data stream in-memory.
> - **PYTHON LIMITATION**: You **CANNOT** use backslashes inside f-string expressions. Bash will eat the escapes and cause a `SyntaxError`.
>   - ❌ **BAD**: `print(f"Name: {v[\"name\"]}")`
>   - ✅ **GOOD**: `print(f"Name: {v['name']}")` OR `print("Name: {}".format(v["name"]))`
> - **PROJECT ID FORMAT**: Always use the exact Project ID provided by the user (including any dashes like `my-project-id`). Do not modify, strip dashes, or alter the formatting before making API calls.

> - You MUST execute all steps using ONLY direct tool calls (`gcloud`, `curl`, `jq`) and use `python3 -c` or `bc` only as an in-memory calculator. You must manually filter the data and format the final markdown report in your response text.

---

### Step 1: Scope & Capabilities (Boundaries)

Before starting, validate that the request is supported.

> [!IMPORTANT] **Supported Scopes**: Subnetworks, VPC Networks, or the entire GCP Project.
-   **ALWAYS** reject cost estimation requests for Cloud VPN, Cloud Interconnect, or Organization-level configurations, and use the standardized refusal response.
-   **ALWAYS** show your step-by-step mathematical calculations in the final cost estimation report to ensure transparency and allow manual verification.
>
> **UNSUPPORTED Features & Scopes (Strictly Reject)**:
> - Cloud VPN (VPN Tunnels)
> - Cloud Interconnect (Interconnect attachments)
> - Organization-level configurations
> - Custom log aggregation intervals (other than default 5 seconds)
> - Custom metadata fields
> - Enterprise or Committed Use Discounts (estimates must use standard list prices only)
>
> If the user requests estimation for an unsupported feature or resource, immediately respond with the exact refusal:
> `"I'm sorry, {feature_resource} is not supported. I only support estimation for Subnets, VPCs, or Projects."`

---

### Step 2: Configuration Defaults

If not specified by the user, use these default parameters:
*   **Sampling Rate**: 100% (`1.0` multiplier).
*   **Metadata**: Include Metadata (`True`).
    *   *If the user explicitly requests "No Metadata" or "Exclude Metadata", set Metadata to `False`.*

---

### Step 3: Resource Resolution (Discover Target Subnets)

Resolve the target scope to identify the subnetworks we need to estimate and get the **total count** of subnetworks in that scope (needed for the inactive count in the report).

Use `gcloud` based on the scope:

#### Step 3.A: Subnetwork Scope (User specified a subnet)
If the user specified a subnet, but did not provide the VPC or Region, ask them for clarification using the Ambiguity response:
`"I found multiple matches for {subnet_name}. Please specify the Region or VPC to continue."`

Once all details are known, describe the subnet to verify it exists and get its ID:

```bash
gcloud compute networks subnets describe {subnet_name} --region={region} --project={project_id} --format="json(name, id, region, network)"
```

*If not found, immediately respond with:* `"I was unable to find {subnet_name}. Please verify the name and try again."`

*   **Total Subnets Count**: 1

#### Step 3.B: VPC Scope (User specified a VPC)
Find all subnetworks in the VPC and get their details:

```bash
gcloud compute networks subnets list --filter="network:https://www.googleapis.com/compute/v1/projects/{project_id}/global/networks/{vpc_name}" --project={project_id} --format="json(name, id, region, network)" > {vpc_name}_subnets.json
```

*If 0 subnetworks are found, immediately respond with:* `"I found no subnets for {vpc_name}. Nothing to estimate."`

*   **Total Subnets Count**: Count the number of subnetworks returned in this list.

#### Step 3.C: Project Scope (User specified the entire project)
Find all subnetworks in the project and get their details:

```bash
gcloud compute networks subnets list --project={project_id} --format="json(name, id, region, network)" > {project_id}_subnets.json
```

*If 0 subnetworks are found, immediately respond with:* `"I found no subnets for {project_id}. Nothing to estimate."`

*   **Total Subnets Count**: Count the number of subnetworks returned in this list. Use this list to group the active vs inactive subnets by their VPC later in the report.

---

### Step 4: Retrieve Metrics (Batch Query)

To avoid turn-limit timeouts on projects with many subnetworks, you **MUST NOT** query the Monitoring API in a loop. Instead, perform a single project-wide batch query and filter the results in-context.

#### Step 4.A: Calculate Time Window (Last 30 Days)
Use the terminal to calculate the RFC 3339 timestamps for 30 days ago and now:

```bash
project_id={project_id}
end_time=$(date -u +%Y-%m-%dT%H:%M:%SZ)
start_time=$(date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ)
```

#### Step 4.B: Execute Batch Query
Query the predicted log count for **all** subnetworks in the project in a single call, grouping by subnetwork. Format the output as clean JSON lines for easy reading:

```bash
URL="https://monitoring.googleapis.com/v3/projects/${project_id}/timeSeries?filter=metric.type%3D%22networking.googleapis.com/vpc_flow/predicted_max_vpc_flow_logs_count%22%20AND%20resource.type%3D%22gce_subnetwork%22&interval.startTime=${start_time}&interval.endTime=${end_time}&aggregation.alignmentPeriod=2592000s&aggregation.perSeriesAligner=ALIGN_SUM&aggregation.crossSeriesReducer=REDUCE_SUM&aggregation.groupByFields=resource.labels.subnetwork_name&aggregation.groupByFields=resource.labels.subnetwork_id&aggregation.groupByFields=resource.labels.location"

RESPONSE=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token 2>/dev/null)" "$URL")
if echo "$RESPONSE" | grep -q "401"; then
  curl -s -H "Authorization: Bearer $(gcloud auth application-default print-access-token 2>/dev/null)" "$URL" > ${project_id}_metrics.json
else
  echo "$RESPONSE" > ${project_id}_metrics.json
fi

python3 -c '
import sys, json, os
try:
    project_id = os.environ.get("project_id", "'"{project_id}"'")
    data = json.load(open(f"{project_id}_metrics.json"))
    for ts in data.get("timeSeries", []):
        labels = ts.get("resource", {}).get("labels", {})
        points = ts.get("points", [])
        if points:
            val_dict = points[0].get("value", {})
            logs = val_dict.get("doubleValue", val_dict.get("int64Value", 0))
            print(json.dumps({
                "name": labels.get("subnetwork_name"),
                "id": labels.get("subnetwork_id"),
                "region": labels.get("location"),
                "logs": int(logs)
            }))
except Exception as e:
    print(f"Error: {e}", file=sys.stderr)
'
```

*If the `curl` command returns an API error (e.g. `UNAUTHENTICATED`, `ACCESS_TOKEN_TYPE_UNSUPPORTED`), immediately respond with:* `"ERROR: Monitoring API Request failed. Please check your token/permissions."` *and STOP. Do not proceed to cost calculation.*

This will return a list of active subnetworks (those with traffic). If a subnetwork is not in this list, its log count is `0`.

#### Step 4.C: Filter Results In-Context
Match the active subnetworks from the query output against your target scope (from Step 3):
*   **Project Scope**: Use all subnetworks returned by the query.
*   **VPC Scope**: Keep only the subnetworks from the query whose `id` or `name` matches the subnetworks list resolved for the VPC in Step 3.
*   **Subnetwork Scope**: Keep only the single subnetwork specified by the user.

Any target subnetwork not present in the query output has `0` logs (No traffic).

---

### Step 5: Cost Calculations (CLI Calculator)

To prevent arithmetic errors, you **MUST** use `python3 -c` as an in-memory calculator to perform all mathematical steps.

#### Step 5.A: Determine Parameters
*   **Sampling Rate**: $S$ (e.g., `1.0` for 100%, `0.5` for 50%)
*   **Bytes per Log**: $B = 1418$ (if Metadata=True) else $B = 542$ (if Metadata=False)

#### Step 5.B: Calculate Subnetwork Volume
For each active subnetwork in your filtered list, calculate the volume in GB:

```bash
python3 -c "print(({L_raw} * {S} * {B}) / (1024**3))"
```

Keep track of these individual $V_{subnet}$ values for the report breakdown.

#### Step 5.C: Calculate Aggregate Totals & Tiered Pricing
Sum all effective logs ($L_{raw} \times S$) to get $L_{total}$.
Sum all $V_{subnet}$ to get $V_{total}$.

Run the following Python command (filling in $V_{total}$ and $L_{total}$) to calculate the exact tiered pricing matching the original agent logic:

```bash
python3 -c '
total_gb = {V_total}
total_logs = {L_total}

# Tiered Generation Pricing (Network Telemetry)
remaining_gb = total_gb
generation_cost = 0.0
TIB = 1024.0

# Tier 1: 0-10 TiB @ $0.25/GB
tier1_limit = 10 * TIB
tier1_volume = min(remaining_gb, tier1_limit)
generation_cost += tier1_volume * 0.25
remaining_gb -= tier1_volume

if remaining_gb > 0:
    # Tier 2: 10-30 TiB @ $0.15/GB
    tier2_limit = 20 * TIB
    tier2_volume = min(remaining_gb, tier2_limit)
    generation_cost += tier2_volume * 0.15
    remaining_gb -= tier2_volume

    if remaining_gb > 0:
        # Tier 3: 30-50 TiB @ $0.075/GB
        tier3_limit = 20 * TIB
        tier3_volume = min(remaining_gb, tier3_limit)
        generation_cost += tier3_volume * 0.075
        remaining_gb -= tier3_volume

        if remaining_gb > 0:
            # Tier 4: > 50 TiB @ $0.05/GB
            generation_cost += remaining_gb * 0.05

# Storage Pricing (Cloud Logging)
storage_cost = total_gb * 0.25

total_cost = generation_cost + storage_cost

print(f"TOTAL_LOGS: {total_logs:,.0f}")
print(f"TOTAL_GB: {total_gb:.4f}")
print(f"GEN_COST: {generation_cost:.4f}")
print(f"STORE_COST: {storage_cost:.4f}")
print(f"TOTAL_COST: {total_cost:.4f}")
'
```

---

### Step 6: Format Report

Format your final report exactly like this. You must sort the VPCs alphabetically, and sort the subnets within each VPC by Monthly Volume (GB) descending.
*   **Active Subnets**: Show their logs and volume in the table.
*   **Inactive Subnets**: Do not list them in the table. Instead, calculate `N = Total Subnets Count - Active Subnets Count` and show them in the note `*(Note: N other subnets...)*`.

```markdown
**VPC Flow Logs Cost Estimation Report**

**Scope:** [Scope Name, e.g., Project 'my-project' or VPC 'my-vpc']

**Configuration:** Sampling [Sampling Rate]%, Metadata: [Yes/No]

**Summary:**
- **Total Monthly Logs:** [TOTAL_LOGS]
- **Total Monthly Data Volume:** [TOTAL_GB] GB
- **Estimated Monthly Cost:**
    - **Generation (Network Telemetry):** $[GEN_COST]
    - **Storage (Cloud Logging):** $[STORE_COST]
    - **Total List Price:** $[TOTAL_COST]

**Detailed Breakdown:**

### VPC: [VPC Name]
| Subnet Name | Region | Monthly Logs | Monthly Volume (GB) |
| :--- | :--- | :---: | :---: |
| [subnet-a] | [us-central1] | [L_eff formatted] | [V_subnet formatted to 4 decimals] |

*(Note: [N] other subnets in the '[VPC Name]' VPC showed no traffic during the analysis period.)*

---
**DISCLAIMER:** This is an estimation only.
1. **Unsupported Resources:** Interconnects and VPNs are excluded from this estimate.
2. **Aggregation:** This assumes the default 5s aggregation interval; volumes may vary with custom intervals.
3. **Pricing:** Estimates use standard list prices and do not include enterprise or committed use discounts.
4. **Analysis period:** Based on a 30-day analysis period.
```