From 07f3416493e37733075951a53b8ade7bd70bfe53 Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Mon, 6 Apr 2026 08:42:04 +0200 Subject: [PATCH] feat(mcp): Add resource events tool (#10412) --- .../basic-usage/prowler-mcp-tools.mdx | 4 +- mcp_server/CHANGELOG.md | 8 +++ .../prowler_app/models/resources.py | 45 ++++++++++++++ .../prowler_app/tools/resources.py | 60 +++++++++++++++++++ ui/CHANGELOG.md | 1 + ui/lib/lighthouse/workflow.ts | 1 + 6 files changed, 118 insertions(+), 1 deletion(-) diff --git a/docs/getting-started/basic-usage/prowler-mcp-tools.mdx b/docs/getting-started/basic-usage/prowler-mcp-tools.mdx index 43cbb12027..d80d8e511d 100644 --- a/docs/getting-started/basic-usage/prowler-mcp-tools.mdx +++ b/docs/getting-started/basic-usage/prowler-mcp-tools.mdx @@ -10,7 +10,7 @@ Complete reference guide for all tools available in the Prowler MCP Server. Tool |----------|------------|------------------------| | Prowler Hub | 10 tools | No | | Prowler Documentation | 2 tools | No | -| Prowler Cloud/App | 27 tools | Yes | +| Prowler Cloud/App | 29 tools | Yes | ## Tool Naming Convention @@ -60,6 +60,7 @@ Tools for searching, viewing, and analyzing cloud resources discovered by Prowle - **`prowler_app_list_resources`** - List and filter cloud resources with advanced filtering options (provider, region, service, resource type, tags) - **`prowler_app_get_resource`** - Get comprehensive details about a specific resource including configuration, metadata, and finding relationships +- **`prowler_app_get_resource_events`** - Get the timeline of cloud API actions performed on a resource (AWS CloudTrail). Shows who did what and when, with full request/response payloads - **`prowler_app_get_resources_overview`** - Get aggregate statistics about cloud resources as a markdown report ### Muting Management @@ -87,6 +88,7 @@ Tools for analyzing privilege escalation chains and security misconfigurations u - **`prowler_app_list_attack_paths_scans`** - List Attack Paths scans with filtering by provider, provider type, and scan state (available, scheduled, executing, completed, failed, cancelled) - **`prowler_app_list_attack_paths_queries`** - Discover available Attack Paths queries for a completed scan, including query names, descriptions, and required parameters - **`prowler_app_run_attack_paths_query`** - Execute an Attack Paths query against a completed scan and retrieve graph results with nodes (cloud resources, findings, virtual nodes) and relationships (access paths, role assumptions, security group memberships) +- **`prowler_app_get_attack_paths_cartography_schema`** - Retrieve the Cartography graph schema (node labels, relationships, properties) for writing accurate custom openCypher queries ### Compliance Management diff --git a/mcp_server/CHANGELOG.md b/mcp_server/CHANGELOG.md index 0a91ce06a7..09d8114196 100644 --- a/mcp_server/CHANGELOG.md +++ b/mcp_server/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to the **Prowler MCP Server** are documented in this file. +## [0.6.0] (Prowler UNRELEASED) + +### 🚀 Added + +- Resource events tool to get timeline for a resource (who, what, when) [(#10412)](https://github.com/prowler-cloud/prowler/pull/10412) + +--- + ## [0.5.0] (Prowler v5.21.0) ### 🚀 Added diff --git a/mcp_server/prowler_mcp_server/prowler_app/models/resources.py b/mcp_server/prowler_mcp_server/prowler_app/models/resources.py index 46d68555ea..823134794f 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/models/resources.py +++ b/mcp_server/prowler_mcp_server/prowler_app/models/resources.py @@ -135,3 +135,48 @@ class ResourcesMetadataResponse(BaseModel): regions=attributes.get("regions"), types=attributes.get("types"), ) + + +class ResourceEvent(MinimalSerializerMixin, BaseModel): + """A cloud API action performed on a resource. + + Sourced from cloud provider audit logs (AWS CloudTrail, Azure Activity Logs, + GCP Audit Logs, etc.). + """ + + id: str + event_time: str + event_name: str + event_source: str + actor: str + actor_uid: str | None = None + actor_type: str | None = None + source_ip_address: str | None = None + user_agent: str | None = None + request_data: dict | None = None + response_data: dict | None = None + error_code: str | None = None + error_message: str | None = None + + @classmethod + def from_api_response(cls, data: dict) -> "ResourceEvent": + """Transform JSON:API resource event response.""" + return cls(id=data["id"], **data.get("attributes", {})) + + +class ResourceEventsResponse(BaseModel): + """Response wrapper for resource events list.""" + + events: list[ResourceEvent] + total_events: int + + @classmethod + def from_api_response(cls, response: dict) -> "ResourceEventsResponse": + """Transform JSON:API response to events list.""" + data = response.get("data", []) + events = [ResourceEvent.from_api_response(item) for item in data] + + return cls( + events=events, + total_events=len(events), + ) diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/resources.py b/mcp_server/prowler_mcp_server/prowler_app/tools/resources.py index a6a2ff77ee..042232e6a5 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/resources.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/resources.py @@ -8,6 +8,7 @@ from typing import Any from prowler_mcp_server.prowler_app.models.resources import ( DetailedResource, + ResourceEventsResponse, ResourcesListResponse, ResourcesMetadataResponse, ) @@ -342,3 +343,62 @@ class ResourcesTools(BaseTool): report = "\n".join(report_lines) return {"report": report} + + async def get_resource_events( + self, + resource_id: str = Field( + description="Prowler's internal UUID (v4) for the resource. Use `prowler_app_list_resources` to find the right ID, or get it from a finding's resource relationship via `prowler_app_get_finding_details`." + ), + lookback_days: int = Field( + default=90, + ge=1, + le=90, + description="How many days back to search for events. Range: 1-90. Default: 90.", + ), + page_size: int = Field( + default=50, + ge=1, + le=50, + description="Number of events to return. Range: 1-50. Default: 50.", + ), + include_read_events: bool = Field( + default=False, + description="Include read-only API calls (e.g., Describe*, Get*, List*). Default: false (write/modify events only).", + ), + ) -> dict[str, Any]: + """Get the timeline of cloud API actions performed on a specific resource. + + IMPORTANT: Currently only available for AWS resources. Uses CloudTrail to retrieve + the modification history of a resource, showing who did what and when. + + Each event includes: + - What happened: event_name (e.g., PutBucketPolicy), event_source (e.g., s3.amazonaws.com) + - Who did it: actor, actor_type, actor_uid + - From where: source_ip_address, user_agent + - What changed: request_data, response_data (full API payloads) + - Errors: error_code, error_message (if the action failed) + + Use cases: + - Investigating security incidents (who modified this resource?) + - Change tracking and audit trails + - Understanding resource configuration drift + - Identifying unauthorized or unexpected modifications + + Workflows: + 1. Resource browsing: prowler_app_list_resources → find resource → this tool for event history + 2. Incident investigation: prowler_app_get_finding_details → get resource ID from finding → this tool to identify who caused the issue, what they changed, and when + """ + params = { + "lookback_days": lookback_days, + "page[size]": page_size, + "include_read_events": include_read_events, + } + + clean_params = self.api_client.build_filter_params(params) + + api_response = await self.api_client.get( + f"/resources/{resource_id}/events", params=clean_params + ) + events_response = ResourceEventsResponse.from_api_response(api_response) + + return events_response.model_dump() diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 62764e6b2a..e519db384a 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the **Prowler UI** are documented in this file. ### 🚀 Added - Findings grouped view with drill-down table showing resources per check, resource detail drawer, infinite scroll pagination, and bulk mute support [(#10425)](https://github.com/prowler-cloud/prowler/pull/10425) +- Resource events tool to Lighthouse AI [(#10412)](https://github.com/prowler-cloud/prowler/pull/10412) ### 🔄 Changed diff --git a/ui/lib/lighthouse/workflow.ts b/ui/lib/lighthouse/workflow.ts index e5811e976a..5a77702132 100644 --- a/ui/lib/lighthouse/workflow.ts +++ b/ui/lib/lighthouse/workflow.ts @@ -82,6 +82,7 @@ const ALLOWED_TOOLS = new Set([ // Resources "prowler_app_list_resources", "prowler_app_get_resource", + "prowler_app_get_resource_events", "prowler_app_get_resources_overview", // Attack Paths "prowler_app_list_attack_paths_queries",